Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR introduces an internal “backend dispatch” layer for azure-cosmos (sync + async) to allow selecting between the existing core-Python implementation and an opt-in Rust/PyO3-backed path, including per-request backend tagging in the User-Agent and a unit-test suite to pin down the wiring/selection rules.
Changes:
- Add sync/async backend abstractions, constants, and factories with selection precedence
_backendkwarg >COSMOS_BACKENDenv var > defaultcore-python. - Wire backend selection into
CosmosClient/async client construction, expose backend instances onclient_connection, and addcreate_itemdispatch + per-request backend stamping. - Extend
CosmosUserAgentPolicyto appendbackend=<name>and add fast unit tests (including an import-guard) to verify wiring and behavior.
Reviewed changes
Copilot reviewed 15 out of 17 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| sdk/cosmos/azure-cosmos/tests/test_backend_wiring_unit.py | New unit tests covering import-guard, backend selection precedence/validation, container dispatch behavior, and UA stamping. |
| sdk/cosmos/azure-cosmos/azure/cosmos/cosmos_client.py | Selects/initializes sync backend(s) at client construction and attaches them to client_connection. |
| sdk/cosmos/azure-cosmos/azure/cosmos/container.py | Adds sync create_item dispatch and stamps the chosen backend into per-request options. |
| sdk/cosmos/azure-cosmos/azure/cosmos/aio/_cosmos_client.py | Selects/initializes async backend(s) at client construction and attaches them to client_connection. |
| sdk/cosmos/azure-cosmos/azure/cosmos/aio/_container.py | Adds async create_item dispatch and stamps the chosen backend into per-request options. |
| sdk/cosmos/azure-cosmos/azure/cosmos/_user_agent_policy.py | Appends a backend=<name> token to the User-Agent based on per-request options. |
| sdk/cosmos/azure-cosmos/azure/cosmos/_backend/base.py | Defines the sync backend ABC and shared immutable request/response dataclasses. |
| sdk/cosmos/azure-cosmos/azure/cosmos/_backend/constants.py | Centralizes backend names, env var, and per-request option key. |
| sdk/cosmos/azure-cosmos/azure/cosmos/_backend/factory.py | Implements backend name resolution + sync backend instance factory. |
| sdk/cosmos/azure-cosmos/azure/cosmos/_backend/core_python.py | Sync “core-python” backend stub (returns None to fall through to existing path). |
| sdk/cosmos/azure-cosmos/azure/cosmos/_backend/rust.py | Sync Rust backend stub with guarded PyO3 import and loud NotImplementedError. |
| sdk/cosmos/azure-cosmos/azure/cosmos/aio/_backend/base.py | Defines the async backend ABC and re-exports shared dataclasses. |
| sdk/cosmos/azure-cosmos/azure/cosmos/aio/_backend/factory.py | Async backend factory mapping resolved backend name to async backend instance. |
| sdk/cosmos/azure-cosmos/azure/cosmos/aio/_backend/core_python.py | Async “core-python” backend stub (returns None to fall through). |
| sdk/cosmos/azure-cosmos/azure/cosmos/aio/_backend/rust.py | Async Rust backend stub with guarded PyO3 import and loud NotImplementedError. |
| sdk/cosmos/azure-cosmos/azure/cosmos/_backend/init.py | Backend package marker/export surface (no diff shown). |
| sdk/cosmos/azure-cosmos/azure/cosmos/aio/_backend/init.py | Async backend package marker/export surface (no diff shown). |
Comment on lines
+242
to
+252
| # Pick which backends this client will hold. Two attributes, named | ||
| # after the two backend types: | ||
| # - _core_python_backend: always present. The default, and the | ||
| # always-available path for any request whose kwargs the Rust | ||
| # backend doesn't support yet. | ||
| # - _rust_backend: present only when Rust is selected as default. | ||
| # Its presence (vs None) is the "Rust is default" signal — no | ||
| # extra attribute needed. | ||
| # Precedence for selection: kwarg `_backend=` > COSMOS_BACKEND env | ||
| # var > "core-python". | ||
| backend_choice = kwargs.pop("_backend", None) |
| self._rust_backend: Optional[RustBackend] = ( | ||
| chosen if isinstance(chosen, RustBackend) else None | ||
| ) | ||
| logging.getLogger(__name__).info( |
| self._rust_backend: Optional[AsyncRustBackend] = ( | ||
| chosen if isinstance(chosen, AsyncRustBackend) else None | ||
| ) | ||
| logging.getLogger(__name__).info( |
| backend = core_python_backend | ||
| if backend is not None: | ||
| # Stamp the backend that actually handled this call so the | ||
| # user-agent policy can append `; backend=<name>` per request. |
| backend = core_python_backend | ||
| if backend is not None: | ||
| # Stamp the backend that actually handled this call so the | ||
| # user-agent policy can append `; backend=<name>` per request. |
Comment on lines
+30
to
+37
| # Compose any per-request user-agent suffixes. Two sources today: | ||
| # 1. Cosmos feature flags derived from the global endpoint manager | ||
| # (existing behavior — circuit breaker, PPAF, etc.). | ||
| # 2. The backend that handled this request ("core-python" or "rust"), | ||
| # stamped per-request from the dispatch site so server-side | ||
| # logs reflect the path the call actually took even when a | ||
| # Rust-default client falls back to core-python for a single call. | ||
| suffix_parts = [] |
Comment on lines
+272
to
+277
| with pytest.raises(Exception): # FrozenInstanceError | ||
| setattr(p, "body_bytes", b"different") | ||
|
|
||
| r = BackendResponse(status_code=201) | ||
| with pytest.raises(Exception): | ||
| setattr(r, "status_code", 200) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Please add an informative description that covers that changes made by the pull request and link all relevant issues.
If an SDK is being regenerated based on a new API spec, a link to the pull request containing these API spec changes should be included above.
All SDK Contribution checklist:
General Guidelines and Best Practices
Testing Guidelines