Skip to content

Add MS Rust toolchain CI leg - #5002

Closed
Daniel Jurek (danieljurek) wants to merge 25 commits into
djurek/onboard-msrust-toolchain-basefrom
djurek/onboard-msrust-toolchain
Closed

Add MS Rust toolchain CI leg#5002
Daniel Jurek (danieljurek) wants to merge 25 commits into
djurek/onboard-msrust-toolchain-basefrom
djurek/onboard-msrust-toolchain

Conversation

@danieljurek

Copy link
Copy Markdown
Member

Adds an internal-only CI leg that builds and tests with the MS Rust toolchain
(ms-prod-1.95) from the ms-rust-tools feed, alongside the existing rustup
legs.

Note

Based on djurek/onboard-msrust-toolchain-base rather than main so the diff
shows only this work. That base is the rebased tip of the CFS work in #4928,
which this depends on for eng/templates/config.toml.template. Retarget to
main once #4928 merges.

Changes

  • eng/pipelines/templates/jobs/ci.tests.yml — new InstallMsRust
    parameter selecting between the MS Rust path (RustInstaller@1 +
    CargoAuthenticate@0 against the internal feed) and the existing
    use-rust.yml steps.
  • eng/pipelines/templates/stages/archetype-sdk-client.yml — adds the
    Linux-MSRust job for the internal project only.
  • eng/templates/rust-toolchain.toml.template — pins the MS Rust channel.
  • eng/scripts/shared/Cargo.ps1 — resolves the rustup executable from
    RUSTUP_EXE.

Notes on non-obvious bits

Four things here are load-bearing and not self-evident, each found by a failed
CI run:

  1. ci.tests.yml splices Matrix directly into $[ ... ] and
    ne(<Matrix>, '{}'), so it must be an expression fragment. A JSON literal
    makes the pipeline fail to compile, so it cannot even be queued. Hence
    format(...), with doubled braces and variables[...] so no nested macro
    expansion is needed.
  2. Matrix keys become job variables. That is how RUSTUP_EXE is set for this
    leg without touching ci.tests.yml.
  3. rust-std cannot appear in the template's components. msrustup resolves
    components as host components only and fails with
    US.host_component_not_found; the host std ships with the toolchain and
    other targets belong in targets. Plain rustup tolerates it, which is why
    the root rust-toolchain.toml still lists it.
  4. msrustup installs outside rustup's registry, so the image's rustup cannot
    resolve the custom ms-prod-1.95 channel and every rustup call from the
    repo root fails. Get-RustupExecutable coalesces $env:RUSTUP_EXE down to
    rustup, so existing legs are unaffected.

Validation

Build 6666539
(rust - canary) succeeded. Test Linux-MSRust reports:

> msrustup show active-toolchain
    Active Rust toolchain: 'ms-prod-1.95'

The nine existing legs still resolve through rustup across
linux/windows/macOS on 1.88/1.95/nightly, so there is no regression.

Heath Stewart (heaths) and others added 14 commits July 31, 2026 14:17
Use semantic APIView LineIds for items, impl blocks, and members so
unrelated insertions no longer churn review anchors between revisions.

Teach generate_api to resolve library-like Cargo targets and run cargo
rustdoc with --lib when needed, which restores APIView generation for
crates such as azure_data_cosmos_driver_native.

Update APIView and driver regressions to lock the new IDs, repeated
trait-impl member identities, and workspace rustdoc target selection.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1ffbadde-a9f2-4018-a562-e3d0550b8386

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1ffbadde-a9f2-4018-a562-e3d0550b8386
## Summary

Expands emulator test coverage for the Cosmos SDK toward parity with the
Python and .NET SDKs, addressing gaps called out in #3666. Two
non-overlapping additions, both test-only:

### Single-partition query feature coverage
`tests/emulator_tests/cosmos_query_features.rs` — 7 tests exercising the
query-language features that are servable within a single logical
partition (scoping every query to one partition makes it a "trivial"
operation the backend serves directly, avoiding the client-side
cross-partition merge the gateway pager does not implement for these):

