Rust SDK 0.4.1

Released .

Rust SDK 0.4.1 follows 0.4.0 and consolidates its upgrade documentation. Applications already using 0.4.0 need no further API migration for this patch. For a new application, start with the Rust SDK guide.

What's new in 0.4

  • Append writes rows directly to a table, with batching, delivery reports, and explicit handling of uncertain outcomes.
  • Catalog operations read complete definitions and preview or apply replacements with ETag checks.
  • Statement handles expose complete snapshots, including progress, results, and errors.
  • Write attempts have configurable timeouts, and failures retain structured diagnostics.

These API changes were introduced in 0.4.0. The steps below apply when upgrading from 0.3.

Upgrade from 0.3

Update the dependency

Use Rust 1.91.0 or later, update the dependency, and commit the application's Cargo files:

cargo add scopedb-client@0.4.1

Replace Ingest with Append

Previous APIReplacement
Client::insertTable::append
Client::ingest_streamTable::append_stream
IngestStreamAppendStream
IngestStreamBuilderAppendStreamBuilder

Append takes rows that match an existing table; it does not take a ScopeQL transform. Move field conversion, filtering, and routing into the producer before sending. For transformations that need ScopeQL, use the separate HTTP ingestion workflow.

Handle append_stream().build() with ? because it validates configuration. Direct append() returns AppendRowsResult with num_rows_inserted; flush() and shutdown() return AppendDeliveryReport with committed_rows. In Continue mode, also inspect outcome, failed_rows, and unknown_rows.

Use batches no larger than 8 MiB and 200,000 rows. Streams default to four concurrent requests; use max_concurrent_batches(1) for sequential submission. Temporary rejections retry by default, but replay of unknown outcomes requires retry_unknown(true) and can duplicate rows. Direct append makes one attempt. Follow the current write example and delivery configuration.

Update Catalog calls

Replace paginated list and fetch calls with a resource selector followed by get(). Each read returns a complete definition and an etag. With catalog = client.catalog():

Previous operationReplacement
List databasescatalog.get().await
List schemas in a databasecatalog.database(db).get().await
List tables in a schemacatalog.schema(db, schema).get().await
describe() or table_schema()table.catalog().get().await
distinct_ondefinition.distinct.on
data_retention_daysdefinition.retention_days

Typed definitions reject unknown fields. Use raw().get() to retain them as JSON. For edits, read the complete definition, preview the replacement, and apply it with the preview's ETag. See manage table definitions for a complete example.

Update statement handling

Previous APIReplacement
with_exec_timeout(...)with_max_elapsed(Duration)
with_max_parallelism(...)Removed
handle.last_status()handle.snapshot()
handle.status().await / fetch_once().awaithandle.refresh().await
handle.fetch().awaithandle.wait().await
Cached progress and result accessorsInspect the complete snapshot

Use std::time::Duration instead of jiff::SignedDuration. with_max_elapsed includes queueing; with_max_estimated limits estimated duration and does not control parallelism. Both require positive durations.

cancel() now returns a complete StatementStatus. Inspect it because execution can race with cancellation. Failed states carry error instead of message; cancelled states have no message. After a query fails following submission, use error.statement_id() with client.statement_handle(id) to resume tracking rather than resubmitting the statement.

Review HTTP clients and timeouts

The SDK's reqwest re-export changes from 0.12 to 0.13. When supplying a custom HTTP client, use scopedb_client::reqwest and disable redirects and transport retries to prevent write replay:

use scopedb_client::reqwest;

let http_client = reqwest::Client::builder()
    .redirect(reqwest::redirect::Policy::none())
    .retry(reqwest::retry::never())
    .build()?;

Pass that client to Client::builder(endpoint).http_client(http_client). The SDK's default HTTP client already uses these policies.

Appends and Catalog mutations default to a 30-second timeout per attempt, including response-body reads. Configure ClientBuilder::write_timeout or AppendStreamBuilder::attempt_timeout with a finite, positive duration. A timed-out write can have committed; inspect write_details() and reconcile before replaying.

Rename remaining fields and methods

Previous APIReplacement
result.json_rows()result.raw_rows(), returning a slice
batch_bytestarget_batch_bytes
max_pending_bytesmax_buffered_bytes
max_in_flight_requestsmax_concurrent_batches
Append result/error append_statestatus
Separate last-failure message/statusstats().last_failure.error
u_intuint

AppendStreamStats no longer implements equality because failures retain their error sources. Table::identifier() includes the database and schema, using scopedb and public when omitted.