Repository navigation
v0.1.2 — request builders and Canton-native retry
Additive (semver-compatible) API growth from external M1 review feedback:
request builders for the read streams, and Canton-native error classification.
Added
-
canton-ledger(request builders):UpdatesRequest,
ActiveContractsRequest, andCompletionsRequest(modulerequest,
re-exported at the root) open up the request surface the plain methods
hard-code — on every read path and both transports: gRPC
(updates_with,updates_resumable_with,updates_page_with,
active_contracts_with,active_contracts_page_with,
active_contracts_resumable_with,completions_with), JSON POST
(JsonClient::updates_with,active_contracts_with), and WebSocket
(ws_updates_with,ws_active_contracts_with,ws_completions_with):- bounded streams (
until(end_inclusive)) for catch-up/sync reads that
terminate at an offset instead of staying live; - template and interface filters (
for_templates/for_interfaces,
acceptingpackage:Module:Entityids with#package-namereferences)
instead of the wildcard filter; - transaction shape selection (
TransactionShape::AcsDelta/
LedgerEffects), created-event blobs, topology events, dropping
reassignments, and non-verbose records; UpdatesRequest::descending— bounded newest-first reads on the stream
and page paths, both transports (rejected up front on the resumable
stream, whose position tracking assumes ascending order);for_any_party(updates and ACS) — thefilters_for_any_party/
filtersForAnyPartyfull-ledger ingestion form, for tokens with
wildcard read authorization;CompletionsRequest::with_user_idto scope the completion stream to a
submitting user id (pairs withSubmit::with_user_id) — required for
tokens that do not carry a user id.
Defaults match the plain methods exactly (
updates_with(UpdatesRequest:: new(p, o))≡updates(p, o)), whose signatures are unchanged — the plain
methods now delegate to the builders, so there is a single body/request
producer per query on each transport. - bounded streams (
-
canton-ledger(submit):Submit::with_transaction_shapeselects the
shape of the transaction returned bysubmit_and_wait_for_transaction
(ledger effects — the default, as before — or ACS delta), removing the last
hard-codedTransactionShape. -
canton-ledger(submit, fullCommandssurface): every remaining
Commandsfield is now settable on both transports —
Submit/JsonCommandsgainwith_submission_id,add_disclosed_contract
(the explicit-disclosure counterpart to the created-event blobs the read
builders expose),with_package_id_selection_preference(the SCU upgrade
pin), andwith_min_ledger_time_abs/with_min_ledger_time_rel;Submit
additionally gainswith_prefetch_contract_keysandwith_taps_max_passes,
andJsonCommandsgainswith_deduplication_period(raw JSON, mirroring
Submit::with_deduplication_duration/_offset). -
canton-ledger(JSON retries):JsonClient::with_retry(RetryConfig)—
the same opt-in retry pipeline as the gRPC client (category-first
classification of the participant's error body, exponential backoff,
server-recommended delays honoured; de-duplication-safe for submits since
the command id stays fixed across attempts). -
canton-core(error classification): errors now expose the precise
retry semantics the Ledger API encodes, beyond the transport status code —
on both transports:ErrorCategory— Canton's error categories (from
ErrorInfo.metadata["category"]on gRPC statuses, or the
errorCategoryfield of JSON API error bodies) with the retryability the
error-code docs define; surfaced asError::category().Error::retry_delay()— the server-recommended pause, from the
google.rpc.RetryInfodetail (gRPC) or theretryInfofield (JSON).Error::correlation_id()— from thegoogle.rpc.RequestInfodetail
(gRPC) orcorrelationId/traceId(JSON), for quoting to the
participant operator.Error::is_retriableis now category-first for bothError::Status
andError::Http: the category's verdict wins over the gRPC/HTTP status
code (e.g. a category-12 "seek after ledger end" on HTTP 400 is
retryable; a category-10 "resource exists" onABORTEDis not), a bare
RetryInfocounts as retryable, and the previous code-based
classification remains as the fallback for non-Canton errors.
Behaviour change under opt-in retry: HTTP errors that Canton marks
retryable now retry where they previously failed fast — including the
413JSON_API_MAXIMUM_LIST_ELEMENTS_NUMBER_EXCEEDED(category 2 with a
1-secondretryInfo), even though shrinking the requestlimitis the
actual remedy. The SDK follows the server's verdict rather than
special-casing codes; callers that want to fail fast on it can match on
Error::Http { status: 413, .. }or handle it before retrying.retry::run_with_retryhonours the server'sretry_delaywhen it
exceeds the local backoff.
Fixed
canton-ledger(WebSocket error frames): aJsCantonErrorframe on a
WS stream is now surfaced asError::Http(with the gRPC code's canonical
HTTP status and the full error body), instead ofError::CommandRejected.
The frame is the same error object the JSON API returns in HTTP error
bodies, so it now carries itscategory()/retry_delay()/
correlation_id()— and, behaviour change,ws_updates_resumablenow
correctly reconnects on transient participant errors (categories 1/2/…),
which the never-retriableCommandRejectedmapping previously turned into
a dead stream.
All six crates release in lockstep at 0.1.2 (canton, canton-core, canton-proto, canton-auth, canton-ledger, canton-admin) — mix only equal versions.
cargo add canton@0.1.2