- `COUNT`, `SUM`/`MIN`/`MAX`, and `AVG` aggregates
- `DISTINCT`
- `TOP` (cross-checked against `ORDER BY` + `LIMIT`)
- `OFFSET`/`LIMIT` windowing
- `GROUP BY` rollups

### Single-hash partition-key value-type coverage
`tests/emulator_tests/cosmos_partition_key_types.rs` — the suite
previously exercised single-hash partition keys almost exclusively with
*string* values; numeric and boolean values were only covered as
*components* of a hierarchical key. These 4 tests drive the full
point-operation lifecycle (create / read / replace / query / delete)
with top-level numeric, boolean, and float partition keys, and assert
that distinct scalar key values route to distinct logical partitions.

## Testing

All 11 new tests pass against the local Cosmos emulator. `cargo fmt` and
`cargo clippy --tests --all-features` are clean.

No CHANGELOG entry: these are test-only changes.

Part of #3666.

---------

Copilot-Session: 3d615f6f-b755-4fd9-96d5-bbdad261a2d2
## Summary

`ConsumerClient::close` and `ProducerClient::close` reported an error
when any other object still held the connection, and they skipped the
orderly teardown when they did. The most common cause is an
`EventReceiver` that the caller has not dropped. Both methods take
`self`, so the client was consumed anyway, which left the connection
with no owner. `EventProcessor::close` had the same fault for a
partition client, and it stopped before it closed the partition clients
that followed.

Closes #4931.

## Motivation

Each close path called `Arc::try_unwrap` on the shared object and turned
a failure into an error. `RecoverableConnection::close_connection` is
the only code that tears the connection down in an orderly way, and it
took `self` by value, which is why every caller needed exclusive
ownership.

The body of `close_connection` reads only through `&self`. Two methods
in the same file already work that way: `close_receiver` takes `self:
&Arc<Self>` and does a graceful per-receiver close, and
`apply_recovery_plan` takes `&self` and replaces every cache that
`close_connection` touches. The exclusive ownership was a choice in the
signature, not a constraint that the struct imposes.

The consequence was worse than an error return.
`RecoverableConnection::drop` only writes a trace message. One layer
down, `ConnectionHandle::drop` in `fe2o3-amqp` queues a close and does
not wait for the service to answer, so a dropped connection closes only
if the runtime still drains that channel. A close that reported this
error therefore skipped the orderly teardown and left the connection to
that best-effort path.

There was a second fault behind the first. `close_connection` left the
connection slot empty and recorded nothing, and `RecoverableConnection`
held no closed state, so a handle that outlived its client could reach
`ensure_connection` and open a new connection to the service after the
application closed the client.

No other Azure SDK for Event Hubs reports an error from close because
other references exist. The Go client closes the namespace, returns
`nil` on every path, and marks the namespace closed so that later
operations report `ErrClientClosed`. The Python client returns `None`
and the Java client returns `void`. The .NET client closes its transport
consumers, then closes the connection only when it owns it, and raises
only an exception that the teardown itself produced. The four clients
disagree about who owns the connection and agree that close always
proceeds.

## Changes

- `RecoverableConnection::close_connection` takes `&self`. The body does
not change.
- `RecoverableConnection` records the close in a new flag.
`ensure_connection` reads that flag under the lock on the connection and
reports an error instead of opening a new one. `close_connection` sets
the flag before it takes the same lock, so a caller that takes the lock
first has its connection torn down by the close that waits behind it,
and a caller that takes the lock afterwards sees the flag. Only
`close_connection` sets it, so connection recovery is unaffected.
- `ConsumerClient::close` and `ProducerClient::close` call
`close_connection` directly and report what it reports.
- `EventProcessor::close` reports a partition client that it cannot take
and continues, so one such client no longer stops it from closing the
partition clients that follow, and no longer stops it from closing the
connection.
- The note on `ProducerClient::close` said that dropping the client also
closes the connection. `Drop` cannot await, so the note is now accurate
about what dropping does.
- Three test-only helpers support the new processor test:
`RecoverableConnection::is_closed`, `ConsumerClient::new_unconnected`,
which builds a client without a connection to the service, and
`ConsumerClient::recoverable_connection`, which reads the connection
after `close` consumes the client. All three are `#[cfg(test)]`, so the
public API does not change.

