Rust SDK 0.5.0

Released .

Rust SDK 0.5.0 follows 0.4.2 with reusable finite writers and structured recovery information for failed writes. It also renames append outcomes and Catalog version fields. Rust 1.91.0 remains supported. For a new application, start with the Rust SDK guide.

What's new

  • Use Table::append_writer() to write a finite slice with bounded concurrency. Its report records request input ranges and outcomes, including the unsubmitted suffix after a failure.
  • Recover partial progress through Error: failed stream admission, finite writes, and stream delivery retain typed reports when propagated with ?.
  • Inspect AppendOutcome::{Succeeded, Failed, Ambiguous} and default to retries of validated HTTP 429 admission refusals. Ambiguous writes require reconciliation or explicit acceptance of duplicate-write risk.
  • Guard Catalog mutations with version and expected_version, and inspect catalog_outcome() after a failed mutation.
  • Resume statement tracking after a lost submission response using the ID retained in Error::statement_id().

Upgrade from 0.4

Update the dependency and commit Cargo.toml and Cargo.lock:

cargo add scopedb-client@0.5.0

Applications using 0.3 can upgrade directly to 0.5.0 by applying the 0.3-to-0.4 API migrations followed by the changes below.

Rename append outcomes and retry options

In 0.4In 0.5
AppendStateAppendOutcome
AppendState::CommittedAppendOutcome::Succeeded
AppendState::RejectedAppendOutcome::Failed
AppendState::UnknownAppendOutcome::Ambiguous
AppendDeliveryOutcome::OkAppendDeliveryOutcome::Succeeded
AppendDeliveryOutcome::UnknownAppendDeliveryOutcome::Ambiguous
AppendStreamBuilder::retry_unknown()AppendStreamBuilder::retry_ambiguous()
AppendDeliveryReport::unknown_rowsAppendDeliveryReport::ambiguous_rows
AppendDeliveryReport::unknown_batchesAppendDeliveryReport::ambiguous_batches
AppendStreamStats::unknown_rowsAppendStreamStats::ambiguous_rows

Succeeded confirms that all rows in the request committed. Failed means no rows took effect or can take effect later. Ambiguous means the request may have taken effect or may still take effect later. AppendOutcome preserves the serialized values committed, rejected, and unknown; its display text uses succeeded, failed, and ambiguous.

Use AppendRowsResult::status and Error::append_details().status to read the outcome. HTTP 200 with a valid, matching row count confirms success, including responses without a wire status field. Valid modern HTTP 4xx errors establish definite failure. HTTP 5xx, interrupted requests, and invalid responses leave the outcome ambiguous.

Only validated HTTP 429 admission refusals qualify for default automatic retries. Older HTTP 503 responses remain ambiguous even when diagnostics say rejected or retryable: true. .retry_ambiguous(true) opts into retrying transient ambiguous failures with possible duplicate rows. Client-side append timeouts are never retried automatically. Table::append continues to make one attempt.

Handle a failed request as a whole batch. Structured row diagnostics may be absent; use the typed outcome for recovery and retain the original input for reconciliation. A later definite failure leaves an earlier ambiguous attempt unresolved.

Rename Catalog version fields

In 0.4In 0.5
CatalogSnapshot::etagCatalogSnapshot::version
CatalogResult::etagCatalogResult::version
CatalogOptions::if_matchCatalogOptions::expected_version

Pass the opaque token unchanged from a read or dry-run result to expected_version. It covers the entire tenant catalog, so changes outside the selected resource can also invalidate it. HTTP 412 with code precondition_failed becomes ErrorKind::Conflict; read the resource again and revise the change. See manage table definitions for an example.

Replace checks for the client-generated catalog_commit_outcome_unknown code with Error::catalog_outcome(). CatalogMutationOutcome::Rejected establishes rejection; Unknown requires reading the resource before replaying the mutation. Catalog reads, dry runs, and local validation failures have no mutation outcome. code() retains the original server code and is absent for client-side failures.

Update error handling

ErrorKind identifies the failure category, while ErrorOperation identifies the SDK operation. Update enum matches and retry checks:

In 0.4In 0.5
ErrorKind::ConfigInvalidErrorKind::InvalidInput
ErrorKind::StatementCancelledErrorKind::Cancelled
AppendRowsFailed / CatalogFailedFailure category plus operation() and typed outcome
ErrorKind::StatementFailedFailure category plus statement_details()
ErrorKind::UnexpectedSpecific category such as InvalidResponse or Internal
is_temporary() / is_persistent()is_retryable() plus typed progress and outcomes
is_permanent()Failure category and is_retryable()
ErrorKind::into_static() / string conversionErrorKind::as_str()

is_retryable() describes whether repeating the same SDK call as-is is safe and useful. It returns false for uncertain writes and aggregate failures carrying partial-progress reports. Inspect retries() and retry_exhausted() on failed append requests to distinguish a retryable failure from an exhausted retry budget.

Error constructors, context mutation, and retry-state setters are internal. Represent application-specific failures with your own error type, retaining the SDK error as a source. SDK operations return Result<T, Error> and preserve their recovery data through ?.

Recover partial progress and submitted statements

Failed operationRecovery data
AppendStream::send_all()append_admission() records the admitted prefix
AppendWriter::write()append_write_report() and append_input_index()
AppendStream::flush() / shutdown()append_delivery_report() records the delivery interval
Statement submission or waitingstatement_id() identifies the existing execution

Rows already admitted to a stream remain owned by that stream. Observe delivery through flush() or shutdown() before replaying them. A failed delivery report includes committed, failed, ambiguous, and dropped row counts since the previous completed barrier; concurrent terminal waiters share the report. Finite-write reports retain input ranges and the unsubmitted suffix. See the Rust error-handling guide.

After a lost statement submission response or a later polling failure, use the retained ID with Client::statement_handle() to resume tracking. with_statement_id() still accepts an application-owned ID.

Review panic boundaries

Error, AppendLastFailure, AppendStreamStats, and AppendBatchFailureEvent no longer implement UnwindSafe or RefUnwindSafe. Review catch_unwind closures capturing these values. Keep errors outside the closure or capture owned diagnostic text where possible. If a closure must capture the error, review the state observable after a panic before choosing AssertUnwindSafe.