Repository navigation
fix(credits): serialize expiration with current account usage - #8723
Conversation
The single-user and single-organization expiration writers now commit only while the persisted microdollars_used still matches the value the expiration amount was computed from. Otherwise they log the concurrency failure and return null, leaving the work to the next balance read, which recomputes from current values. Tests cover both the applied and the deferred write for each entity.
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Executive SummaryThe incremental merge replaces the snapshot-based expiration wrappers with the canonical Assumptions: Files Reviewed (25 files)
Previous Review Summaries (4 snapshots, latest commit b22bbb2)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit b22bbb2)Status: No Issues Found | Recommendation: Merge Executive SummaryThe incremental commit replaces the owner/organization-scoped Assumptions: Files Reviewed (4 files)
Previous review (commit c6bf63d)Status: No Issues Found | Recommendation: Merge Executive SummaryThe incremental commit rewrites the closure lookup in Assumptions: Files Reviewed (2 files)
Previous review (commit 35073eb)Status: No Issues Found | Recommendation: Merge Executive SummaryThe rewritten single-entity expiration writers ( Assumptions: Files Reviewed (16 files)
Previous review (commit da034a9)Status: No Issues Found | Recommendation: Merge Executive SummaryThe usage-snapshot guard added to both single-entity expiration writers is correct and well covered by the new applied/deferred tests for each entity; no defects found in the changed lines. Assumptions: Files Reviewed (3 files)
Reviewed by deepseek-flash-latest · Input: 160.7K · Output: 39.6K · Cached: 4.2M Review guidance: REVIEW.md from base branch |
|
bot: Holding this PR during the autonomous merge review. The credit-expiry guard has database-backed tests, but separate runtime evidence through the balance callers is not established. The do-not-merge label records this hold; no code defect is implied where the blocker is missing evidence. |
|
bot: Runtime evidence through the balance callers is now established, so this clears the evidence hold.
The checks used synthetic accounts and a disposable local PostgreSQL database. |
|
bot: The renewed performance hold is cleared after testing the canonical paid-credit integration on the current head.
Performance limit: large consumed-grant sets still cause owner-specific writer stalls. The canonical allocation calculation retains quadratic work. The PR description records this limit; isolated measurements do not establish production tail latency. No additional production setup is required. This clears the verification hold, not authorization to merge. |
Evidence
Evidence: demonstrated — an isolated local application and PostgreSQL run exercises personal and organization expiration through the balance callers and HTTP routes. Paid-request controls use a local fixture provider.
Change
Single-account expiration reads current primary account values under a row lock. Balance callers use the returned usage and acquired credits together. Explicit force checks retain their refresh behavior.
Expiration inserts use bounded batches. Baseline changes use a set-based update. Completed expiration checks return current account state without scanning the credit history again. Organization detail responses refresh the complete row.
Expiry calculations use the canonical paid-credit reconciler. Closure queries use bounded lookups through the unique original-transaction link.
Verification
Performance limits
Synthetic stress runs still show owner-specific writer stalls when many consumed grants expire together. The canonical allocation calculation retains quadratic work.
The closed-history query no longer depends on refreshed planner statistics. These isolated measurements do not establish production tail latency or workload frequency.
Production prerequisites
No schema migration, environment variable, secret, feature flag, or external service change is required.