Repository navigation
Fix adapter issues found while documenting the billing adapters - #3
Open
saiyam1814 wants to merge 6 commits into
Open
saiyam1814 wants to merge 6 commits into
saiyam1814 wants to merge 6 commits into
Conversation
Automatic subscriptions refused such a plan with a retryable error, so the pipeline retried that tenant forever and held up Stripe delivery for every tenant. The error is now permanent: the tenant is logged as rejected, its customer and usage keep flowing, and everyone else is unaffected.
A rate card change created a contract on the new rate card and left the old one open, so usage was rated twice. vBilling now keeps one open contract per tenant: the new contract starts at UTC midnight and every other open vBilling contract of the tenant ends there, or is archived if it would not have started by then. Contracts vBilling did not create are never touched. Uniqueness keys carry the start date (vbilling:<rate card>@<date>:<tenant hash>), so a tenant can return to an earlier rate card; v0.2.0 keys are recognized and those contracts adopted. A tenant that loses its state adopts its open contract instead of creating another. With the Stripe link on, customers that vBilling did not create (found by alias or pinned by ID) now get the Stripe billing provider configuration when they have none. The new requests are validated against Metronome's published OpenAPI schemas, added to testdata.
Billing platforms report totals per tenant and metric, but a sku, region, project or cluster filter summed only the matching ledger events, so a tenant with two SKUs always mismatched. Filters now pick the tenant and metric pairs to compare, and each row covers all of that tenant's usage of the metric.
PUT /api/v1/billing-states/{tenant} returned 404 unless a Stripe or
Metronome webhook secret was set, so Lago and custom billing platforms
could not drive enforcement. The enforcer now always exists; webhooks
still need their own secrets.
- A webhook receiver that rejects the catalog event with 400, 413 or 422 no longer pauses usage delivery: the catalog is informational. - Offboarding records each destination's result: a permanent rejection is final, and destinations that succeeded are not called again while another one retries. - Lago treats 404 on terminating a subscription as already done, and its DELETE errors are classified like its other requests.
Stripe plans over 20 prices, Metronome contract handover and Stripe links, filtered reconciliation, and billing states without webhook secrets. Also corrects the gpu_profile example in a code comment.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #2, so the guides and the behavior they describe ship together. After #2 merges, this PR retargets to
main.Fixes
Stripe: a plan with more than 20 prices stalled all Stripe delivery.
Automatic subscriptions returned a retryable error, so the pipeline retried that tenant forever while every other tenant's usage waited. The error is now permanent: the tenant is logged as rejected, its customer and usage keep flowing, and nobody else is held up.
Metronome: a rate card change rated usage twice.
The new contract was created and the old one left open. vBilling now keeps one open contract per tenant:
/v1/contracts/updateEndDate)/v1/contracts/archive, finalized invoices kept)vbilling:<rate card>@<date>:<tenant hash>), so returning to an earlier rate card works; v0.2.0 keys are recognized and their contracts adopted/v2/contracts/list)Metronome: the Stripe link only applied to customers vBilling created.
Customers found by alias or pinned by ID now get the Stripe billing provider configuration when they have none (
/v1/getCustomerBillingProviderConfigurations,/v1/setCustomerBillingProviderConfigurations).Reconcile:
sku,region,projectandclusterfilters always mismatched.They summed only the matching ledger events, while billing platforms report totals per tenant and metric. Filters now pick the tenant and metric pairs to compare, and each row covers all of that tenant's usage of the metric.
Billing states needed a Stripe or Metronome webhook secret.
Without one,
PUT /api/v1/billing-states/{tenant}returned 404, so Lago and custom billing platforms couldn't drive enforcement. The enforcer now always exists; webhooks still need their own secrets.Rejections that can never succeed were retried forever:
Tests
New tests cover each fix: the 21-price plan, a permanently rejected tenant in the pipeline, the contract handover across days and on the same day, adopting legacy contracts (with pagination), linking existing customers, filtered reconcile, the rejected catalog, final offboarding, and the Lago 404.
go test -race ./...passes, andgo vetis clean. The reconcile test fails on the old code.The new Metronome requests are checked against request schemas taken from Metronome's published OpenAPI spec and added to
testdata. As before, they have not been run against a live Metronome account.Not changed
enforcemode still cannot hold tenant clusters with their own nodes (Private Nodes, Auto Nodes, Standalone). Their pods never reach the control plane cluster, and changing that needs write access inside each tenant cluster. It stays documented as a limit.CustomerResolveris still only consulted by the Stripe and Metronome webhooks, the only inbound billing signals. Other platforms can now use the billing-state API.🤖 Generated with Claude Code