From 3463a0ba608d2e0f069d9a775cbc482e846e28fe Mon Sep 17 00:00:00 2001 From: tvaron3 Date: Mon, 28 Sep 2026 13:03:43 -0400 Subject: [PATCH 1/3] Link Cosmos changelog entries to PR 5366 Add PR references to the driver and macro release notes, and remove unnecessary blank lines from the changelog and generated Default template. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- sdk/cosmos/azure_data_cosmos_driver/CHANGELOG.md | 5 ++--- sdk/cosmos/azure_data_cosmos_macros/CHANGELOG.md | 2 +- sdk/cosmos/azure_data_cosmos_macros/src/lib.rs | 1 - 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/sdk/cosmos/azure_data_cosmos_driver/CHANGELOG.md b/sdk/cosmos/azure_data_cosmos_driver/CHANGELOG.md index c11cad34290..05bb0549bd7 100644 --- a/sdk/cosmos/azure_data_cosmos_driver/CHANGELOG.md +++ b/sdk/cosmos/azure_data_cosmos_driver/CHANGELOG.md @@ -28,9 +28,8 @@ ### Bugs Fixed -- Preserve admitted throttle retry settings during operation-triggered account metadata refresh, including regional and HTTP-version recovery paths. -- Honor per-operation endpoint unavailability TTL and runtime TTL updates during routing without changing sibling operations' cooldown intervals. - +- Preserve admitted throttle retry settings during operation-triggered account metadata refresh, including regional and HTTP-version recovery paths. ([#5366](https://github.com/Azure/azure-sdk-for-rust/pull/5366)) +- Honor per-operation endpoint unavailability TTL and runtime TTL updates during routing without changing sibling operations' cooldown intervals. ([#5366](https://github.com/Azure/azure-sdk-for-rust/pull/5366)) - Reconciled dataflow partition-range identity resolution across logical, EPK, sequential, and hedged requests, preserving split-parent session tokens on Gateway 2.0 while keeping logical partition-key wire routing unchanged, and enforcing the end-to-end timeout across planning and first-page execution. ([#5315](https://github.com/Azure/azure-sdk-for-rust/pull/5315)) - Container recreation now preserves collection RID mismatch errors during cold partition routing and rejects incompatible stale partition keys with a dedicated client substatus. ([#5324](https://github.com/Azure/azure-sdk-for-rust/pull/5324)) - Gateway 2.0 change feed requests now forward incremental-mode and wire-format-version metadata, so change feeds work over the thin-client transport. ([#5332](https://github.com/Azure/azure-sdk-for-rust/pull/5332)) diff --git a/sdk/cosmos/azure_data_cosmos_macros/CHANGELOG.md b/sdk/cosmos/azure_data_cosmos_macros/CHANGELOG.md index 06fce3b7421..b61c00e9187 100644 --- a/sdk/cosmos/azure_data_cosmos_macros/CHANGELOG.md +++ b/sdk/cosmos/azure_data_cosmos_macros/CHANGELOG.md @@ -4,7 +4,7 @@ ### Features Added -- Added `#[option(skip)]` for internal optional state excluded from configuration views and builder setters. +- Added `#[option(skip)]` for internal optional state excluded from configuration views and builder setters. ([#5366](https://github.com/Azure/azure-sdk-for-rust/pull/5366)) ### Breaking Changes diff --git a/sdk/cosmos/azure_data_cosmos_macros/src/lib.rs b/sdk/cosmos/azure_data_cosmos_macros/src/lib.rs index 8802d06b8cc..3775871f14d 100644 --- a/sdk/cosmos/azure_data_cosmos_macros/src/lib.rs +++ b/sdk/cosmos/azure_data_cosmos_macros/src/lib.rs @@ -131,7 +131,6 @@ fn generate_default(input: &OptionsInput) -> Result { Self { #(#fields),* } - } } }) From f93159e6fc9de3ce23b29fd75100100f6c6c54b7 Mon Sep 17 00:00:00 2001 From: tvaron3 Date: Tue, 29 Sep 2026 11:26:55 -0400 Subject: [PATCH 2/3] Remove native cancellation and address review Restore reserved cancellation outcomes and await driver completion instead of dropping in-flight work that can lose diagnostics. Remove the cancellation API and test, and regenerate the native header and API listing. Clarify tri-state and explicit-empty option encoding in op_request.rs and the README, and correct metadata-request argument indentation in cosmos_driver.rs. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../src/driver/cosmos_driver.rs | 4 +- .../azure_data_cosmos_driver_native/README.md | 9 +- .../azure_data_cosmos_driver_native/api.md | 5 - .../include/azurecosmosdriver.h | 18 ++-- .../src/completion.rs | 36 ++----- .../src/op_request.rs | 9 +- .../src/submit.rs | 97 +------------------ 7 files changed, 31 insertions(+), 147 deletions(-) diff --git a/sdk/cosmos/azure_data_cosmos_driver/src/driver/cosmos_driver.rs b/sdk/cosmos/azure_data_cosmos_driver/src/driver/cosmos_driver.rs index d843e864c34..9c860aaf4b7 100644 --- a/sdk/cosmos/azure_data_cosmos_driver/src/driver/cosmos_driver.rs +++ b/sdk/cosmos/azure_data_cosmos_driver/src/driver/cosmos_driver.rs @@ -6060,8 +6060,8 @@ mod tests { &user_agent, &client_id, false, - None, -) + None, + ) .await .expect_err( "503 ServiceUnavailable response with a non-empty JSON envelope must surface as an error", diff --git a/sdk/cosmos/azure_data_cosmos_driver_native/README.md b/sdk/cosmos/azure_data_cosmos_driver_native/README.md index d09d7f7875d..75bf8836e65 100644 --- a/sdk/cosmos/azure_data_cosmos_driver_native/README.md +++ b/sdk/cosmos/azure_data_cosmos_driver_native/README.md @@ -106,10 +106,11 @@ lookups and recreation refreshes. Cached references retain the credentials used to create them, so same-account clients on one runtime must use compatible credentials. Use separate runtimes when credential isolation is required. -`cosmos_operation_handle_cancel` requests cancellation for any submitted work. -Continue draining until its terminal completion before releasing the host cookie. -An already-ready result wins the cancellation race; otherwise pending work is -dropped before one CANCELLED completion is published, retaining patch tracking ID. +Host-requested cancellation is not supported: dropping an in-flight driver future +can discard its diagnostics. The CANCELLED outcome and handle-state values remain +reserved. Hosts must retain operation cookies and drain terminal completions even +if their own callers stop waiting. Admission deadlines remain enforced separately; +an admission timeout does not guarantee partial driver diagnostics. ### Commands diff --git a/sdk/cosmos/azure_data_cosmos_driver_native/api.md b/sdk/cosmos/azure_data_cosmos_driver_native/api.md index b0ca3c4279f..895579f8ec0 100644 --- a/sdk/cosmos/azure_data_cosmos_driver_native/api.md +++ b/sdk/cosmos/azure_data_cosmos_driver_native/api.md @@ -61,8 +61,6 @@ pub mod completion { #[no_mangle] pub extern "C" fn cosmos_completion_take_driver(c: *mut CosmosCompletion) -> *mut crate::driver::DriverHandle; #[no_mangle] - pub extern "C" fn cosmos_operation_handle_cancel(handle: *const OperationHandle); - #[no_mangle] pub extern "C" fn cosmos_operation_handle_free(op: *mut OperationHandle); #[no_mangle] pub extern "C" fn cosmos_operation_handle_state(op: *const OperationHandle) -> CosmosOperationHandleState; @@ -287,14 +285,12 @@ pub mod error { CosmosSubStatusClientQueryPlanInvalidTopOffsetLimit = 20114, CosmosSubStatusClientContinuationTokenNonQueryOperation = 20117, CosmosSubStatusClientDuplicateFaultInjectionRuleId = 20150, - CosmosSubStatusClientThroughputControlGroupNotRegistered = 20152, CosmosSubStatusClientHttpClientConstructionFailed = 20153, CosmosSubStatusClientReqwestFeatureRequired = 20154, CosmosSubStatusClientRequestUrlMissingHost = 20155, CosmosSubStatusClientRequestUrlMissingKnownPort = 20156, CosmosSubStatusClientImdsHttpClientConstructionFailed = 20157, CosmosSubStatusClientImdsReqwestFeatureRequired = 20158, - CosmosSubStatusClientPartitionKeyRangeCacheRequired = 20159, CosmosSubStatusClientContinuationTokenFetchInFlight = 20200, CosmosSubStatusClientTopologyProviderMissing = 20201, CosmosSubStatusClientDriverNotInitialized = 20202, @@ -452,7 +448,6 @@ pub mod op_request { pub max_session_retry_count: i64, pub end_to_end_timeout_ms: i64, pub endpoint_unavailability_ttl_ms: i64, - pub throughput_control_group: crate::string::CosmosStringView, pub excluded_regions: *const crate::string::CosmosStringView, pub excluded_regions_len: usize, pub custom_headers: *const CosmosHeaderKv, diff --git a/sdk/cosmos/azure_data_cosmos_driver_native/include/azurecosmosdriver.h b/sdk/cosmos/azure_data_cosmos_driver_native/include/azurecosmosdriver.h index c1b4aa4bd03..b5c677752ef 100644 --- a/sdk/cosmos/azure_data_cosmos_driver_native/include/azurecosmosdriver.h +++ b/sdk/cosmos/azure_data_cosmos_driver_native/include/azurecosmosdriver.h @@ -80,7 +80,9 @@ enum cosmos_completion_outcome_t */ COSMOS_COMPLETION_OUTCOME_ERROR = 1, /** - * Cancellation won before a terminal driver result was available. + * Reserved and unused. On-demand cancellation is not supported, so no + * operation produces this outcome. The value is kept fixed so it can be + * reused if cancellation is added in the future. */ COSMOS_COMPLETION_OUTCOME_CANCELLED = 2, /** @@ -253,7 +255,9 @@ enum cosmos_operation_handle_state_t */ COSMOS_OPERATION_HANDLE_STATE_FAILED = 2, /** - * A cancelled completion was posted after the pending future was dropped. + * Reserved and unused. No completion drives a handle into this state. + * The value is kept fixed so it can be reused if cancellation is added + * in the future. */ COSMOS_OPERATION_HANDLE_STATE_CANCELLED = 3, }; @@ -2093,14 +2097,6 @@ void cosmos_account_ref_free(struct cosmos_account_ref_t *account); */ void cosmos_bytes_free(struct cosmos_bytes_t bytes); -/** - * Requests cancellation without consuming the operation handle. - * - * NULL is a no-op. Keep the handle and host cookie alive until the terminal - * completion is drained; an already-ready driver result wins over cancellation. - */ -void cosmos_operation_handle_cancel(const struct cosmos_operation_handle_t *handle); - /** * Returns the effective PATCH tracking UUID carried by a completion. * @@ -2125,7 +2121,7 @@ struct cosmos_completion_queue_t *cosmos_completion_queue_create(const struct co * Does **not** block or wait for in-flight operations — it drops the * producer-side handle immediately. In-flight submissions keep the shared * queue state alive through their own `Arc`s and still run to completion - * unless explicitly cancelled, but once the handle is freed their completions, + * (there is no cancellation), but once the handle is freed their completions, * and the diagnostics they carry, can no longer be observed and are dropped * with any pending allocations. Hosts that must observe every completion first * call `cosmos_completion_queue_shutdown` and drain via diff --git a/sdk/cosmos/azure_data_cosmos_driver_native/src/completion.rs b/sdk/cosmos/azure_data_cosmos_driver_native/src/completion.rs index 4347828674a..f852e31a4e5 100644 --- a/sdk/cosmos/azure_data_cosmos_driver_native/src/completion.rs +++ b/sdk/cosmos/azure_data_cosmos_driver_native/src/completion.rs @@ -64,7 +64,9 @@ pub enum CosmosCompletionOutcome { /// message, …) are populated (message/detail only when the queue opted in /// via `include_error_details`). CosmosCompletionOutcomeError = 1, - /// Cancellation won before a terminal driver result was available. + /// Reserved and unused. On-demand cancellation is not supported, so no + /// operation produces this outcome. The value is kept fixed so it can be + /// reused if cancellation is added in the future. CosmosCompletionOutcomeCancelled = 2, /// Reserved sentinel for any non-zero outcome introduced after this spec. CosmosCompletionOutcomeUnknown = 255, @@ -84,7 +86,9 @@ pub enum CosmosOperationHandleState { CosmosOperationHandleStateCompleted = 1, /// Completion was posted with `outcome == CosmosCompletionOutcomeError`. CosmosOperationHandleStateFailed = 2, - /// A cancelled completion was posted after the pending future was dropped. + /// Reserved and unused. No completion drives a handle into this state. + /// The value is kept fixed so it can be reused if cancellation is added + /// in the future. CosmosOperationHandleStateCancelled = 3, } @@ -142,7 +146,6 @@ pub(crate) struct OperationInner { /// Lifecycle state — encoded as one of [`CosmosOperationHandleState`]. state: AtomicU8, patch_tracking_id: OnceLock, - cancellation: tokio::sync::Notify, } impl OperationInner { @@ -152,7 +155,6 @@ impl OperationInner { CosmosOperationHandleState::CosmosOperationHandleStateInFlight as u8, ), patch_tracking_id: OnceLock::new(), - cancellation: tokio::sync::Notify::new(), } } @@ -165,21 +167,6 @@ impl OperationInner { fn patch_tracking_id(&self) -> Option { self.patch_tracking_id.get().cloned() } - - pub(crate) async fn cancelled(&self) { - self.cancellation.notified().await; - } -} - -/// Requests cancellation without consuming the operation handle. -/// -/// NULL is a no-op. Keep the handle and host cookie alive until the terminal -/// completion is drained; an already-ready driver result wins over cancellation. -#[no_mangle] -pub extern "C" fn cosmos_operation_handle_cancel(handle: *const OperationHandle) { - if let Some(inner) = OperationHandle::inner_arc(handle) { - inner.cancellation.notify_one(); - } } /// The C ABI handle for an in-flight (or just-completed) operation @@ -582,15 +569,6 @@ impl PendingCompletion { p } - pub(crate) fn cancelled(user_data: isize, op_inner: Arc) -> Self { - Self::base( - CosmosCompletionOutcome::CosmosCompletionOutcomeCancelled, - CosmosErrorCode::CosmosErrorCodeOperationCancelled.as_status_code(), - user_data, - op_inner, - ) - } - /// Moves the owned allocations into a heap-stable backing box and returns /// the `#[repr(C)]` completion with borrowed pointers into it plus any /// owned side-payload handles. `op_inner` is dropped here (its terminal @@ -1012,7 +990,7 @@ pub extern "C" fn cosmos_completion_queue_create( /// Does **not** block or wait for in-flight operations — it drops the /// producer-side handle immediately. In-flight submissions keep the shared /// queue state alive through their own `Arc`s and still run to completion -/// unless explicitly cancelled, but once the handle is freed their completions, +/// (there is no cancellation), but once the handle is freed their completions, /// and the diagnostics they carry, can no longer be observed and are dropped /// with any pending allocations. Hosts that must observe every completion first /// call `cosmos_completion_queue_shutdown` and drain via diff --git a/sdk/cosmos/azure_data_cosmos_driver_native/src/op_request.rs b/sdk/cosmos/azure_data_cosmos_driver_native/src/op_request.rs index ee4d0a85a56..5aed28f06a6 100644 --- a/sdk/cosmos/azure_data_cosmos_driver_native/src/op_request.rs +++ b/sdk/cosmos/azure_data_cosmos_driver_native/src/op_request.rs @@ -72,13 +72,14 @@ use crate::partition_key::{CosmosPartitionKeyComponent, PartitionKeyHandle}; /// /// - **enum fields** (`*_strategy`, `content_response_on_write`): `0` = unset /// (inherit), any other value = the corresponding driver variant. -/// - **tri-state bools** (`session_capturing_disabled`): `0` = unset, -/// `1` = `false`, `2` = `true`. +/// - **tri-state bools** (`session_capturing_disabled`, `hedging_enabled`, +/// and binary-encoding flags): `0` = unset, `1` = `false`, `2` = `true`. /// - **i64 numeric fields** (retry counters/bucket): `< 0` = unset, /// `0..=u32::MAX` = the value; larger values are rejected. /// - **i64 duration fields** (`*_ms`): `< 0` = unset, `>= 0` = milliseconds. -/// - **string / array fields** (`excluded_regions`, `custom_headers`): -/// NULL / length `0` = unset. +/// - **array fields** (`excluded_regions`, `custom_headers`): NULL with length +/// `0` = unset (inherit); non-NULL with length `0` clears inherited values. +/// NULL with a nonzero length is invalid. /// /// It is a documentation marker only — the fields are plain integers / /// pointers so the struct stays `#[repr(C)]`. diff --git a/sdk/cosmos/azure_data_cosmos_driver_native/src/submit.rs b/sdk/cosmos/azure_data_cosmos_driver_native/src/submit.rs index 5c7f532fbcf..107de5dd71b 100644 --- a/sdk/cosmos/azure_data_cosmos_driver_native/src/submit.rs +++ b/sdk/cosmos/azure_data_cosmos_driver_native/src/submit.rs @@ -178,19 +178,12 @@ fn spawn_oneshot( // would stay `IN_FLIGHT` forever — the host continuation hangs and // leaks. Catching the panic here lets us still publish exactly one // completion, honoring the spec section 3.6 invariant. - let done = { - let work = std::panic::AssertUnwindSafe(async move { fut.await.map(to_success) }); - tokio::select! { - biased; - result = work.catch_unwind() => Some(result), - () = ctx.op_inner.cancelled() => None, - } - }; + let work = std::panic::AssertUnwindSafe(async move { fut.await.map(to_success) }); + let done = work.catch_unwind().await; let user_data = ctx.user_data.as_isize(); let completion = match done { - None => PendingCompletion::cancelled(user_data, ctx.op_inner.clone()), - Some(Ok(Ok(success))) => match success { + Ok(Ok(success)) => match success { SuccessKind::Response { response, next_continuation, @@ -207,13 +200,13 @@ fn spawn_oneshot( PendingCompletion::ok_container(user_data, ctx.op_inner.clone(), *container) } }, - Some(Ok(Err(err))) => PendingCompletion::error( + Ok(Err(err)) => PendingCompletion::error( user_data, ctx.op_inner.clone(), err, ctx.include_error_details, ), - Some(Err(panic_payload)) => { + Err(panic_payload) => { // The driver future (or success conversion) panicked. Synthesize // a driver error carrying the CLIENT_FFI_PANIC status and route // it through the normal rich-error path so the completion's @@ -876,84 +869,4 @@ mod tests { cosmos_completion_queue_free(queue); cosmos_runtime_free(rt); } - - #[test] - fn cancellation_drops_pending_work_but_ready_results_win() { - use crate::completion::{ - cosmos_completion_patch_tracking_id, cosmos_completion_queue_create, - cosmos_completion_queue_free, cosmos_completion_queue_free_completions, - cosmos_completion_queue_wait, cosmos_operation_handle_cancel, - cosmos_operation_handle_free, CosmosCompletion, CosmosCompletionOutcome, - }; - use crate::runtime::{__test_only_create_default_runtime, cosmos_runtime_free}; - use std::{ - mem::MaybeUninit, - sync::atomic::{AtomicBool, Ordering}, - }; - - struct DropSignal(Arc); - impl Drop for DropSignal { - fn drop(&mut self) { - self.0.store(true, Ordering::SeqCst); - } - } - let runtime = __test_only_create_default_runtime(); - let queue = cosmos_completion_queue_create(runtime, std::ptr::null()); - for ready in [false, true] { - let dropped = Arc::new(AtomicBool::new(false)); - let guard = DropSignal(Arc::clone(&dropped)); - let (ctx, handle) = pre_flight_spawn(queue, 42).unwrap(); - ctx.op_inner - .set_patch_tracking_id("7f5241c9-d7c2-4071-97a3-43bdebf6ef8f".into()); - let runtime = Arc::clone(ctx.queue.runtime()); - cosmos_operation_handle_cancel(handle); - cosmos_operation_handle_cancel(handle); - spawn_oneshot( - ctx, - runtime, - async move { - let _guard = guard; - if !ready { - futures::future::pending::<()>().await; - } - Ok(()) - }, - |()| SuccessKind::Response { - response: None, - next_continuation: None, - }, - ); - let mut slot = MaybeUninit::::uninit(); - assert_eq!( - cosmos_completion_queue_wait(queue, slot.as_mut_ptr(), 1, 5000), - 1 - ); - // SAFETY: wait wrote exactly one initialized completion. - let mut completion = unsafe { slot.assume_init() }; - assert!( - dropped.load(Ordering::SeqCst), - "work is quiescent before delivery" - ); - assert_eq!(completion.user_data, 42); - assert_eq!( - completion.outcome, - if ready { - CosmosCompletionOutcome::CosmosCompletionOutcomeOk - } else { - CosmosCompletionOutcome::CosmosCompletionOutcomeCancelled - } - ); - assert!(!cosmos_completion_patch_tracking_id(&completion).is_null()); - cosmos_operation_handle_cancel(handle); - let mut slot = MaybeUninit::::uninit(); - assert_eq!( - cosmos_completion_queue_wait(queue, slot.as_mut_ptr(), 1, 0), - 0 - ); - cosmos_completion_queue_free_completions(&mut completion, 1); - cosmos_operation_handle_free(handle); - } - cosmos_completion_queue_free(queue); - cosmos_runtime_free(runtime); - } } From 018dc11f9df2a42142089e74a10b2a81379667d8 Mon Sep 17 00:00:00 2001 From: Ananth Mudumba Date: Wed, 30 Sep 2026 11:08:27 -0700 Subject: [PATCH 3/3] Add native 0.2.0 changelog Start maintained native release history at 0.2.0 and document the operation-options ABI additions and pre-1.0 compatibility boundary. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: dc991c8a-81db-439a-a4e2-03b45107a0c5 --- .../CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 sdk/cosmos/azure_data_cosmos_driver_native/CHANGELOG.md diff --git a/sdk/cosmos/azure_data_cosmos_driver_native/CHANGELOG.md b/sdk/cosmos/azure_data_cosmos_driver_native/CHANGELOG.md new file mode 100644 index 00000000000..d7f3abeeae4 --- /dev/null +++ b/sdk/cosmos/azure_data_cosmos_driver_native/CHANGELOG.md @@ -0,0 +1,17 @@ +# Release History + +## 0.2.0 (Unreleased) + +### Features Added + +- Added runtime, client, and request operation options to the native C FFI, including immutable admission snapshots for operation submission. ([#5366](https://github.com/Azure/azure-sdk-for-rust/pull/5366)) + +### Breaking Changes + +- Changed the pre-1.0 operation-options and request ABI layouts, including 64-bit retry-count fields; hosts using the 0.1.0 bootstrap ABI must rebuild for 0.2.0. ([#5366](https://github.com/Azure/azure-sdk-for-rust/pull/5366)) + +### Bugs Fixed + +### Other Changes + +- Began maintained native release history at 0.2.0; earlier 0.1.0 development is treated as the bootstrap baseline.