This changes behavior. `close` no longer reports "multiple references
exist". A handle that outlives its client now reports that the client is
closed on its next call, where it opened a second connection before. No
test asserts the old error.

Two known limits stay, and both match what the code does today. A close
that races an attach holding a transient clone of the connection skips
the AMQP close and leaves that connection to the drop path.
`close_connection` does not raise the recovery generation, so an attach
that races a close can return one link that fails on its next use; it
cannot open a connection.

## Test plan

- `close_works_while_another_reference_exists` is a new unit test on the
connection. It holds a second reference, closes, and makes sure the
close succeeds and that the surviving reference cannot open a new
connection.
- `close_continues_past_a_retained_partition_client` is a new unit test
on the processor. It queues two partition clients, holds the first, and
closes the processor, then makes sure the second client closed and the
consumer connection closed. Against the previous code it fails with
"Partition client still has multiple references."
- `cargo test -p azure_messaging_eventhubs --lib`: 144 passed, 0 failed,
14 ignored.
- `cargo build -p azure_messaging_eventhubs --all-targets`, `cargo fmt
--check`, and `cargo clippy --all-targets --all-features` are clean.
- Validated live against an Event Hubs namespace, with the same test run
on this branch and on unmodified `main` as a control. The test opens a
consumer, opens a receiver on a partition, holds the receiver, and
closes the consumer.
- On `main`: `close` reported "Could not close consumer recoverable
connection, multiple references exist", which is the reported defect.
- On this branch: `close` succeeded, and the read that followed on the
surviving receiver reported "The client that owns this connection is
closed", so the receiver did not open a second connection.
- The live tests that close a receiver before the client keep working,
because that order was already correct.
## WS9: end-to-end validation for the Cosmos client-side observability
layer

This is the **WS9 end-to-end validation** for the Cosmos observability
layer merged in #4789 (the `DiagnosticsHandler` seam plus the built-in
metrics, distributed-tracing, and sampled-logging handlers). It adds the
tooling needed to run the layer under sustained load and confirm the
design goal: **quiet at steady state, rich on error.**

Everything here is a `publish = false` tooling crate. There are **no
product-code changes to the SDK**.

### What's included

**Soak/load harness** — new crate
`sdk/cosmos/azure_data_cosmos_observability_harness`

- Registers `CosmosMetricsHandler` + `CosmosTracingHandler` +
`SamplingLogHandler` via
`CosmosClientBuilder::with_diagnostics_handler`.
- Installs global OpenTelemetry meter + tracer providers with a
selectable exporter: **stdout** (default, no infra), **OTLP/gRPC**
(behind the opt-in `otlp` feature, rustls — no OpenSSL), or **none**;
sampled diagnostics logs surface through `tracing-subscriber`.
- Drives a configurable read/write/query mix across N workers for a set
duration at a target RPS, against the **Cosmos emulator** (default,
TLS-relaxed runtime) or a real account.
- Optional **fault injection** (probability, delay, error type, op
filter, and a mid-run fault *window*) exercises the failure/threshold
path so the "rich on error" behavior can be observed.
- Cargo features mirror the SDK's own (`metrics`, `distributed_tracing`,
`fault_injection`; all default-on) so the harness compiles the exact
code path it validates; `otlp` is opt-in because it drags in the gRPC
stack.
- Auth: account key, connection string, Entra ID via the developer-tools
credential chain, or **Kubernetes workload identity** for running in a
cluster.

### What moved out

An earlier revision of this PR also carried a Grafana dashboard, a local
`docker compose` stack, and a soak runbook under
`sdk/cosmos/azure_data_cosmos_benchmarks/`. Per review feedback
(@tvaron3) those are manual-testing infrastructure and don't belong in
the SDK repo, so they now live in the Cosmos team's internal tooling
repo, alongside the Azure deployment that runs this harness continuously
against a real account and publishes a persistent team dashboard.

