Skip to content

fix(balanceworker): subject lookup#4356

Merged
tothandras merged 1 commit into
mainfrom
fix/balance-worker-subject-lookup
May 13, 2026
Merged

fix(balanceworker): subject lookup#4356
tothandras merged 1 commit into
mainfrom
fix/balance-worker-subject-lookup

Conversation

@tothandras
Copy link
Copy Markdown
Contributor

@tothandras tothandras commented May 13, 2026

failed to create entitlement delete snapshot event: failed to get customer and subject: failed to get subject: not found error: subject not found [namespace=xxx subject.key=xxx]

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced error handling to gracefully process snapshot events even when certain subject data is unavailable, improving system resilience and stability.

Review Change Stack

@tothandras tothandras requested a review from a team as a code owner May 13, 2026 09:18
@tothandras tothandras added the release-note/bug-fix Release note: Bug Fixes label May 13, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 13, 2026

📝 Walkthrough

Walkthrough

This PR makes the subject resolution flow more resilient by treating missing subjects defensively. When subjectService.GetByKey returns a not-found error, the code now creates a minimal synthetic subject.Subject that preserves the attribution key for downstream snapshot events instead of propagating the error.

Changes

Subject Resolution Error Handling

Layer / File(s) Summary
Synthetic subject fallback for not-found errors
openmeter/entitlement/balanceworker/subject_customer.go
When a subject lookup returns a generic-not-found error, resolveCustomerAndSubject returns a synthetic subject.Subject containing only the namespace and usage-attribution key. Other errors still propagate.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main fix: making subject lookup more defensive in the balance worker to handle missing subjects gracefully instead of failing.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/balance-worker-subject-lookup

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@turip turip requested a review from chrisgacsal May 13, 2026 09:19
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
openmeter/entitlement/balanceworker/subject_customer.go (2)

48-56: ⚖️ Poor tradeoff

Consider whether this fallback belongs in the subject service layer.

Right now, each caller of subjectService.GetByKey would need to implement this same fallback logic if they want to handle missing subjects gracefully. Moving this behavior into the subject service itself (or providing a GetByKeyOrSynthetic method) would centralize the logic and ensure consistency across the codebase.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openmeter/entitlement/balanceworker/subject_customer.go` around lines 48 -
56, The missing-subject fallback currently implemented at the call site
(checking models.IsGenericNotFoundError and returning a synthetic
*subject.Subject) should be moved into the subject service to centralize
behavior; either modify subjectService.GetByKey to return a synthetic subject
when not found or add a new helper like subjectService.GetByKeyOrSynthetic that
encapsulates the logic creating the synthetic subject (Namespace, Key) and
returns it instead of surfacing the not-found error, and update callers
(including the logic around *cus) to call the new/updated service method so they
no longer duplicate the models.IsGenericNotFoundError check.

48-56: ⚡ Quick win

Consider adding observability when falling back to synthetic subject.

The silent fallback makes it harder to monitor how often this scenario occurs or debug issues later. Adding a log or metric when creating the synthetic subject would help with visibility.

📊 Suggestion: Add logging for observability
 	if err != nil {
 		// Subjects are no longer persisted as their own entity, so a missing row is
 		// expected. Fall back to a synthetic subject carrying just the key so the
 		// snapshot event still reports the usage-attribution key downstream.
 		if models.IsGenericNotFoundError(err) {
+			// Log this fallback for monitoring/debugging
+			// (Adjust logger as appropriate for your codebase)
+			logger.Debug(ctx, "subject not found, using synthetic subject",
+				"namespace", namespace,
+				"key", subjKey,
+			)
 			return *cus, &subject.Subject{
 				Namespace: namespace,
 				Key:       subjKey,
 			}, nil
 		}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openmeter/entitlement/balanceworker/subject_customer.go` around lines 48 -
56, When models.IsGenericNotFoundError(err) triggers and you return the
synthetic subject, add an observability call (log and/or metric) inside that
branch to record the fallback occurrence; include identifying fields like
namespace, subjKey and the customer identifier from cus (e.g., cus.ID) and the
error string to aid debugging. Locate the branch around
models.IsGenericNotFoundError in subject_customer.go and emit the log/metric
before returning the synthetic subject (use the package's existing logger or
metrics client). Ensure the message is concise and structured (event name like
"synthetic_subject_fallback") and avoid exposing sensitive data.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@openmeter/entitlement/balanceworker/subject_customer.go`:
- Around line 48-56: The missing-subject fallback currently implemented at the
call site (checking models.IsGenericNotFoundError and returning a synthetic
*subject.Subject) should be moved into the subject service to centralize
behavior; either modify subjectService.GetByKey to return a synthetic subject
when not found or add a new helper like subjectService.GetByKeyOrSynthetic that
encapsulates the logic creating the synthetic subject (Namespace, Key) and
returns it instead of surfacing the not-found error, and update callers
(including the logic around *cus) to call the new/updated service method so they
no longer duplicate the models.IsGenericNotFoundError check.
- Around line 48-56: When models.IsGenericNotFoundError(err) triggers and you
return the synthetic subject, add an observability call (log and/or metric)
inside that branch to record the fallback occurrence; include identifying fields
like namespace, subjKey and the customer identifier from cus (e.g., cus.ID) and
the error string to aid debugging. Locate the branch around
models.IsGenericNotFoundError in subject_customer.go and emit the log/metric
before returning the synthetic subject (use the package's existing logger or
metrics client). Ensure the message is concise and structured (event name like
"synthetic_subject_fallback") and avoid exposing sensitive data.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6468276e-0f95-4749-a694-a5bca8598e24

📥 Commits

Reviewing files that changed from the base of the PR and between 968f4d1 and 768867d.

📒 Files selected for processing (1)
  • openmeter/entitlement/balanceworker/subject_customer.go

@tothandras tothandras merged commit 4655390 into main May 13, 2026
30 of 31 checks passed
@tothandras tothandras deleted the fix/balance-worker-subject-lookup branch May 13, 2026 09:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/bug-fix Release note: Bug Fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants