-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Session Token Management APIs #36971
base: main
Are you sure you want to change the base?
Conversation
API change check APIView has identified API level changes in this PR and created following API reviews. |
…into tvaron3/sessionTokenHelper
…xinlian12/azure-sdk-for-python into tvaron3/sessionTokenHelper
…into tvaron3/sessionTokenHelper
/azp run python - cosmos - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
…into tvaron3/sessionTokenHelper
sdk/cosmos/azure-cosmos/azure/cosmos/_cosmos_client_connection.py
Outdated
Show resolved
Hide resolved
sdk/cosmos/azure-cosmos/azure/cosmos/_cosmos_client_connection.py
Outdated
Show resolved
Hide resolved
sdk/cosmos/azure-cosmos/azure/cosmos/_cosmos_client_connection.py
Outdated
Show resolved
Hide resolved
""" | ||
return FeedRangeEpk(await self._get_epk_range_for_partition_key(partition_key)) | ||
|
||
async def is_feed_range_subset(self, parent_feed_range: FeedRange, child_feed_range: FeedRange) -> bool: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this doesn't need to be on the client at all? Can this not simply be a utility on the FeedRange
object itself?
As a Python developer, it would be cool if I could just do something like:
if child_feed_range in parent_feed_range:
Or failing that, even something like:
if parent_feed_range.contains(child_feed_range):
if child_feed_range.is_subset(parent_feed_range):
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added container information to the feed ranges and a check to make sure the feed ranges inputted correspond to the correct container. Feed ranges are scoped to a container.
@@ -1319,3 +1332,40 @@ async def read_feed_ranges( | |||
|
|||
return [FeedRangeEpk(Range.PartitionKeyRangeToRange(partitionKeyRange)) | |||
for partitionKeyRange in partition_key_ranges] | |||
|
|||
async def get_updated_session_token(self, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't look like it needs to be on the client at all, nor does it look like it should be async?
This could also probably be a utility on the FeedRange
object:
target_feed_range.get_session_tokens(feed_ranges_to_session_tokens)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added container information to the feed ranges and a check to make sure the feed ranges inputted correspond to the correct container. Feed ranges and session tokens are scoped to a container.
/azp run python - cosmos - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
/azp run python - cosmos - tests |
Azure Pipelines successfully started running 1 pipeline(s). |
Problem Statement
Customers that maintain their own session tokens could need ways to get the most updated session token. For example, a customer using multiple clients and keeping their session token in a cache could face race conditions when updating the cache. If a customer has a high cardinality of logical partition keys, it will mean storing many session tokens. Addresses #36286.
Changes
APIs
Container.py
def get_updated_session_token(feed_ranges_to_session_tokens: List, target_feed_range: str): --> str
- Requires no metadata callsdef feed_range_for_logical_partition(pk: PartitionKey): --> FeedRange
- There could be metadata calls for the collection properties, but it is cacheddef is_feed_range_subset(parent_feed_range: str, child_feed_range: str): --> bool
- no metadata calls are necessary for thisdef read_feed_ranges(num_of_ranges: int): --> List
- This would be out of scope for this pr. This would require metadata calls to setup the pkrange cacheSamples
Tradeoffs to Storing Session Token by Logical Partition Key vs Physical Partition vs Artificial Feed Ranges
Storing session tokens by logical partition keys has the benefit of requiring fewer updates. This approach minimizes the number of concurrent updates, which can be advantageous in terms of performance. Additionally, during a failover, the availability impact is reduced because there are fewer updates to the session tokens. For example, if Region A fails over and the client has a session token with a global LSN of 42, the next request would go to Region B, where the LSN on the replicas might be 32 due to replication lag. This discrepancy would trigger the 404 / 1002 exception (Read Session Not Available) for any requests with this session token.
On the other hand, using physical partitions or artificial feed ranges involves an optimistic get from the cache, as the number of concurrent updates will increase significantly. However, the benefit of this approach is that the cardinality of the stored session tokens would be significantly less, which can simplify management and reduce overhead. It would also mean a bigger blast radius during a failover as the scenario shown above would be more common.
Implementation
Glossary
Session Token Format: PKRangeId:VersionNumber#GlobalLSN#RegionId1=LocalLSN1#RegionId2=LocalLSN2...
Compound session token: Comma separated session tokens
Some Scenarios
Flow
For the
def is_feed_range_subset(parent_feed_range: str, child_feed_range: str): --> str
api, the implementation will follow the .NET implementation in this pr https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4566/files. Merging session tokens will be done in the same way as the session container. Merging will take higher version number, higher global lsn, and higher local lsns.