Skip to content

v0.1.2 — request builders and Canton-native retry

Choose a tag to compare

@dmitryk-cf dmitryk-cf released this 05 Aug 18:50
· 156 commits to main since this release

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, and CompletionsRequest (module request,
    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,
      accepting package:Module:Entity ids with #package-name references)
      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) — the filters_for_any_party /
      filtersForAnyParty full-ledger ingestion form, for tokens with
      wildcard read authorization;
    • CompletionsRequest::with_user_id to scope the completion stream to a
      submitting user id (pairs with Submit::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.

  • canton-ledger (submit): Submit::with_transaction_shape selects the
    shape of the transaction returned by submit_and_wait_for_transaction
    (ledger effects — the default, as before — or ACS delta), removing the last
    hard-coded TransactionShape.

  • canton-ledger (submit, full Commands surface): every remaining
    Commands field is now settable on both transports —
    Submit/JsonCommands gain with_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), and with_min_ledger_time_abs/with_min_ledger_time_rel; Submit
    additionally gains with_prefetch_contract_keys and with_taps_max_passes,
    and JsonCommands gains with_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
      errorCategory field of JSON API error bodies) with the retryability the
      error-code docs define; surfaced as Error::category().
    • Error::retry_delay() — the server-recommended pause, from the
      google.rpc.RetryInfo detail (gRPC) or the retryInfo field (JSON).
    • Error::correlation_id() — from the google.rpc.RequestInfo detail
      (gRPC) or correlationId/traceId (JSON), for quoting to the
      participant operator.
    • Error::is_retriable is now category-first for both Error::Status
      and Error::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" on ABORTED is not), a bare
      RetryInfo counts 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
      413 JSON_API_MAXIMUM_LIST_ELEMENTS_NUMBER_EXCEEDED (category 2 with a
      1-second retryInfo), even though shrinking the request limit is 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_retry honours the server's retry_delay when it
      exceeds the local backoff.

Fixed

  • canton-ledger (WebSocket error frames): a JsCantonError frame on a
    WS stream is now surfaced as Error::Http (with the gRPC code's canonical
    HTTP status and the full error body), instead of Error::CommandRejected.
    The frame is the same error object the JSON API returns in HTTP error
    bodies, so it now carries its category()/retry_delay()/
    correlation_id() — and, behaviour change, ws_updates_resumable now
    correctly reconnects on transient participant errors (categories 1/2/…),
    which the never-retriable CommandRejected mapping 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