Concurrent billing-credit requests can attempt to initialize the same user balance at the same time. That can produce duplicate-key error spans and make the initial balance grant side effects harder to reason about. Worker parse jobs with insufficient credits also currently log an expected billing failure at error level, even though the job should fail normally with PAYMENT_REQUIRED.
Expected behavior
- First-use user balance initialization is idempotent under concurrent requests.
- The initial balance grant, transaction, and payment records are created once.
- The async API and sync worker billing paths use the same initialization behavior.
- Insufficient-credit parse failures still return
PAYMENT_REQUIRED, but the billing log is warning-level rather than error-level.
Acceptance criteria
- Concurrent
GET /billing/credits requests create only one balance/grant/payment set.
- Worker parse jobs with insufficient credits fail with
PAYMENT_REQUIRED without emitting error-level billing logs.
- Contract tests cover the observable API behavior and worker side effects.
Linked PR: #23
Concurrent billing-credit requests can attempt to initialize the same user balance at the same time. That can produce duplicate-key error spans and make the initial balance grant side effects harder to reason about. Worker parse jobs with insufficient credits also currently log an expected billing failure at error level, even though the job should fail normally with
PAYMENT_REQUIRED.Expected behavior
PAYMENT_REQUIRED, but the billing log is warning-level rather than error-level.Acceptance criteria
GET /billing/creditsrequests create only one balance/grant/payment set.PAYMENT_REQUIREDwithout emitting error-level billing logs.Linked PR: #23