The crate stays here because it path-depends on `azure_data_cosmos` and
can only build in this workspace — the same reason
`azure_data_cosmos_perf` lives here. The tooling repo's deploy script
assembles its build context from an SDK checkout, which is the split
`rust-perf` already uses.

`--auth workload-identity` is the one piece of that work that is a
genuine SDK change rather than infra, so it stayed: `--auth aad` uses
`DeveloperToolsCredential`, which resolves against a signed-in CLI
session and therefore cannot authenticate from a container.

### How to run

Emulator + stdout, no infrastructure at all:

```sh
cargo run -p azure_data_cosmos_observability_harness -- --duration-secs 60 --concurrency 8 --rps 200
```

Exercise the rich-on-error path:

```sh
cargo run -p azure_data_cosmos_observability_harness -- \
  --duration-secs 120 --concurrency 8 --rps 200 \
  --fault-probability 0.1 --fault-error too-many-requests --fault-delay-ms 50
```

Export to any OTLP/gRPC collector:

```sh
cargo run -p azure_data_cosmos_observability_harness --features otlp -- \
  --exporter otlp --otlp-endpoint http://localhost:4317 --duration-secs 3600
```

The crate README has the full flag set, the environment fallbacks, and a
minimal collector config for the OTLP path.

### Verification

- `cargo fmt`; `cargo clippy -p azure_data_cosmos_observability_harness
--all-features --all-targets` clean (this is what CI's `Build Analyze`
runs — an earlier revision only checked `--features otlp` and missed a
`clippy::large_futures` hit).
- `cargo build` on default features, `--all-features`, and
`--no-default-features`.
- `cargo test -p azure_data_cosmos_observability_harness --all-features`
— 13/13.
- Feature resolution verified with `cargo tree -e features -i tonic` /
`-i aws-lc-rs` across the default, `--features otlp`,
`--no-default-features --features otlp`, and `+
opentelemetry-otlp/tls-ring` builds, so enabling the exporter does not
lock consumers into a crypto provider.
- cSpell + markdownlint clean.
- Smoke-verified against running behavior: telemetry initializes, the
metrics histogram exports, steady-state success is quiet, and a failure
emits the full `DiagnosticsContext`.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7c387a4e-befb-4bcf-a800-bed57fec3b5c
The agentic triage workflow could not read triggering issues because the
MCP Gateway repository-visibility check calls `search_repositories`,
while the workflow exposed only issue and pull request tools. The failed
lookup caused public issues to be treated as private and emitted
incomplete-result reports.

- `.github/workflows/issue-triage.md`: enable the `repos` toolset and
document the gateway dependency.
- `.github/workflows/*.lock.yml` and `.github/aw/actions-lock.json`:
recompile all agentic workflows with gh-aw v0.84.3 so the shared action
pin stays consistent.

Fixes #4963

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2eb4ee47-e40e-46c4-8067-dd745b87a598
…4973)

