Repository navigation
Conversation
Kaiten now makes usage reports idempotent with a client key and keeps their history. - openapi/ is synced from kaitencloud/kaiten@ef755b4 (feat/billing) and the models regenerated; UsageReport.behavior is named UsageBehavior. - instances.report_usage(transaction_id=...): a keyed report is sent as idempotent, so it is retried like a read under the same key; a report without a key is still sent once. A malformed key raises ValueError before any request. - The usage endpoint's 409 is named by its code: TransactionIdReusedError (a ConflictError, never retried) or ThresholdExceededError. - instances.report_usage_detailed() returns UsageReportResult: usage, replayed (Idempotent-Replayed) and metadata_dropped (Kaiten-Metadata-Dropped). - An API without transaction_id refuses the field: the report is resent without it, and the client stops sending keys for its lifetime, logging once. - instances.list_usage_reports() walks the history by afterSeq, stops on a short page or at its limit, and raises PaginationError on a cursor that does not move. - instances.export_usage_reports() and export_organization_usage_reports() stream CSV or NDJSON into a binary destination through the new APIClient.stream_to, which retries only before the first byte. - unasync rewrites aread and aiter_* for the sync client. Signed-off-by: Tom Ribuot <[email protected]>
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.
What does this PR change?
The Python SDK's side of two Kaiten features: idempotent usage reports (
transactionId) and the usage history. Server side: kaitencloud/kaiten#16. The same features land in kaitencloud/sdk-go#1 and kaitencloud/sdk-js#2.instances.report_usage(..., transaction_id=...). A keyed report is sent as idempotent, so it is retried like a read (connection errors, 408, 429, 5xx), every attempt under the same key. A report without a key is still sent once. A malformed key raisesValueErrorbefore any request.TransactionIdReusedError(a newConflictError, never retried, original report inerrors[0].value) orThresholdExceededErroras before.instances.report_usage_detailed()returns aUsageReportResult:usage,replayed(Idempotent-Replayed) andmetadata_dropped(Kaiten-Metadata-Dropped).transactionIdrefuses the field. The report is resent without it, and the client stops sending keys (and retrying reports) for its lifetime, logging one warning on thekaitencloudlogger.instances.list_usage_reports()walks theafterSeqpages (from_,to,transaction_id,limit). It stops on a short page or at its limit, and raisesPaginationErrorif the cursor ever fails to advance.instances.export_usage_reports()andinstances.export_organization_usage_reports()stream CSV or NDJSON into a binary destination and return the bytes written.APIClient.stream_to, which retries only before the first byte.instance_slug,instance_id,entitlement_slugandentitlement_id; the IDs reach deleted ones.openapi/is synced from kaitencloud/kaiten@ef755b4 (feat/billing) and the models regenerated, withUsageReport.behaviornamedUsageBehavior.scripts/unasync.pynow rewritesareadandaiter_*for the sync client.Why?
A usage report whose response was lost could not be retried safely, because it might count twice. A key makes the retry safe. The history lets an application show and keep what was counted.
Testing
task checkpasses locally: generated code up to date, ruff, mypy, and 783 tests at 96 % coverage.tests/test_usage_reports.py, 19 tests:InvalidTransactionIdis not mistaken for it;afterSeq, the limit, and a cursor that doesn't advance;Checklist
CONTRIBUTING.md.Signed-off-byline.