From 684ae5e90968f1ac151eaeedf4a40aadb6364890 Mon Sep 17 00:00:00 2001 From: Andrew Mathew Date: Mon, 10 Nov 2025 11:34:40 -0800 Subject: [PATCH 1/9] Added priority level for clients --- .../azure/cosmos/_cosmos_client_connection.py | 4 ++ .../aio/_cosmos_client_connection_async.py | 4 ++ sdk/cosmos/azure-cosmos/samples/examples.py | 59 +++++++++++++++++ .../azure-cosmos/samples/examples_async.py | 64 +++++++++++++++++++ sdk/cosmos/azure-cosmos/tests/test_headers.py | 30 +++++++++ .../azure-cosmos/tests/test_headers_async.py | 30 +++++++++ 6 files changed, 191 insertions(+) diff --git a/sdk/cosmos/azure-cosmos/azure/cosmos/_cosmos_client_connection.py b/sdk/cosmos/azure-cosmos/azure/cosmos/_cosmos_client_connection.py index dd9479280a34..37cfe815d522 100644 --- a/sdk/cosmos/azure-cosmos/azure/cosmos/_cosmos_client_connection.py +++ b/sdk/cosmos/azure-cosmos/azure/cosmos/_cosmos_client_connection.py @@ -165,6 +165,10 @@ def __init__( # pylint: disable=too-many-statements if throughput_bucket: self.default_headers[http_constants.HttpHeaders.ThroughputBucket] = throughput_bucket + priority_level = kwargs.pop('priority_level', None) + if priority_level: + self.default_headers[http_constants.HttpHeaders.PriorityLevel] = priority_level + # Keeps the latest response headers from the server. self.last_response_headers: CaseInsensitiveDict = CaseInsensitiveDict() diff --git a/sdk/cosmos/azure-cosmos/azure/cosmos/aio/_cosmos_client_connection_async.py b/sdk/cosmos/azure-cosmos/azure/cosmos/aio/_cosmos_client_connection_async.py index 80f031f1c292..5fb40b7a5d79 100644 --- a/sdk/cosmos/azure-cosmos/azure/cosmos/aio/_cosmos_client_connection_async.py +++ b/sdk/cosmos/azure-cosmos/azure/cosmos/aio/_cosmos_client_connection_async.py @@ -167,6 +167,10 @@ def __init__( # pylint: disable=too-many-statements if throughput_bucket: self.default_headers[http_constants.HttpHeaders.ThroughputBucket] = throughput_bucket + priority_level = kwargs.pop('priority_level', None) + if priority_level: + self.default_headers[http_constants.HttpHeaders.PriorityLevel] = priority_level + if consistency_level is not None: self.default_headers[http_constants.HttpHeaders.ConsistencyLevel] = consistency_level diff --git a/sdk/cosmos/azure-cosmos/samples/examples.py b/sdk/cosmos/azure-cosmos/samples/examples.py index 675e279c9007..041fc3958b3a 100644 --- a/sdk/cosmos/azure-cosmos/samples/examples.py +++ b/sdk/cosmos/azure-cosmos/samples/examples.py @@ -126,6 +126,65 @@ # [END priority_level option] +# [START client_level_priority] +# Priority can also be set at the client level, which will apply to all requests made by that client. +# This is useful when you want all operations from a particular client to have the same priority. +# The client-level priority is set during client initialization with the `priority_level` parameter. + +# Create a client with Low priority for all requests +low_priority_client = CosmosClient(url, key, priority_level="Low") +low_priority_database = low_priority_client.get_database_client(database_name) +low_priority_container = low_priority_database.get_container_client(container_name) + +# Add some items to query +for i in range(1, 4): + low_priority_container.upsert_item( + dict(id="low_priority_item{}".format(i), productName="Widget", productModel="Model {}".format(i)) + ) + +# All requests from this client will have Low priority by default +for item in low_priority_container.query_items( + query='SELECT * FROM products p WHERE p.productName = "Widget"', + enable_cross_partition_query=True +): + print(json.dumps(item, indent=True)) + +# [END client_level_priority] + +# [START request_priority_precedence] +# Request-level priority takes precedence over client-level priority. +# This allows you to override the default priority for specific operations. + +# Create a client with Low priority +client_with_default_priority = CosmosClient(url, key, priority_level="Low") +database_with_priority = client_with_default_priority.get_database_client(database_name) +container_with_priority = database_with_priority.get_container_client(container_name) + +# Add items with different priority levels to the container +container_with_priority.upsert_item( + dict(id="urgent_item1", productName="Widget", priority="urgent", productModel="Urgent Model") +) +container_with_priority.upsert_item( + dict(id="normal_item1", productName="Widget", priority="normal", productModel="Normal Model") +) + +# This query will use High priority, overriding the client's Low priority setting +for important_item in container_with_priority.query_items( + query='SELECT * FROM products p WHERE p.priority = "urgent"', + enable_cross_partition_query=True, + priority="High" # Request-level priority overrides client-level priority +): + print(json.dumps(important_item, indent=True)) + +# This query will use the client's default Low priority +for normal_item in container_with_priority.query_items( + query='SELECT * FROM products p WHERE p.priority = "normal"', + enable_cross_partition_query=True +): + print(json.dumps(normal_item, indent=True)) + +# [END request_priority_precedence] + # Delete items from the container. # The Cosmos DB SQL API does not support 'DELETE' queries, # so deletes must be done with the delete_item method diff --git a/sdk/cosmos/azure-cosmos/samples/examples_async.py b/sdk/cosmos/azure-cosmos/samples/examples_async.py index 87751c2b4295..12643daeb1d9 100644 --- a/sdk/cosmos/azure-cosmos/samples/examples_async.py +++ b/sdk/cosmos/azure-cosmos/samples/examples_async.py @@ -122,12 +122,76 @@ async def examples_async(): # then Azure Cosmos DB will throttle low priority requests to allow high priority requests to execute. # Can be used for Read, Write, and Query operations. This is specified with the `priority` keyword. # the value can either be low or high. + + # Ensure we have items to query (this reuses items from earlier in the example) + # If running this section independently, uncomment the lines below: + # for i in range(1, 10): + # await container.upsert_item( + # dict(id="item{}".format(i), productName="Widget", productModel="Model {}".format(i)) + # ) + async for queried_item in container.query_items( query='SELECT * FROM products p WHERE p.productModel <> "DISCONTINUED"', priority="High" ): print(json.dumps(queried_item, indent=True)) # [END priority_level option] + # [START client_level_priority] + # Priority can also be set at the client level, which will apply to all requests made by that client. + # This is useful when you want all operations from a particular client to have the same priority. + # The client-level priority is set during client initialization with the `priority_level` parameter. + + # Create a client with Low priority for all requests + async with CosmosClient(url, key, priority_level="Low") as low_priority_client: + low_priority_database = low_priority_client.get_database_client(database_name) + low_priority_container = low_priority_database.get_container_client(container_name) + + # Add some items to query + for i in range(1, 4): + await low_priority_container.upsert_item( + dict(id="low_priority_item{}".format(i), productName="Widget", productModel="Model {}".format(i)) + ) + + # All requests from this client will have Low priority by default + async for item in low_priority_container.query_items( + query='SELECT * FROM products p WHERE p.productName = "Widget"' + ): + print(json.dumps(item, indent=True)) + + # [END client_level_priority] + + # [START request_priority_precedence] + # Request-level priority takes precedence over client-level priority. + # This allows you to override the default priority for specific operations. + + # Create a client with Low priority + async with CosmosClient(url, key, priority_level="Low") as client_with_default_priority: + database_with_priority = client_with_default_priority.get_database_client(database_name) + container_with_priority = database_with_priority.get_container_client(container_name) + + # Add items with different priority levels to the container + await container_with_priority.upsert_item( + dict(id="urgent_item1", productName="Widget", priority="urgent", productModel="Urgent Model") + ) + await container_with_priority.upsert_item( + dict(id="normal_item1", productName="Widget", priority="normal", productModel="Normal Model") + ) + + # This query will use High priority, overriding the client's Low priority setting + async for important_item in container_with_priority.query_items( + query='SELECT * FROM products p WHERE p.priority = "urgent"', + priority="High" # Request-level priority overrides client-level priority + ): + print(json.dumps(important_item, indent=True)) + + # This query will use the client's default Low priority + async for normal_item in container_with_priority.query_items( + query='SELECT * FROM products p WHERE p.priority = "normal"' + ): + print(json.dumps(normal_item, indent=True)) + + # [END request_priority_precedence] + # Delete items from the container. # The Cosmos DB SQL API does not support 'DELETE' queries, # so deletes must be done with the delete_item method diff --git a/sdk/cosmos/azure-cosmos/tests/test_headers.py b/sdk/cosmos/azure-cosmos/tests/test_headers.py index 8d0673f0f446..228a7cd61c9c 100644 --- a/sdk/cosmos/azure-cosmos/tests/test_headers.py +++ b/sdk/cosmos/azure-cosmos/tests/test_headers.py @@ -15,6 +15,9 @@ client_throughput_bucket_number = 2 request_throughput_bucket_number = 3 +client_priority_level = "Low" +request_priority_level = "High" + def client_raw_response_hook(response): assert (response.http_request.headers[http_constants.HttpHeaders.ThroughputBucket] == str(client_throughput_bucket_number)) @@ -23,6 +26,14 @@ def request_raw_response_hook(response): assert (response.http_request.headers[http_constants.HttpHeaders.ThroughputBucket] == str(request_throughput_bucket_number)) +def client_priority_raw_response_hook(response): + assert (response.http_request.headers[http_constants.HttpHeaders.PriorityLevel] + == client_priority_level) + +def request_priority_raw_response_hook(response): + assert (response.http_request.headers[http_constants.HttpHeaders.PriorityLevel] + == request_priority_level) + def partition_merge_support_response_hook(raw_response): header = raw_response.http_request.headers assert http_constants.HttpHeaders.SDKSupportedCapabilities in header @@ -290,5 +301,24 @@ def test_partition_merge_support_header(self): # base method to set the header(GetHeaders). self.container.read(raw_response_hook=partition_merge_support_response_hook) + def test_client_level_priority_level(self): + # Test that priority level set at client level is used for all requests + cosmos_client.CosmosClient(self.host, self.masterKey, + priority_level=client_priority_level, + raw_response_hook=client_priority_raw_response_hook) + + def test_request_precedence_priority_level(self): + # Test that request-level priority takes precedence over client-level priority + client = cosmos_client.CosmosClient(self.host, self.masterKey, + priority_level=client_priority_level) + created_db = client.get_database_client(self.configs.TEST_DATABASE_ID) + created_container = created_db.get_container_client(self.configs.TEST_MULTI_PARTITION_CONTAINER_ID) + + # Create an item with request-level priority that overrides client-level priority + created_container.create_item( + body={'id': '1' + str(uuid.uuid4()), 'pk': 'mypk'}, + priority=request_priority_level, + raw_response_hook=request_priority_raw_response_hook) + if __name__ == "__main__": unittest.main() diff --git a/sdk/cosmos/azure-cosmos/tests/test_headers_async.py b/sdk/cosmos/azure-cosmos/tests/test_headers_async.py index dfbc28f9a8d4..3f368a1d781a 100644 --- a/sdk/cosmos/azure-cosmos/tests/test_headers_async.py +++ b/sdk/cosmos/azure-cosmos/tests/test_headers_async.py @@ -16,6 +16,9 @@ client_throughput_bucket_number = 2 request_throughput_bucket_number = 3 +client_priority_level = "Low" +request_priority_level = "High" + async def client_raw_response_hook(response): assert (response.http_request.headers[http_constants.HttpHeaders.ThroughputBucket] == str(client_throughput_bucket_number)) @@ -24,6 +27,14 @@ async def request_raw_response_hook(response): assert (response.http_request.headers[http_constants.HttpHeaders.ThroughputBucket] == str(request_throughput_bucket_number)) +async def client_priority_raw_response_hook(response): + assert (response.http_request.headers[http_constants.HttpHeaders.PriorityLevel] + == client_priority_level) + +async def request_priority_raw_response_hook(response): + assert (response.http_request.headers[http_constants.HttpHeaders.PriorityLevel] + == request_priority_level) + class ClientIDVerificationError(Exception): """Custom exception for client ID verification errors.""" @@ -236,5 +247,24 @@ async def test_partition_merge_support_header(self): # base method to set the header(GetHeaders). await self.container.read(raw_response_hook=partition_merge_support_response_hook) + async def test_client_level_priority_level_async(self): + # Test that priority level set at client level is used for all requests + CosmosClient(self.host, self.masterKey, + priority_level=client_priority_level, + raw_response_hook=client_priority_raw_response_hook) + + async def test_request_precedence_priority_level_async(self): + # Test that request-level priority takes precedence over client-level priority + client = CosmosClient(self.host, self.masterKey, + priority_level=client_priority_level) + database = client.get_database_client(self.configs.TEST_DATABASE_ID) + created_container = database.get_container_client(self.configs.TEST_MULTI_PARTITION_CONTAINER_ID) + + # Create an item with request-level priority that overrides client-level priority + await created_container.create_item( + body={'id': '1' + str(uuid.uuid4()), 'pk': 'mypk'}, + priority=request_priority_level, + raw_response_hook=request_priority_raw_response_hook) + if __name__ == "__main__": unittest.main() From 9d0a6a50271d5fd9f9763e66588c04f74c2fd94e Mon Sep 17 00:00:00 2001 From: Andrew Mathew Date: Mon, 10 Nov 2025 11:45:45 -0800 Subject: [PATCH 2/9] added to changelog and docstring --- sdk/cosmos/azure-cosmos/CHANGELOG.md | 1 + .../azure-cosmos/azure/cosmos/_cosmos_client_connection.py | 3 +++ .../azure/cosmos/aio/_cosmos_client_connection_async.py | 3 +++ 3 files changed, 7 insertions(+) diff --git a/sdk/cosmos/azure-cosmos/CHANGELOG.md b/sdk/cosmos/azure-cosmos/CHANGELOG.md index da6df4c3f593..f9f05f3b171c 100644 --- a/sdk/cosmos/azure-cosmos/CHANGELOG.md +++ b/sdk/cosmos/azure-cosmos/CHANGELOG.md @@ -4,6 +4,7 @@ #### Features Added * Added merge support. See [PR 42924](https://github.com/Azure/azure-sdk-for-python/pull/42924). +* Added support for priority_level for sync and async clients. See [PR 43917](https://github.com/Azure/azure-sdk-for-python/pull/43917) #### Breaking Changes diff --git a/sdk/cosmos/azure-cosmos/azure/cosmos/_cosmos_client_connection.py b/sdk/cosmos/azure-cosmos/azure/cosmos/_cosmos_client_connection.py index 37cfe815d522..ce4a92164028 100644 --- a/sdk/cosmos/azure-cosmos/azure/cosmos/_cosmos_client_connection.py +++ b/sdk/cosmos/azure-cosmos/azure/cosmos/_cosmos_client_connection.py @@ -132,6 +132,9 @@ def __init__( # pylint: disable=too-many-statements The connection policy for the client. :param documents.ConsistencyLevel consistency_level: The default consistency policy for client operations. + :keyword Literal["High", "Low"] priority_level: Priority based execution allows users to set a priority for the + client. Once the user has reached their provisioned throughput, low priority requests are throttled + before high priority requests start getting throttled. Feature must first be enabled at the account level. """ self.client_id = str(uuid.uuid4()) self.url_connection = url_connection diff --git a/sdk/cosmos/azure-cosmos/azure/cosmos/aio/_cosmos_client_connection_async.py b/sdk/cosmos/azure-cosmos/azure/cosmos/aio/_cosmos_client_connection_async.py index 5fb40b7a5d79..a4c0964d3f6a 100644 --- a/sdk/cosmos/azure-cosmos/azure/cosmos/aio/_cosmos_client_connection_async.py +++ b/sdk/cosmos/azure-cosmos/azure/cosmos/aio/_cosmos_client_connection_async.py @@ -134,6 +134,9 @@ def __init__( # pylint: disable=too-many-statements The connection policy for the client. :param documents.ConsistencyLevel consistency_level: The default consistency policy for client operations. + :keyword Literal["High", "Low"] priority_level: Priority based execution allows users to set a priority for the + client. Once the user has reached their provisioned throughput, low priority requests are throttled + before high priority requests start getting throttled. Feature must first be enabled at the account level. """ self.client_id = str(uuid.uuid4()) self.url_connection = url_connection From 31fa90918973335d60c10f5701510d0644713c8c Mon Sep 17 00:00:00 2001 From: Andrew Mathew Date: Mon, 10 Nov 2025 12:18:37 -0800 Subject: [PATCH 3/9] changed item to queried_item for pylint --- sdk/cosmos/azure-cosmos/samples/examples.py | 4 ++-- sdk/cosmos/azure-cosmos/samples/examples_async.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sdk/cosmos/azure-cosmos/samples/examples.py b/sdk/cosmos/azure-cosmos/samples/examples.py index 041fc3958b3a..106e14678cbe 100644 --- a/sdk/cosmos/azure-cosmos/samples/examples.py +++ b/sdk/cosmos/azure-cosmos/samples/examples.py @@ -143,11 +143,11 @@ ) # All requests from this client will have Low priority by default -for item in low_priority_container.query_items( +for queried_item in low_priority_container.query_items( query='SELECT * FROM products p WHERE p.productName = "Widget"', enable_cross_partition_query=True ): - print(json.dumps(item, indent=True)) + print(json.dumps(queried_item, indent=True)) # [END client_level_priority] diff --git a/sdk/cosmos/azure-cosmos/samples/examples_async.py b/sdk/cosmos/azure-cosmos/samples/examples_async.py index 12643daeb1d9..66df5ed1ab9d 100644 --- a/sdk/cosmos/azure-cosmos/samples/examples_async.py +++ b/sdk/cosmos/azure-cosmos/samples/examples_async.py @@ -153,10 +153,10 @@ async def examples_async(): ) # All requests from this client will have Low priority by default - async for item in low_priority_container.query_items( + async for queried_item in low_priority_container.query_items( query='SELECT * FROM products p WHERE p.productName = "Widget"' ): - print(json.dumps(item, indent=True)) + print(json.dumps(queried_item, indent=True)) # [END client_level_priority] From 216339f22f8f79f180be0ada5b7f4f5177ac8cfd Mon Sep 17 00:00:00 2001 From: Andrew Mathew Date: Tue, 11 Nov 2025 10:04:39 -0500 Subject: [PATCH 4/9] made suggested changes --- sdk/cosmos/azure-cosmos/CHANGELOG.md | 2 +- .../azure/cosmos/_cosmos_client_connection.py | 8 ++-- .../aio/_cosmos_client_connection_async.py | 8 ++-- sdk/cosmos/azure-cosmos/samples/examples.py | 14 +++--- .../azure-cosmos/samples/examples_async.py | 6 +-- sdk/cosmos/azure-cosmos/tests/test_headers.py | 18 ++++---- .../azure-cosmos/tests/test_headers_async.py | 44 ++++++++++--------- 7 files changed, 52 insertions(+), 48 deletions(-) diff --git a/sdk/cosmos/azure-cosmos/CHANGELOG.md b/sdk/cosmos/azure-cosmos/CHANGELOG.md index f9f05f3b171c..aec5e133f862 100644 --- a/sdk/cosmos/azure-cosmos/CHANGELOG.md +++ b/sdk/cosmos/azure-cosmos/CHANGELOG.md @@ -4,7 +4,7 @@ #### Features Added * Added merge support. See [PR 42924](https://github.com/Azure/azure-sdk-for-python/pull/42924). -* Added support for priority_level for sync and async clients. See [PR 43917](https://github.com/Azure/azure-sdk-for-python/pull/43917) +* Added support for priority levels of `Low` and `High` for sync and async clients. See [PR 43917](https://github.com/Azure/azure-sdk-for-python/pull/43917) #### Breaking Changes diff --git a/sdk/cosmos/azure-cosmos/azure/cosmos/_cosmos_client_connection.py b/sdk/cosmos/azure-cosmos/azure/cosmos/_cosmos_client_connection.py index ce4a92164028..4e08365e2c47 100644 --- a/sdk/cosmos/azure-cosmos/azure/cosmos/_cosmos_client_connection.py +++ b/sdk/cosmos/azure-cosmos/azure/cosmos/_cosmos_client_connection.py @@ -132,7 +132,7 @@ def __init__( # pylint: disable=too-many-statements The connection policy for the client. :param documents.ConsistencyLevel consistency_level: The default consistency policy for client operations. - :keyword Literal["High", "Low"] priority_level: Priority based execution allows users to set a priority for the + :keyword Literal["High", "Low"] priority: Priority based execution allows users to set a priority for the client. Once the user has reached their provisioned throughput, low priority requests are throttled before high priority requests start getting throttled. Feature must first be enabled at the account level. """ @@ -168,9 +168,9 @@ def __init__( # pylint: disable=too-many-statements if throughput_bucket: self.default_headers[http_constants.HttpHeaders.ThroughputBucket] = throughput_bucket - priority_level = kwargs.pop('priority_level', None) - if priority_level: - self.default_headers[http_constants.HttpHeaders.PriorityLevel] = priority_level + priority = kwargs.pop('priority', None) + if priority: + self.default_headers[http_constants.HttpHeaders.PriorityLevel] = priority # Keeps the latest response headers from the server. self.last_response_headers: CaseInsensitiveDict = CaseInsensitiveDict() diff --git a/sdk/cosmos/azure-cosmos/azure/cosmos/aio/_cosmos_client_connection_async.py b/sdk/cosmos/azure-cosmos/azure/cosmos/aio/_cosmos_client_connection_async.py index a4c0964d3f6a..67d5d4efa3e9 100644 --- a/sdk/cosmos/azure-cosmos/azure/cosmos/aio/_cosmos_client_connection_async.py +++ b/sdk/cosmos/azure-cosmos/azure/cosmos/aio/_cosmos_client_connection_async.py @@ -134,7 +134,7 @@ def __init__( # pylint: disable=too-many-statements The connection policy for the client. :param documents.ConsistencyLevel consistency_level: The default consistency policy for client operations. - :keyword Literal["High", "Low"] priority_level: Priority based execution allows users to set a priority for the + :keyword Literal["High", "Low"] priority: Priority based execution allows users to set a priority for the client. Once the user has reached their provisioned throughput, low priority requests are throttled before high priority requests start getting throttled. Feature must first be enabled at the account level. """ @@ -170,9 +170,9 @@ def __init__( # pylint: disable=too-many-statements if throughput_bucket: self.default_headers[http_constants.HttpHeaders.ThroughputBucket] = throughput_bucket - priority_level = kwargs.pop('priority_level', None) - if priority_level: - self.default_headers[http_constants.HttpHeaders.PriorityLevel] = priority_level + priority = kwargs.pop('priority', None) + if priority: + self.default_headers[http_constants.HttpHeaders.PriorityLevel] = priority if consistency_level is not None: self.default_headers[http_constants.HttpHeaders.ConsistencyLevel] = consistency_level diff --git a/sdk/cosmos/azure-cosmos/samples/examples.py b/sdk/cosmos/azure-cosmos/samples/examples.py index 106e14678cbe..c5da77ae0fc3 100644 --- a/sdk/cosmos/azure-cosmos/samples/examples.py +++ b/sdk/cosmos/azure-cosmos/samples/examples.py @@ -129,10 +129,10 @@ # [START client_level_priority] # Priority can also be set at the client level, which will apply to all requests made by that client. # This is useful when you want all operations from a particular client to have the same priority. -# The client-level priority is set during client initialization with the `priority_level` parameter. +# The client-level priority is set during client initialization with the `priority` parameter. # Create a client with Low priority for all requests -low_priority_client = CosmosClient(url, key, priority_level="Low") +low_priority_client = CosmosClient(url, key, priority="Low") low_priority_database = low_priority_client.get_database_client(database_name) low_priority_container = low_priority_database.get_container_client(container_name) @@ -156,21 +156,21 @@ # This allows you to override the default priority for specific operations. # Create a client with Low priority -client_with_default_priority = CosmosClient(url, key, priority_level="Low") +client_with_default_priority = CosmosClient(url, key, priority="Low") database_with_priority = client_with_default_priority.get_database_client(database_name) container_with_priority = database_with_priority.get_container_client(container_name) # Add items with different priority levels to the container container_with_priority.upsert_item( - dict(id="urgent_item1", productName="Widget", priority="urgent", productModel="Urgent Model") + dict(id="urgent_item1", productName="Widget", priority="high", productModel="High Priority Model") ) container_with_priority.upsert_item( - dict(id="normal_item1", productName="Widget", priority="normal", productModel="Normal Model") + dict(id="normal_item1", productName="Widget", priority="low", productModel="Low Priority Model") ) # This query will use High priority, overriding the client's Low priority setting for important_item in container_with_priority.query_items( - query='SELECT * FROM products p WHERE p.priority = "urgent"', + query='SELECT * FROM products p WHERE p.priority = "high"', enable_cross_partition_query=True, priority="High" # Request-level priority overrides client-level priority ): @@ -178,7 +178,7 @@ # This query will use the client's default Low priority for normal_item in container_with_priority.query_items( - query='SELECT * FROM products p WHERE p.priority = "normal"', + query='SELECT * FROM products p WHERE p.priority = "low"', enable_cross_partition_query=True ): print(json.dumps(normal_item, indent=True)) diff --git a/sdk/cosmos/azure-cosmos/samples/examples_async.py b/sdk/cosmos/azure-cosmos/samples/examples_async.py index 66df5ed1ab9d..935beba1019a 100644 --- a/sdk/cosmos/azure-cosmos/samples/examples_async.py +++ b/sdk/cosmos/azure-cosmos/samples/examples_async.py @@ -139,10 +139,10 @@ async def examples_async(): # [START client_level_priority] # Priority can also be set at the client level, which will apply to all requests made by that client. # This is useful when you want all operations from a particular client to have the same priority. - # The client-level priority is set during client initialization with the `priority_level` parameter. + # The client-level priority is set during client initialization with the `priority` parameter. # Create a client with Low priority for all requests - async with CosmosClient(url, key, priority_level="Low") as low_priority_client: + async with CosmosClient(url, key, priority="Low") as low_priority_client: low_priority_database = low_priority_client.get_database_client(database_name) low_priority_container = low_priority_database.get_container_client(container_name) @@ -165,7 +165,7 @@ async def examples_async(): # This allows you to override the default priority for specific operations. # Create a client with Low priority - async with CosmosClient(url, key, priority_level="Low") as client_with_default_priority: + async with CosmosClient(url, key, priority="Low") as client_with_default_priority: database_with_priority = client_with_default_priority.get_database_client(database_name) container_with_priority = database_with_priority.get_container_client(container_name) diff --git a/sdk/cosmos/azure-cosmos/tests/test_headers.py b/sdk/cosmos/azure-cosmos/tests/test_headers.py index 228a7cd61c9c..7aeb6afed067 100644 --- a/sdk/cosmos/azure-cosmos/tests/test_headers.py +++ b/sdk/cosmos/azure-cosmos/tests/test_headers.py @@ -15,8 +15,8 @@ client_throughput_bucket_number = 2 request_throughput_bucket_number = 3 -client_priority_level = "Low" -request_priority_level = "High" +client_priority = "Low" +request_priority = "High" def client_raw_response_hook(response): assert (response.http_request.headers[http_constants.HttpHeaders.ThroughputBucket] @@ -28,11 +28,11 @@ def request_raw_response_hook(response): def client_priority_raw_response_hook(response): assert (response.http_request.headers[http_constants.HttpHeaders.PriorityLevel] - == client_priority_level) + == client_priority) def request_priority_raw_response_hook(response): assert (response.http_request.headers[http_constants.HttpHeaders.PriorityLevel] - == request_priority_level) + == request_priority) def partition_merge_support_response_hook(raw_response): header = raw_response.http_request.headers @@ -301,23 +301,23 @@ def test_partition_merge_support_header(self): # base method to set the header(GetHeaders). self.container.read(raw_response_hook=partition_merge_support_response_hook) - def test_client_level_priority_level(self): + def test_client_level_priority(self): # Test that priority level set at client level is used for all requests cosmos_client.CosmosClient(self.host, self.masterKey, - priority_level=client_priority_level, + priority=client_priority, raw_response_hook=client_priority_raw_response_hook) - def test_request_precedence_priority_level(self): + def test_request_precedence_priority(self): # Test that request-level priority takes precedence over client-level priority client = cosmos_client.CosmosClient(self.host, self.masterKey, - priority_level=client_priority_level) + priority=client_priority) created_db = client.get_database_client(self.configs.TEST_DATABASE_ID) created_container = created_db.get_container_client(self.configs.TEST_MULTI_PARTITION_CONTAINER_ID) # Create an item with request-level priority that overrides client-level priority created_container.create_item( body={'id': '1' + str(uuid.uuid4()), 'pk': 'mypk'}, - priority=request_priority_level, + priority=request_priority, raw_response_hook=request_priority_raw_response_hook) if __name__ == "__main__": diff --git a/sdk/cosmos/azure-cosmos/tests/test_headers_async.py b/sdk/cosmos/azure-cosmos/tests/test_headers_async.py index 3f368a1d781a..d0453f5bf3fc 100644 --- a/sdk/cosmos/azure-cosmos/tests/test_headers_async.py +++ b/sdk/cosmos/azure-cosmos/tests/test_headers_async.py @@ -16,8 +16,8 @@ client_throughput_bucket_number = 2 request_throughput_bucket_number = 3 -client_priority_level = "Low" -request_priority_level = "High" +client_priority = "Low" +request_priority = "High" async def client_raw_response_hook(response): assert (response.http_request.headers[http_constants.HttpHeaders.ThroughputBucket] @@ -29,11 +29,11 @@ async def request_raw_response_hook(response): async def client_priority_raw_response_hook(response): assert (response.http_request.headers[http_constants.HttpHeaders.PriorityLevel] - == client_priority_level) + == client_priority) async def request_priority_raw_response_hook(response): assert (response.http_request.headers[http_constants.HttpHeaders.PriorityLevel] - == request_priority_level) + == request_priority) class ClientIDVerificationError(Exception): @@ -247,24 +247,28 @@ async def test_partition_merge_support_header(self): # base method to set the header(GetHeaders). await self.container.read(raw_response_hook=partition_merge_support_response_hook) - async def test_client_level_priority_level_async(self): + async def test_client_level_priority_async(self): # Test that priority level set at client level is used for all requests - CosmosClient(self.host, self.masterKey, - priority_level=client_priority_level, - raw_response_hook=client_priority_raw_response_hook) - - async def test_request_precedence_priority_level_async(self): + async with CosmosClient(self.host, self.masterKey, + priority=client_priority, + raw_response_hook=client_priority_raw_response_hook) as client: + # Make a request to trigger the hook + database = client.get_database_client(self.configs.TEST_DATABASE_ID) + container = database.get_container_client(self.configs.TEST_MULTI_PARTITION_CONTAINER_ID) + created_item = await container.create_item(body={'id': '1' + str(uuid.uuid4()), 'pk': 'mypk'}) + + async def test_request_precedence_priority_async(self): # Test that request-level priority takes precedence over client-level priority - client = CosmosClient(self.host, self.masterKey, - priority_level=client_priority_level) - database = client.get_database_client(self.configs.TEST_DATABASE_ID) - created_container = database.get_container_client(self.configs.TEST_MULTI_PARTITION_CONTAINER_ID) - - # Create an item with request-level priority that overrides client-level priority - await created_container.create_item( - body={'id': '1' + str(uuid.uuid4()), 'pk': 'mypk'}, - priority=request_priority_level, - raw_response_hook=request_priority_raw_response_hook) + async with CosmosClient(self.host, self.masterKey, + priority=client_priority) as client: + database = client.get_database_client(self.configs.TEST_DATABASE_ID) + created_container = database.get_container_client(self.configs.TEST_MULTI_PARTITION_CONTAINER_ID) + + # Create an item with request-level priority that overrides client-level priority + await created_container.create_item( + body={'id': '1' + str(uuid.uuid4()), 'pk': 'mypk'}, + priority=request_priority, + raw_response_hook=request_priority_raw_response_hook) if __name__ == "__main__": unittest.main() From 76b1f347ac8c4aca99f9acf0bb3118f42802a779 Mon Sep 17 00:00:00 2001 From: Andrew Mathew Date: Tue, 11 Nov 2025 10:09:01 -0500 Subject: [PATCH 5/9] fixed sample bug --- sdk/cosmos/azure-cosmos/samples/examples.py | 8 ++++---- sdk/cosmos/azure-cosmos/samples/examples_async.py | 15 ++++----------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/sdk/cosmos/azure-cosmos/samples/examples.py b/sdk/cosmos/azure-cosmos/samples/examples.py index c5da77ae0fc3..7cd6d0b56c84 100644 --- a/sdk/cosmos/azure-cosmos/samples/examples.py +++ b/sdk/cosmos/azure-cosmos/samples/examples.py @@ -162,15 +162,15 @@ # Add items with different priority levels to the container container_with_priority.upsert_item( - dict(id="urgent_item1", productName="Widget", priority="high", productModel="High Priority Model") + dict(id="urgent_item1", productName="Widget", priority="High", productModel="High Priority Model") ) container_with_priority.upsert_item( - dict(id="normal_item1", productName="Widget", priority="low", productModel="Low Priority Model") + dict(id="normal_item1", productName="Widget", priority="Low", productModel="Low Priority Model") ) # This query will use High priority, overriding the client's Low priority setting for important_item in container_with_priority.query_items( - query='SELECT * FROM products p WHERE p.priority = "high"', + query='SELECT * FROM products p WHERE p.priority = "High"', enable_cross_partition_query=True, priority="High" # Request-level priority overrides client-level priority ): @@ -178,7 +178,7 @@ # This query will use the client's default Low priority for normal_item in container_with_priority.query_items( - query='SELECT * FROM products p WHERE p.priority = "low"', + query='SELECT * FROM products p WHERE p.priority = "Low"', enable_cross_partition_query=True ): print(json.dumps(normal_item, indent=True)) diff --git a/sdk/cosmos/azure-cosmos/samples/examples_async.py b/sdk/cosmos/azure-cosmos/samples/examples_async.py index 935beba1019a..e0c7c996e1f1 100644 --- a/sdk/cosmos/azure-cosmos/samples/examples_async.py +++ b/sdk/cosmos/azure-cosmos/samples/examples_async.py @@ -123,13 +123,6 @@ async def examples_async(): # Can be used for Read, Write, and Query operations. This is specified with the `priority` keyword. # the value can either be low or high. - # Ensure we have items to query (this reuses items from earlier in the example) - # If running this section independently, uncomment the lines below: - # for i in range(1, 10): - # await container.upsert_item( - # dict(id="item{}".format(i), productName="Widget", productModel="Model {}".format(i)) - # ) - async for queried_item in container.query_items( query='SELECT * FROM products p WHERE p.productModel <> "DISCONTINUED"', priority="High" ): @@ -171,22 +164,22 @@ async def examples_async(): # Add items with different priority levels to the container await container_with_priority.upsert_item( - dict(id="urgent_item1", productName="Widget", priority="urgent", productModel="Urgent Model") + dict(id="urgent_item1", productName="Widget", priority="Low", productModel="Low Priority Model") ) await container_with_priority.upsert_item( - dict(id="normal_item1", productName="Widget", priority="normal", productModel="Normal Model") + dict(id="normal_item1", productName="Widget", priority="High", productModel="High Priority Model") ) # This query will use High priority, overriding the client's Low priority setting async for important_item in container_with_priority.query_items( - query='SELECT * FROM products p WHERE p.priority = "urgent"', + query='SELECT * FROM products p WHERE p.priority = "High"', priority="High" # Request-level priority overrides client-level priority ): print(json.dumps(important_item, indent=True)) # This query will use the client's default Low priority async for normal_item in container_with_priority.query_items( - query='SELECT * FROM products p WHERE p.priority = "normal"' + query='SELECT * FROM products p WHERE p.priority = "Low"' ): print(json.dumps(normal_item, indent=True)) From 6b99c575a51ed67ba7a7fe957864ca0e67ed719e Mon Sep 17 00:00:00 2001 From: Andrew Mathew <80082032+andrewmathew1@users.noreply.github.com> Date: Wed, 12 Nov 2025 08:40:27 -0500 Subject: [PATCH 6/9] Update sdk/cosmos/azure-cosmos/CHANGELOG.md Co-authored-by: Simon Moreno <30335873+simorenoh@users.noreply.github.com> --- sdk/cosmos/azure-cosmos/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/cosmos/azure-cosmos/CHANGELOG.md b/sdk/cosmos/azure-cosmos/CHANGELOG.md index aec5e133f862..8d3d914a9ed5 100644 --- a/sdk/cosmos/azure-cosmos/CHANGELOG.md +++ b/sdk/cosmos/azure-cosmos/CHANGELOG.md @@ -4,7 +4,7 @@ #### Features Added * Added merge support. See [PR 42924](https://github.com/Azure/azure-sdk-for-python/pull/42924). -* Added support for priority levels of `Low` and `High` for sync and async clients. See [PR 43917](https://github.com/Azure/azure-sdk-for-python/pull/43917) +* Added support for priority-based throttling at the client level for sync and async clients. See [PR 43917](https://github.com/Azure/azure-sdk-for-python/pull/43917) #### Breaking Changes From 145fb517aef1023db73caa822e978fcaa40f8049 Mon Sep 17 00:00:00 2001 From: Andrew Mathew Date: Wed, 12 Nov 2025 13:27:17 -0500 Subject: [PATCH 7/9] Changed test pipeline from West US to West Central US --- sdk/cosmos/test-resources.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/cosmos/test-resources.bicep b/sdk/cosmos/test-resources.bicep index cfaee9a3ff0f..c99344adfeb5 100644 --- a/sdk/cosmos/test-resources.bicep +++ b/sdk/cosmos/test-resources.bicep @@ -39,7 +39,7 @@ var multiRegionConfiguration = [ isZoneRedundant: false } { - locationName: 'West US' + locationName: 'West Central US' provisioningState: 'Succeeded' failoverPriority: 1 isZoneRedundant: false From 46a1f05e80bc5a4a2dac9e385a3f27e5367a0998 Mon Sep 17 00:00:00 2001 From: Andrew Mathew Date: Thu, 13 Nov 2025 16:16:46 -0500 Subject: [PATCH 8/9] added changes to vector index policy tests --- .../azure-cosmos/tests/test_vector_policy.py | 15 +++------------ .../tests/test_vector_policy_async.py | 15 +++------------ 2 files changed, 6 insertions(+), 24 deletions(-) diff --git a/sdk/cosmos/azure-cosmos/tests/test_vector_policy.py b/sdk/cosmos/azure-cosmos/tests/test_vector_policy.py index 5b63e8b76ef3..406203c07e80 100644 --- a/sdk/cosmos/azure-cosmos/tests/test_vector_policy.py +++ b/sdk/cosmos/azure-cosmos/tests/test_vector_policy.py @@ -60,7 +60,7 @@ def test_create_vector_embedding_container(self): indexing_policy = { "vectorIndexes": [ {"path": "/vector1", "type": "flat"}, - {"path": "/vector2", "type": "quantizedFlat", "quantizationByteSize": 8}, + {"path": "/vector2", "type": "quantizedFlat", "quantizerType": "product", "quantizationByteSize": 8}, {"path": "/vector3", "type": "diskANN", "quantizationByteSize": 8, "vectorIndexShardKey": ["/city"], "indexingSearchListSize": 50} ] } @@ -149,6 +149,7 @@ def test_replace_vector_indexing_policy(self): { "path": "/vector1", "type": "diskANN", + "quantizerType": "product", "quantizationByteSize": 128, "indexingSearchListSize": 100 } @@ -179,6 +180,7 @@ def test_replace_vector_indexing_policy(self): { "path": "/vector1", "type": "diskANN", + "quantizerType": "product", "quantizationByteSize": 128, "indexingSearchListSize": 100 }] @@ -407,17 +409,6 @@ def test_fail_replace_vector_indexing_policy(self): assert e.status_code == 400 assert ("The Vector Indexing Policy's path::/vector1 not matching in Embedding's path." in e.http_error_message) - # don't provide vector indexing policy - try: - self.test_db.replace_container( - created_container, - PartitionKey(path="/id"), - vector_embedding_policy=vector_embedding_policy) - pytest.fail("Container replace should have failed for missing indexing policy.") - except exceptions.CosmosHttpResponseError as e: - assert e.status_code == 400 - assert ("The Vector Indexing Policy cannot be changed in Collection Replace." - in e.http_error_message) # using a new indexing policy new_indexing_policy = { "vectorIndexes": [ diff --git a/sdk/cosmos/azure-cosmos/tests/test_vector_policy_async.py b/sdk/cosmos/azure-cosmos/tests/test_vector_policy_async.py index 8e680a946020..6449846a7cfe 100644 --- a/sdk/cosmos/azure-cosmos/tests/test_vector_policy_async.py +++ b/sdk/cosmos/azure-cosmos/tests/test_vector_policy_async.py @@ -51,7 +51,7 @@ async def test_create_vector_embedding_container_async(self): "vectorIndexes": [ {"path": "/vector1", "type": "flat"}, - {"path": "/vector2", "type": "quantizedFlat", "quantizationByteSize": 64, "vectorIndexShardKey": ["/city"]}, + {"path": "/vector2", "type": "quantizedFlat", "quantizerType": "product", "quantizationByteSize": 64, "vectorIndexShardKey": ["/city"]}, {"path": "/vector3", "type": "diskANN", "quantizationByteSize": 8, "indexingSearchListSize": 50} ] @@ -124,6 +124,7 @@ async def test_replace_vector_indexing_policy_async(self): { "path": "/vector1", "type": "diskANN", + "quantizerType": "product", "quantizationByteSize": 128, "indexingSearchListSize": 100 } @@ -154,6 +155,7 @@ async def test_replace_vector_indexing_policy_async(self): { "path": "/vector1", "type": "diskANN", + "quantizerType": "product", "quantizationByteSize": 128, "indexingSearchListSize": 100 }] @@ -338,17 +340,6 @@ async def test_fail_replace_vector_indexing_policy_async(self): assert e.status_code == 400 assert ("The Vector Indexing Policy's path::/vector1 not matching in Embedding's path." in e.http_error_message) - # don't provide vector indexing policy - try: - await self.test_db.replace_container( - created_container, - PartitionKey(path="/id"), - vector_embedding_policy=vector_embedding_policy) - pytest.fail("Container replace should have failed for missing indexing policy.") - except exceptions.CosmosHttpResponseError as e: - assert e.status_code == 400 - assert ("The Vector Indexing Policy cannot be changed in Collection Replace." - in e.http_error_message) # using a new indexing policy new_indexing_policy = { "vectorIndexes": [ From d07c831a9ab9e795f16d6f3b2c6ab4824fd81235 Mon Sep 17 00:00:00 2001 From: Andrew Mathew Date: Thu, 13 Nov 2025 17:36:33 -0500 Subject: [PATCH 9/9] bugfixes for vector policy tests --- sdk/cosmos/azure-cosmos/tests/test_vector_policy.py | 6 +++--- sdk/cosmos/azure-cosmos/tests/test_vector_policy_async.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sdk/cosmos/azure-cosmos/tests/test_vector_policy.py b/sdk/cosmos/azure-cosmos/tests/test_vector_policy.py index 406203c07e80..214896e12a60 100644 --- a/sdk/cosmos/azure-cosmos/tests/test_vector_policy.py +++ b/sdk/cosmos/azure-cosmos/tests/test_vector_policy.py @@ -61,7 +61,7 @@ def test_create_vector_embedding_container(self): "vectorIndexes": [ {"path": "/vector1", "type": "flat"}, {"path": "/vector2", "type": "quantizedFlat", "quantizerType": "product", "quantizationByteSize": 8}, - {"path": "/vector3", "type": "diskANN", "quantizationByteSize": 8, "vectorIndexShardKey": ["/city"], "indexingSearchListSize": 50} + {"path": "/vector3", "type": "diskANN", "quantizerType": "product", "quantizationByteSize": 8, "vectorIndexShardKey": ["/city"], "indexingSearchListSize": 50} ] } vector_embedding_policy = { @@ -101,7 +101,7 @@ def test_create_vector_embedding_container(self): # Pass a vector indexing policy with hierarchical vectorIndexShardKey value indexing_policy = { "vectorIndexes": [ - {"path": "/vector2", "type": "diskANN", 'quantizationByteSize': 64, 'indexingSearchListSize': 100, "vectorIndexShardKey": ["/country/city"]}] + {"path": "/vector2", "type": "diskANN", "quantizerType": "product", 'quantizationByteSize': 64, 'indexingSearchListSize': 100, "vectorIndexShardKey": ["/country/city"]}] } container_id = "vector_container" + str(uuid.uuid4()) created_container = self.test_db.create_container( @@ -442,7 +442,7 @@ def test_fail_replace_vector_indexing_policy(self): pytest.fail("Container replace should have failed for new embedding policy.") except exceptions.CosmosHttpResponseError as e: assert e.status_code == 400 - assert ("The Vector Embedding Policy cannot be changed in Collection Replace" + assert ("Paths in existing embedding policy cannot be modified in Collection Replace" in e.http_error_message) self.test_db.delete_container(container_id) diff --git a/sdk/cosmos/azure-cosmos/tests/test_vector_policy_async.py b/sdk/cosmos/azure-cosmos/tests/test_vector_policy_async.py index 6449846a7cfe..61c623b79270 100644 --- a/sdk/cosmos/azure-cosmos/tests/test_vector_policy_async.py +++ b/sdk/cosmos/azure-cosmos/tests/test_vector_policy_async.py @@ -53,7 +53,7 @@ async def test_create_vector_embedding_container_async(self): {"path": "/vector2", "type": "quantizedFlat", "quantizerType": "product", "quantizationByteSize": 64, "vectorIndexShardKey": ["/city"]}, - {"path": "/vector3", "type": "diskANN", "quantizationByteSize": 8, "indexingSearchListSize": 50} + {"path": "/vector3", "type": "diskANN", "quantizerType": "product", "quantizationByteSize": 8, "indexingSearchListSize": 50} ] } vector_embedding_policy = { @@ -373,7 +373,7 @@ async def test_fail_replace_vector_indexing_policy_async(self): pytest.fail("Container replace should have failed for new embedding policy.") except exceptions.CosmosHttpResponseError as e: assert e.status_code == 400 - assert ("The Vector Embedding Policy cannot be changed in Collection Replace" + assert ("Paths in existing embedding policy cannot be modified in Collection Replace" in e.http_error_message) await self.test_db.delete_container(container_id)