Sync .github/workflows directory with azure-sdk-tools for PR
Azure/azure-sdk-tools#16649 See [eng/common
workflow](https://github.com/Azure/azure-sdk-tools/blob/main/eng/common/README.md#workflow)

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: danieljurek <2158838+danieljurek@users.noreply.github.com>
## Summary

Adds bounded cross-region hedging for the two Cosmos **metadata cache
reads** — Collection `Read` (container properties) and PartitionKeyRange
`ReadFeed` (routing map) — in `azure_data_cosmos_driver`. Ports the idea
behind the merged .NET PR
[Azure/azure-cosmos-dotnet-v3#5999](Azure/azure-cosmos-dotnet-v3#5999),
adapted to the Rust driver architecture.

## Why

When a region is slow (but not down), PPAF/PPCB don't trigger, so the
two lazy metadata reads on the cold/warm path suffer tail-latency spikes
— and they sit on the critical path of a client's first operation
against a container. Data-plane document reads already get cross-region
hedging in this driver; metadata reads did not. `HEDGING_SPEC.md`
already scoped these as "Phase 2".

## Approach

This **extends the driver's existing hedging engine** (the
`execute_hedged` race that data-plane reads already use), rather than
porting .NET's standalone `MetadataHedgingStrategy` — both metadata
reads already flow through the same `execute_operation_pipeline`.

- **Pair-gated eligibility** — replaced the cartesian
`HEDGEABLE_RESOURCE_TYPES × HEDGEABLE_OPERATION_TYPES` gate with a
single `HEDGEABLE_PAIRS` source of truth, so widening to metadata can't
also enable `(Document, ReadFeed)` document change-feed hedging.
- **Fixed 1.5 s metadata threshold** — metadata reads run with
`OperationOptions::default()`, so they use a fixed 1.5 s threshold
(matching .NET's control-plane threshold) instead of the data-plane
`min(1000ms, timeout/2)`.
- **Primary-authoritative tie-break** — for metadata, a hedge may win
only with a definitive **success**; a definitive error / regional
failure defers to the primary. Guards the replication-lag race where a
not-yet-consistent secondary returns `404`/`409` before a slow-but-good
primary. Data-plane hedging is unchanged (keeps first-`Final`-wins).
- **PartitionKeyRange continuation pinning** — the pkranges change-feed
continuation ETag is region-affine, so only the **cold first page** is
hedged; when the hedge wins, later pages are pinned to the winning
region via a new internal `OperationOverrides::pinned_endpoint` routing
override.

### Deliberate divergences from .NET (per `HEDGING_SPEC.md` §5.2)
- **Decoupled from PPAF** — reuses the existing `AvailabilityStrategy` /
`AZURE_COSMOS_HEDGING_ENABLED` control; no PPAF coupling and no new
`AZURE_COSMOS_METADATA_HEDGING_ENABLED` switch.
- Reuses `HedgeDiagnostics` — no new trace datum.

## Commits (each independently verified)

1. Pair-gate hedge eligibility for metadata reads
2. Fixed 1.5 s hedge threshold for metadata reads
3. Keep primary authoritative for metadata hedges (tie-break)
4. CHANGELOG
5. Defer PartitionKeyRange until the pin lands (kept the branch
merge-safe mid-development)
6. Add `pinned_endpoint` routing override (reusable primitive)
7. Hedge PartitionKeyRange reads with continuation pinning
8. In-memory-emulator metadata hedging integration tests

## Testing

- **Unit** — eligibility matrix (both metadata reads hedge; stray/write
pairs don't), the 1.5 s threshold, the primary-authoritative tie-break
(success wins / definitive-error defers / data-plane unchanged), and the
`pinned_endpoint` routing helper.
- **Integration** — deterministic in-memory-emulator tests (no live
account) that inject a region-targeted `ResponseDelay` on the Collection
`Read` metadata op: enabled + slow primary ⇒ hedged (alternate wins);
enabled + fast ⇒ primary wins pre-threshold; disabled ⇒ not hedged.
- Full driver lib suite green; `cargo clippy` + `cargo fmt` clean on the
changed code.

## Follow-ups (not blocking)

- `HEDGING_SPEC.md` Phase-2 write-up.
- A live multi-region gated integration test (the deterministic emulator
tests cover the logic today).
- Confirm the PPCB feedback sites stay data-plane-gated for metadata
(believed fine — metadata carries no partition key range id).

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7bd2d6d3-2f2b-4df1-88e9-976f95665284
Copilot-Session: dc253669-ba60-4540-9df1-8c7ba3949313
Copilot-Session: ac9ab8a2-54e7-464e-b6f4-078f60dac9cf
Copilot-Session: 49ca1a2f-4e01-44a7-a1a5-959602b42935
Copilot-Session: 2af76390-9049-48f0-89f2-51f754db60ba
…references (#4908)

CosmosOperation is moved and cloned throughout the driver pipeline
(planner, dataflow, retry), so its size and clone cost sit on the hot
path. The bulk of its 968 bytes came from CosmosResourceReference (640),
which embedded the account, database, and container references entirely
by value -- duplicating the 88-byte Url and the credential up to three
times per operation.

Hold AccountReference, DatabaseReference, ContainerReference, and
ItemReference behind an internal Arc<...Inner>. These types are
immutable after construction, so sharing is always safe, and because
every accessor already returned a borrow the change required no
call-site updates. Cloning an operation -- which the pipeline does on
every retry -- is now a few atomic increments instead of a deep copy of
a Url, a Secret, a Vec<Url>, and several strings. As a side effect
ContainerReference and ItemReference drop from three allocations to one.

Also collapse the mutually-exclusive database/container fields of
CosmosResourceReference into a single ResourceScope enum, enforcing in
the type system an invariant that was previously only convention.

Add a size_budgets test module pinning the hot-path model types, with
budgets set above current actuals so adding a field is not an automatic
failure but exceeding the budget is.

CosmosOperation 968 -> 392, CosmosResourceReference 640 -> 64, and the
four reference types 136/168/296/376 -> 8 each. No public API changes.
`Create-if-not-exists` and similar flows can intentionally treat non-2xx
service responses (for example, 409 Conflict) as successful control
flow. The Cosmos pipeline was emitting high-severity logs for these
outcomes, creating noisy `WARN`/`ERROR` output under normal usage.

- **Pipeline abort logging severity**
- Changed `operation_pipeline` abort-path logging from `tracing::error!`
to `tracing::debug!` for terminal operation outcomes that include typed
Cosmos HTTP status.

- **Hedged terminal HTTP outcome severity**
- Changed hedged terminal HTTP status logging
(`cosmos.hedge.terminal_http_error`) from `tracing::warn!` to
`tracing::debug!`.

- **Behavioral impact**
- Status/sub-status telemetry remains logged, but request-status
messages no longer surface as warn/error by default for user-handled
HTTP outcomes.

```rust
// before
tracing::error!(status = ?cosmos_status, "operation aborted");
tracing::warn!(http_status = u16::from(status.status_code()), "cosmos.hedge.terminal_http_error");

// after
tracing::debug!(status = ?cosmos_status, "operation aborted");
tracing::debug!(http_status = u16::from(status.status_code()), "cosmos.hedge.terminal_http_error");
```

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: analogrelay <7574+analogrelay@users.noreply.github.com>
Co-authored-by: Ashley Stanton-Nurse <ashleyst@microsoft.com>
## Summary

- add resumable cross-partition streaming `ORDER BY` execution
- preserve exact Cosmos value and RID ordering across pages and
partition splits, for scalar sort keys
- reject array/object sort keys with `400`/`20119`
`ClientOrderByComplexValueUnsupported`, matching Java, Python, and
JavaScript
- add a source-attributed cross-SDK scenario catalog and emulator/live
coverage

## Scope: complex sort keys

Ordering by a sort key that evaluates to a JSON array or object is
intentionally out of scope. The service persists such a value only as a
bounded 128-bit hash, which the client cannot recompute — so a
cross-partition merge cannot reproduce the service's order, and a
resumed continuation cannot tell whether a row was already returned.
Failing fast beats emitting an order we cannot guarantee, or silently
dropping and duplicating rows across a resume. Java, Python, and
JavaScript reject these queries for the same reason, so this is not a
limitation unique to Rust.

Queries scoped to a single logical partition are unaffected — the
service orders those, and the client never compares sort keys.

## Testing

- `cargo test -p azure_data_cosmos_driver --all-features`
- `cargo clippy -p azure_data_cosmos_driver --all-features --all-targets
-- -D warnings`
- `cargo clippy -p azure_data_cosmos --all-features --all-targets -- -D
warnings`
- PR cSpell check
- live Gateway ORDER BY query-plan parity
- live numeric/string ASC/DESC and mixed-direction resume across a real
1-to-2 partition split

Fixes #4756

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80371d09-63a0-4ebc-8bfc-6af45c217151
Sync eng/common directory with azure-sdk-tools for PR
Azure/azure-sdk-tools#16431 See [eng/common
workflow](https://github.com/Azure/azure-sdk-tools/blob/main/eng/common/README.md#workflow)

Co-authored-by: helen229 <gaoh@microsoft.com>
Runs Analyze-Code.ps1 with `-Audit` on a schedule and against pushes to
the `main` branch. This PR is primarily intended to run audit validation
which cannot run in the Azure DevOps pipelines.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 01e1ff18-2aaf-458b-89c0-8a17789ea7c4
The native C wrapper ( azure_data_cosmos_driver_native ) used to hand
back errors in two different shapes: a coarse, FFI-only enum
( cosmos_error_code_t , with its own banded numbering like  2404 ,
 3001 ) and the driver's own rich  (http_status, sub_status)  taxonomy.
That meant every language binding on top of the wrapper had to learn a
second, wrapper-specific error vocabulary and translate between the two.
This PR removes that split so there is one taxonomy everywhere.


• Every fallible C function now returns a single packed 32-bit status,
 cosmos_status_code_t , encoded as  (http_status << 16) | sub_status .
•  0  means success ( COSMOS_STATUS_SUCCESS ).
• A low-16-bit value of  0xFFFF  ( COSMOS_STATUS_NO_SUB_STATUS ) means
"no sub-status".
• Hosts decode with  http = code >> 16  and  sub = code & 0xFFFF .
• Service errors pass through verbatim as the driver's real  (http,
sub)  — no more lossy re-classification into a coarse band.
• Pure-FFI / pre-flight failures (a NULL pointer, bad UTF-8, a shut-down
queue, a panic, …) are no longer special: they now carry a real HTTP
status paired with a driver  CLIENT_FFI_*  sub-status, so they fit the
exact same integer as a wire error.
• The rich error struct was flattened and renamed to  cosmos_error_t 
( CosmosError  in Rust), carrying the packed status plus message,
activity id, session token, ETag, and backtrace inline. Free it with
 cosmos_error_free .

| Sub-status constant | Value | HTTP | Raised when |
| --- | --- | --- | --- |
| `CLIENT_FFI_NULL_ARGUMENT` | 20350 | 400 | A required pointer argument
was NULL |
| `CLIENT_FFI_INVALID_UTF8` | 20351 | 400 | A C string argument was not
valid UTF-8 |
| `CLIENT_FFI_INVALID_HEADER` | 20352 | 400 | A request header
name/value was non-ASCII/control |
| `CLIENT_FFI_INVALID_OPTION_VALUE` | 20353 | 400 | A builder setter got
an out-of-range value |
| `CLIENT_FFI_OPERATION_CONSUMED` | 20354 | 400 | An operation handle
was reused after a successful submit |
| `CLIENT_FFI_PRECONDITION_ALREADY_SET` | 20355 | 400 | A second
precondition was set on one operation |
| `CLIENT_FFI_UNSUPPORTED_OPERATION_FOR_MUTATOR` | 20356 | 400 | A
mutator was applied to an incompatible operation kind |
| `CLIENT_FFI_FEED_EXHAUSTED` | 20357 | 404 | A single-shot feed submit
had no further page |
| `CLIENT_FFI_QUEUE_SHUTDOWN` | 20358 | 503 | Submit targeted an already
shut-down completion queue |
| `CLIENT_FFI_QUEUE_FULL` | 20359 | 503 | Submit targeted a completion
queue at hard capacity |
| `CLIENT_FFI_OPERATION_CANCELLED` | 20360 | 408 | An operation was
cancelled before completing |
| `CLIENT_FFI_RUNTIME_BUILD_FAILED` | 20361 | 500 | The underlying
driver runtime could not be built |
| `CLIENT_FFI_PANIC` | 20362 | 500 | A spawned driver future panicked
(panic firewall) |
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
3 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Simon Moreno (simorenoh) and others added 11 commits August 6, 2026 16:18
)

This is the bottom of a 3-PR stack that re-lands the validated "address
Cosmos databases/containers by RID" change as small, reviewable slices.
With both downstream PRs merged into this one, it now holds the entirety
of the RID functionality for the the driver references + the wire
protocol for RID addressing, along with the public surface area from
slices 2 and 3.

- **`models/resource_reference.rs`** — `ContainerReference` becomes
RID-capable. New `new_by_rid` constructor and `base_path()` /
`is_by_rid()` accessors; `database_name()` and `name_based_path()` now
return `Option` (absent when the container was resolved purely by RID).
Equality/hash key on account + container RID so name- and RID-resolved
references for the same physical container collapse to one key.
- **`models/cosmos_resource_reference.rs`** — the raw-path /
lowercased-RID signing protocol: `compute_paths` raw-path handling,
`rid_signing_override`, `is_rid_addressed`,
`ResourcePaths::is_rid_based`, `encode_path_segments`, plus
`addressing_conflict` / `debug_assert_addressing_consistent`
(debug-only) and the full path/signing/round-trip unit tests.
- **`models/mod.rs`** — export `encode_path_segments` to the driver
crate.
- **`driver/pipeline/operation_pipeline.rs`** —
`build_transport_request` sends RID-based paths **raw** and
percent-encodes name-based paths (encoding the `=` padding of a base64
RID would make the gateway treat it as a name and reject the RID-based
signature).
- **`driver/routing/session_container.rs`** — session-token index keys
on `base_path()` so RID- and name-addressed containers index
consistently.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6963d41c-a1b9-489f-bd68-4dfa857d528b
Enable CFS for Rust pipelines. 

* Add CFSClean configuration 
* Write a `$CARGO_HOME/config.toml` file that uses the CFS feed instead
of crates.io
* Disable `-Audit` in analyze, this was moved to GitHub Actions in
#4972
* Set up nuget config to support azure-amqp 

## Other information 

Logs indicated that `static.rust-lang.org` might be blocked but it is
not actually blocked and so `rustup` works. However, anything that
attempts to contact `crates.io` (both resolve to the same IP) will be
blocked.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: danieljurek <2158838+danieljurek@users.noreply.github.com>
Copilot-Session: 45d0af54-5586-49dd-a9da-aabfe61403cc
Sync eng/common directory with azure-sdk-tools for PR
Azure/azure-sdk-tools#16662 See [eng/common
workflow](https://github.com/Azure/azure-sdk-tools/blob/main/eng/common/README.md#workflow)

Co-authored-by: Chidozie Ononiwu <chononiw@microsoft.com>
ci.tests.yml splices its Matrix parameter directly into a `$[ ... ]`
runtime expression and into `ne(<Matrix>, '{}')`. Passing a JSON object
literal produced invalid expression syntax and blocked the pipeline from
queueing at all.

Pass an expression fragment instead: `format()` builds the single-leg
matrix JSON at runtime, with LINUXVMIMAGE/LINUXPOOL resolved via
`variables[...]` so no nested macro expansion is required.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e0f28e95-2c6c-4e82-a025-b6a8dd2e1f3e
msrustup resolves `components` strictly as host components and fails with
US.host_component_not_found for 'rust-std', which it treats as a
target-scoped component instead. The host std library already ships with
the toolchain, so the entry was redundant as well as fatal.

The root rust-toolchain.toml keeps rust-std since plain rustup accepts it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e0f28e95-2c6c-4e82-a025-b6a8dd2e1f3e
msrustup installs MS Rust toolchains outside rustup's registry, so rustup
cannot resolve the custom 'ms-prod-1.95' channel from rust-toolchain.toml
and every rustup call from the repo root fails.

Let RUSTUP_EXE name the tool to query, defaulting to rustup so existing
jobs are unaffected, and set it to msrustup as a matrix variable on the
MS Rust leg. Matrix keys become job variables, so this needs no change to
ci.tests.yml.

Also skip msrustup's leading INFO lines when parsing the active toolchain,
and check for an empty result before trimming rather than after.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e0f28e95-2c6c-4e82-a025-b6a8dd2e1f3e
@danieljurek
Daniel Jurek (danieljurek) force-pushed the djurek/onboard-msrust-toolchain branch from 2c64af1 to dc2cb68 Compare August 7, 2026 04:22
@danieljurek

Copy link
Copy Markdown
Member Author

Superseded by #5020, which targets main directly now that #4928 has merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.