From 9ec9da08d66797c7f1db82774dab6b1162bfd578 Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Tue, 12 Aug 2025 09:09:58 +0200 Subject: [PATCH 1/3] fix: update DeletionEvent to retrieve MCPUsage before updating deletion timestamp --- VERSION | 2 +- internal/usage/tracking.go | 18 ++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/VERSION b/VERSION index 6088c2c..3802e7d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v0.0.13-dev \ No newline at end of file +v0.0.14 diff --git a/internal/usage/tracking.go b/internal/usage/tracking.go index 6237223..aa264c4 100644 --- a/internal/usage/tracking.go +++ b/internal/usage/tracking.go @@ -168,19 +168,17 @@ func (u *UsageTracker) DeletionEvent(ctx context.Context, project string, worksp return fmt.Errorf("error getting object key: %w", err) } - var mcpUsage = v1.MCPUsage{ - ObjectMeta: metav1.ObjectMeta{ - Name: objectKey.Name, - Namespace: objectKey.Namespace, - }, - Spec: v1.MCPUsageSpec{ - MCPDeletedAt: metav1.NewTime(time.Now().UTC()), - }, - } - err = u.client.Patch(ctx, &mcpUsage, client.Merge) + var mcpUsage v1.MCPUsage + err = u.client.Get(ctx, objectKey, &mcpUsage) if k8serrors.IsNotFound(err) { return nil } + if err != nil { + return fmt.Errorf("error getting MCPUsage resource: %w", err) + } + + mcpUsage.Spec.MCPDeletedAt = metav1.NewTime(time.Now().UTC()) + err = u.client.Update(ctx, &mcpUsage) if err != nil { return fmt.Errorf("error when setting deletion timestamp on MCPUsage element: %w", err) } From f4a1365b94771405b74c264d7634a6ed3b74eaa2 Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Tue, 12 Aug 2025 09:11:34 +0200 Subject: [PATCH 2/3] Update internal/usage/tracking.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- internal/usage/tracking.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/internal/usage/tracking.go b/internal/usage/tracking.go index aa264c4..e80a128 100644 --- a/internal/usage/tracking.go +++ b/internal/usage/tracking.go @@ -180,7 +180,24 @@ func (u *UsageTracker) DeletionEvent(ctx context.Context, project string, worksp mcpUsage.Spec.MCPDeletedAt = metav1.NewTime(time.Now().UTC()) err = u.client.Update(ctx, &mcpUsage) if err != nil { - return fmt.Errorf("error when setting deletion timestamp on MCPUsage element: %w", err) + err = retry.RetryOnConflict(retry.DefaultRetry, func() error { + // Re-fetch the latest version to avoid update conflicts + err := u.client.Get(ctx, objectKey, &mcpUsage) + if err != nil { + return fmt.Errorf("error getting MCPUsage resource during retry: %w", err) + } + mcpUsage.Spec.MCPDeletedAt = metav1.NewTime(time.Now().UTC()) + err = u.client.Update(ctx, &mcpUsage) + if err != nil { + if k8serrors.IsConflict(err) { + return err // trigger retry + } + return fmt.Errorf("error when setting deletion timestamp on MCPUsage element: %w", err) + } + return nil + }) + if err != nil { + return err } return nil From 92eab724647dd9679ec1c8e6a6c2ccf61c038e0e Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Tue, 12 Aug 2025 09:13:09 +0200 Subject: [PATCH 3/3] fix: streamline DeletionEvent to update MCPDeletedAt with retry logic --- internal/usage/tracking.go | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/internal/usage/tracking.go b/internal/usage/tracking.go index e80a128..913ceae 100644 --- a/internal/usage/tracking.go +++ b/internal/usage/tracking.go @@ -168,25 +168,15 @@ func (u *UsageTracker) DeletionEvent(ctx context.Context, project string, worksp return fmt.Errorf("error getting object key: %w", err) } - var mcpUsage v1.MCPUsage - err = u.client.Get(ctx, objectKey, &mcpUsage) - if k8serrors.IsNotFound(err) { - return nil - } - if err != nil { - return fmt.Errorf("error getting MCPUsage resource: %w", err) - } - - mcpUsage.Spec.MCPDeletedAt = metav1.NewTime(time.Now().UTC()) - err = u.client.Update(ctx, &mcpUsage) - if err != nil { + deletedAt := metav1.NewTime(time.Now().UTC()) err = retry.RetryOnConflict(retry.DefaultRetry, func() error { + var mcpUsage v1.MCPUsage // Re-fetch the latest version to avoid update conflicts err := u.client.Get(ctx, objectKey, &mcpUsage) if err != nil { return fmt.Errorf("error getting MCPUsage resource during retry: %w", err) } - mcpUsage.Spec.MCPDeletedAt = metav1.NewTime(time.Now().UTC()) + mcpUsage.Spec.MCPDeletedAt = deletedAt err = u.client.Update(ctx, &mcpUsage) if err != nil { if k8serrors.IsConflict(err) { @@ -196,6 +186,7 @@ func (u *UsageTracker) DeletionEvent(ctx context.Context, project string, worksp } return nil }) + if err != nil { return err }