Skip to content

Commit c87d16a

Browse files
authored
[Cosmos] change retry_write to int, update semantic_reranker api (#43341)
* change `retry_write` to int, update semantic_reranker api, mark provisional * Update CHANGELOG.md * changelog, readme, tests * update offer.py typechecking * typehint update, set max properly for timeouts, * Update CHANGELOG with breaking change Updated CHANGELOG.md to reflect new features, breaking changes, and other modifications. * Update comments for clarity in set_retry_write method * Update max write retry count logic * update tests
1 parent 9a68138 commit c87d16a

15 files changed

+116
-118
lines changed

sdk/cosmos/azure-cosmos/CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
#### Features Added
66
* Added ability to return a tuple of a DatabaseProxy/ContainerProxy with the associated database/container properties when creating or reading databases/containers through `return_properties` parameter. See [PR 41742](https://github.com/Azure/azure-sdk-for-python/pull/41742)
7-
* Added a new API for Semantic Reranking. See [PR 42991](https://github.com/Azure/azure-sdk-for-python/pull/42991)
7+
* Added a new **preview feature** API for Semantic Reranking. See [PR 42991](https://github.com/Azure/azure-sdk-for-python/pull/42991)
8+
89
#### Breaking Changes
10+
* Changed `retry_write` from `bool` to `int` to match other retryable options. See [PR 43341](https://github.com/Azure/azure-sdk-for-python/pull/43341).
911

1012
#### Bugs Fixed
1113

sdk/cosmos/azure-cosmos/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -686,15 +686,15 @@ The snippet below shows how to enable this feature at the client and request lev
686686
cosmos_client = CosmosClient(
687687
url=URL,
688688
credential=KEY,
689-
retry_write=True, # enables native retryable writes at the client level
689+
retry_write=1, # enables a single native retryable write at the client level
690690
)
691691

692692
database = cosmos_client.get_database_client(DATABASE_NAME)
693693
container = database.get_container_client(CONTAINER_NAME)
694694

695695
container.create_item(
696696
item_body,
697-
retry_write=True # enables native retryable writes at the request level
697+
retry_write=1 # enables a single native retryable write at the request level
698698
)
699699
```
700700

sdk/cosmos/azure-cosmos/azure/cosmos/_request_object.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def __init__(
4747
self.excluded_locations_circuit_breaker: list[str] = []
4848
self.healthy_tentative_location: Optional[str] = None
4949
self.pk_val = pk_val
50-
self.retry_write: bool = False
50+
self.retry_write: int = 0
5151

5252
def route_to_location_with_preferred_location_flag( # pylint: disable=name-too-long
5353
self,
@@ -85,14 +85,16 @@ def set_excluded_location_from_options(self, options: Mapping[str, Any]) -> None
8585
if self._can_set_excluded_location(options):
8686
self.excluded_locations = options['excludedLocations']
8787

88-
def set_retry_write(self, request_options: Mapping[str, Any], client_retry_write: bool) -> None:
88+
def set_retry_write(self, request_options: Mapping[str, Any], client_retry_write: int) -> None:
8989
if self.resource_type == ResourceType.Document:
9090
if request_options and request_options.get(Constants.Kwargs.RETRY_WRITE):
91-
# If request retry write is True, set the option
91+
# If request retry write is > 0, set the option
9292
self.retry_write = request_options[Constants.Kwargs.RETRY_WRITE]
9393
elif client_retry_write and self.operation_type != _OperationType.Patch:
94-
# If it is not a patch operation and the client config is set, set the retry write to True
94+
# If it is not a patch operation and the client config is set, set the retry write to the client value
9595
self.retry_write = client_retry_write
96+
else:
97+
self.retry_write = 0
9698

9799
def set_excluded_locations_from_circuit_breaker(self, excluded_locations: list[str]) -> None: # pylint: disable=name-too-long
98100
self.excluded_locations_circuit_breaker = excluded_locations

sdk/cosmos/azure-cosmos/azure/cosmos/_retry_utility.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,9 +297,9 @@ def _handle_service_response_retries(request, client, response_retry_policy, exc
297297
raise exception
298298

299299
def is_write_retryable(request_params, client):
300-
return (request_params.retry_write or
301-
client.connection_policy.RetryNonIdempotentWrites and
302-
not request_params.operation_type == _OperationType.Patch)
300+
return (request_params.retry_write > 0 or
301+
(client.connection_policy.RetryNonIdempotentWrites > 0 and
302+
not request_params.operation_type == _OperationType.Patch))
303303

304304
def _configure_timeout(request: PipelineRequest, absolute: Optional[int], per_request: int) -> None:
305305
if absolute is not None:

sdk/cosmos/azure-cosmos/azure/cosmos/_service_response_retry_policy.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,10 @@ def __init__(self, connection_policy, global_endpoint_manager, pk_range_wrapper,
2121
self.connection_policy = connection_policy
2222
self.request = args[0] if args else None
2323
if self.request:
24-
if self.request.retry_write:
24+
if self.request.retry_write > 0:
2525
# If the request is a write operation, we set the maximum retry count to be the number of
26-
# write regional routing contexts available in the global endpoint manager.
27-
# This ensures that we retry the write operation across all available regions.
28-
# We also ensure that we retry at least once, hence the max is set to 2 by default.
29-
self.max_write_retry_count = max(len(self.global_endpoint_manager.
30-
location_cache.write_regional_routing_contexts), 2)
26+
# write retries provided by the customer.
27+
self.max_write_retry_count = self.request.retry_write
3128
self.location_endpoint = (self.global_endpoint_manager
3229
.resolve_service_endpoint_for_partition(self.request, pk_range_wrapper))
3330
self.logger = logging.getLogger('azure.cosmos.ServiceResponseRetryPolicy')
@@ -48,9 +45,9 @@ def ShouldRetry(self):
4845

4946
if self.request:
5047

51-
if not _OperationType.IsReadOnlyOperation(self.request.operation_type) and not self.request.retry_write:
48+
if not _OperationType.IsReadOnlyOperation(self.request.operation_type) and not self.request.retry_write > 0:
5249
return False
53-
if self.request.retry_write and self.failover_retry_count + 1 >= self.max_write_retry_count:
50+
if self.request.retry_write > 0 and self.failover_retry_count + 1 >= self.max_write_retry_count:
5451
# If we have already retried the write operation to the maximum allowed number of times,
5552
# we do not retry further.
5653
return False

sdk/cosmos/azure-cosmos/azure/cosmos/_timeout_failover_retry_policy.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,9 @@ def __init__(self, connection_policy, global_endpoint_manager, pk_range_wrapper,
2121
# a request object
2222
self._max_retry_attempt_count = len(self.global_endpoint_manager.location_cache
2323
.read_regional_routing_contexts) + 1
24-
# If the request is a write operation, we only want to retry once if retry write is enabled
24+
# If the request is a write operation, we only want to retry as many times as retry_write
2525
if self.request and _OperationType.IsWriteOperation(self.request.operation_type):
26-
self._max_retry_attempt_count = len(
27-
self.global_endpoint_manager.location_cache.write_regional_routing_contexts
28-
) + 1
26+
self._max_retry_attempt_count = self.request.retry_write
2927
self.retry_count = 0
3028
self.connection_policy = connection_policy
3129

@@ -70,4 +68,4 @@ def resolve_next_region_service_endpoint(self):
7068
def is_operation_retryable(self):
7169
if _OperationType.IsReadOnlyOperation(self.request.operation_type):
7270
return True
73-
return self.request.retry_write
71+
return self.request.retry_write > 0

sdk/cosmos/azure-cosmos/azure/cosmos/aio/_container.py

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ async def create_item(
216216
initial_headers: Optional[dict[str, str]] = None,
217217
priority: Optional[Literal["High", "Low"]] = None,
218218
no_response: Optional[bool] = None,
219-
retry_write: Optional[bool] = None,
219+
retry_write: Optional[int] = None,
220220
throughput_bucket: Optional[int] = None,
221221
**kwargs: Any
222222
) -> CosmosDict:
@@ -246,9 +246,9 @@ async def create_item(
246246
:keyword bool no_response: Indicates whether service should be instructed to skip
247247
sending response payloads. When not specified explicitly here, the default value will be determined from
248248
client-level options.
249-
:keyword bool retry_write: Indicates whether the SDK should automatically retry this write operation, even if
249+
:keyword int retry_write: Indicates how many times the SDK should automatically retry this write operation, even if
250250
the operation is not guaranteed to be idempotent. This should only be enabled if the application can
251-
tolerate such risks or has logic to safely detect and handle duplicate operations.
251+
tolerate such risks or has logic to safely detect and handle duplicate operations. Default is None (no retries).
252252
:keyword int throughput_bucket: The desired throughput bucket for the client
253253
:raises ~azure.cosmos.exceptions.CosmosHttpResponseError: Item with the given ID already exists.
254254
:returns: A CosmosDict representing the new item. The dict will be empty if `no_response` is specified.
@@ -1103,7 +1103,7 @@ async def upsert_item(
11031103
match_condition: Optional[MatchConditions] = None,
11041104
priority: Optional[Literal["High", "Low"]] = None,
11051105
no_response: Optional[bool] = None,
1106-
retry_write: Optional[bool] = None,
1106+
retry_write: Optional[int] = None,
11071107
throughput_bucket: Optional[int] = None,
11081108
**kwargs: Any
11091109
) -> CosmosDict:
@@ -1129,9 +1129,9 @@ async def upsert_item(
11291129
:keyword bool no_response: Indicates whether service should be instructed to skip
11301130
sending response payloads. When not specified explicitly here, the default value will be determined from
11311131
client-level options.
1132-
:keyword bool retry_write: Indicates whether the SDK should automatically retry this write operation, even if
1132+
:keyword int retry_write: Indicates how many times the SDK should automatically retry this write operation, even if
11331133
the operation is not guaranteed to be idempotent. This should only be enabled if the application can
1134-
tolerate such risks or has logic to safely detect and handle duplicate operations.
1134+
tolerate such risks or has logic to safely detect and handle duplicate operations. Default is None (no retries).
11351135
:keyword int throughput_bucket: The desired throughput bucket for the client
11361136
:keyword Sequence[str] excluded_locations: Excluded locations to be skipped from preferred locations. The locations
11371137
in this list are specified as the names of the azure Cosmos locations like, 'West US', 'East US' and so on.
@@ -1178,29 +1178,28 @@ async def upsert_item(
11781178
@distributed_trace_async
11791179
async def semantic_rerank(
11801180
self,
1181-
reranking_context: str,
1181+
*,
1182+
context: str,
11821183
documents: list[str],
1183-
semantic_reranking_options: Optional[dict[str, Any]] = None
1184+
options: Optional[dict[str, Any]] = None
11841185
) -> CosmosDict:
1185-
"""Rerank a list of documents using semantic reranking.
1186+
""" **provisional** Rerank a list of documents using semantic reranking.
11861187
11871188
This method uses a semantic reranker to score and reorder the provided documents
11881189
based on their relevance to the given reranking context.
11891190
1190-
:param str reranking_context: The context or query string to use for reranking the documents.
1191-
:param list[str] documents: A list of documents (as strings) to be reranked.
1192-
:param dict[str, Any] semantic_reranking_options: Optional dictionary of additional options to customize the semantic reranking process.
1191+
:keyword str context: The reranking context or query string to use for reranking the documents.
1192+
:keyword list[str] documents: A list of documents (as strings) to be reranked.
1193+
:keyword dict[str, Any] options: Optional dictionary of additional request options to customize the semantic reranking process.
11931194
11941195
Supported options:
1195-
11961196
* **return_documents** (bool): Whether to return the document text in the response. If False, only scores and indices are returned. Default is True.
11971197
* **top_k** (int): Maximum number of documents to return in the reranked results. If not specified, all documents are returned.
11981198
* **batch_size** (int): Number of documents to process in each batch. Used for optimizing performance with large document sets.
11991199
* **sort** (bool): Whether to sort the results by relevance score in descending order. Default is True.
12001200
* **document_type** (str): Type of documents being reranked. Supported values are "string" and "json".
12011201
* **target_paths** (str): If document_type is "json", the list of JSON paths to extract text from for reranking. Comma-separated string.
12021202
1203-
:type semantic_reranking_options: Optional[dict[str, Any]]
12041203
:returns: A CosmosDict containing the reranking results. The structure typically includes results list with reranked documents and their relevance scores. Each result contains index, relevance_score, and optionally document.
12051204
:rtype: ~azure.cosmos.CosmosDict[str, Any]
12061205
:raises ~azure.cosmos.exceptions.CosmosHttpResponseError: If the semantic reranking operation fails.
@@ -1214,9 +1213,9 @@ async def semantic_rerank(
12141213
)
12151214

12161215
result = await inference_service.rerank(
1217-
reranking_context=reranking_context,
1216+
reranking_context=context,
12181217
documents=documents,
1219-
semantic_reranking_options=semantic_reranking_options
1218+
semantic_reranking_options=options
12201219
)
12211220

12221221
return result
@@ -1235,7 +1234,7 @@ async def replace_item(
12351234
match_condition: Optional[MatchConditions] = None,
12361235
priority: Optional[Literal["High", "Low"]] = None,
12371236
no_response: Optional[bool] = None,
1238-
retry_write: Optional[bool] = None,
1237+
retry_write: Optional[int] = None,
12391238
throughput_bucket: Optional[int] = None,
12401239
**kwargs: Any
12411240
) -> CosmosDict:
@@ -1262,9 +1261,9 @@ async def replace_item(
12621261
:keyword bool no_response: Indicates whether service should be instructed to skip
12631262
sending response payloads. When not specified explicitly here, the default value will be determined from
12641263
client-level options.
1265-
:keyword bool retry_write: Indicates whether the SDK should automatically retry this write operation, even if
1264+
:keyword int retry_write: Indicates how many times the SDK should automatically retry this write operation, even if
12661265
the operation is not guaranteed to be idempotent. This should only be enabled if the application can
1267-
tolerate such risks or has logic to safely detect and handle duplicate operations.
1266+
tolerate such risks or has logic to safely detect and handle duplicate operations. Default is None (no retries).
12681267
:keyword int throughput_bucket: The desired throughput bucket for the client
12691268
:keyword Sequence[str] excluded_locations: Excluded locations to be skipped from preferred locations. The locations
12701269
in this list are specified as the names of the azure Cosmos locations like, 'West US', 'East US' and so on.
@@ -1322,7 +1321,7 @@ async def patch_item(
13221321
match_condition: Optional[MatchConditions] = None,
13231322
priority: Optional[Literal["High", "Low"]] = None,
13241323
no_response: Optional[bool] = None,
1325-
retry_write: Optional[bool] = None,
1324+
retry_write: Optional[int] = None,
13261325
throughput_bucket: Optional[int] = None,
13271326
**kwargs: Any
13281327
) -> CosmosDict:
@@ -1355,9 +1354,9 @@ async def patch_item(
13551354
:keyword bool no_response: Indicates whether service should be instructed to skip
13561355
sending response payloads. When not specified explicitly here, the default value will be determined from
13571356
client-level options.
1358-
:keyword bool retry_write: Indicates whether the SDK should automatically retry this write operation, even if
1357+
:keyword int retry_write: Indicates how many times the SDK should automatically retry this write operation, even if
13591358
the operation is not guaranteed to be idempotent. This should only be enabled if the application can
1360-
tolerate such risks or has logic to safely detect and handle duplicate operations.
1359+
tolerate such risks or has logic to safely detect and handle duplicate operations. Default is None (no retries).
13611360
:keyword int throughput_bucket: The desired throughput bucket for the client
13621361
:keyword Sequence[str] excluded_locations: Excluded locations to be skipped from preferred locations. The locations
13631362
in this list are specified as the names of the azure Cosmos locations like, 'West US', 'East US' and so on.
@@ -1413,7 +1412,7 @@ async def delete_item(
14131412
etag: Optional[str] = None,
14141413
match_condition: Optional[MatchConditions] = None,
14151414
priority: Optional[Literal["High", "Low"]] = None,
1416-
retry_write: Optional[bool] = None,
1415+
retry_write: Optional[int] = None,
14171416
throughput_bucket: Optional[int] = None,
14181417
**kwargs: Any
14191418
) -> None:
@@ -1443,9 +1442,9 @@ async def delete_item(
14431442
in this list are specified as the names of the azure Cosmos locations like, 'West US', 'East US' and so on.
14441443
If all preferred locations were excluded, primary/hub location will be used.
14451444
This excluded_location will override existing excluded_locations in client level.
1446-
:keyword bool retry_write: Indicates whether the SDK should automatically retry this write operation, even if
1445+
:keyword int retry_write: Indicates how many times the SDK should automatically retry this write operation, even if
14471446
the operation is not guaranteed to be idempotent. This should only be enabled if the application can
1448-
tolerate such risks or has logic to safely detect and handle duplicate operations.
1447+
tolerate such risks or has logic to safely detect and handle duplicate operations. Default is None (no retries).
14491448
:keyword response_hook: A callable invoked with the response metadata.
14501449
:paramtype response_hook: Callable[[Mapping[str, str], None], None]
14511450
:keyword int throughput_bucket: The desired throughput bucket for the client

0 commit comments

Comments
 (0)