-
Notifications
You must be signed in to change notification settings - Fork 539
[Internal] DTS: Adds logic to merge session data from DTC response into SessionContainer #5705
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
Changes from all commits
a4aa5e3
8508fe7
6387d62
081c9d3
f9b31e2
d7b6a03
68a6fd6
c86579d
92f75ac
e217d8a
b78f663
52ae176
1302d61
07c97c3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,11 +7,13 @@ namespace Microsoft.Azure.Cosmos | |
| using System; | ||
| using System.Collections.Generic; | ||
| using System.IO; | ||
| using System.Net; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
| using Microsoft.Azure.Cosmos.Core.Trace; | ||
| using Microsoft.Azure.Cosmos.Tracing; | ||
| using Microsoft.Azure.Documents; | ||
| using Microsoft.Azure.Documents.Collections; | ||
|
|
||
| internal class DistributedTransactionCommitter | ||
| { | ||
|
|
@@ -75,13 +77,20 @@ private async Task<DistributedTransactionResponse> ExecuteCommitAsync( | |
|
|
||
| cancellationToken.ThrowIfCancellationRequested(); | ||
|
|
||
| return await DistributedTransactionResponse.FromResponseMessageAsync( | ||
| DistributedTransactionResponse response = await DistributedTransactionResponse.FromResponseMessageAsync( | ||
| responseMessage, | ||
| serverRequest, | ||
| this.clientContext.SerializerCore, | ||
| serverRequest.IdempotencyToken, | ||
| trace, | ||
| cancellationToken); | ||
|
|
||
| DistributedTransactionCommitter.MergeSessionTokens( | ||
| response, | ||
| serverRequest, | ||
| this.clientContext.DocumentClient.sessionContainer); | ||
|
|
||
| return response; | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -100,8 +109,59 @@ private static void EnrichRequestMessage(RequestMessage requestMessage, Distribu | |
| requestMessage.UseGatewayMode = true; | ||
| } | ||
|
|
||
| internal static void MergeSessionTokens( | ||
| DistributedTransactionResponse response, | ||
| DistributedTransactionServerRequest serverRequest, | ||
| ISessionContainer sessionContainer) | ||
| { | ||
| // Mirror the pattern used by GatewayStoreModel.CaptureSessionTokenAndHandleSplitAsync. | ||
| // after a response is received, store each operation's session token in the SessionContainer | ||
| // so that subsequent Session-consistency reads on the affected collections can use the latest token | ||
| // without getting ReadSessionNotAvailable. | ||
| // | ||
| // DTC spans multiple collections so the server embeds per-operation session | ||
| // tokens in the JSON body; those are already parsed into DistributedTransactionOperationResult.SessionToken, | ||
| // but we must explicitly push them into the SessionContainer. | ||
|
|
||
| if (response == null || response.Count == 0 || serverRequest == null || sessionContainer == null) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| RequestNameValueCollection headers = new RequestNameValueCollection(); | ||
|
|
||
| for (int i = 0; i < response.Count; i++) | ||
| { | ||
| DistributedTransactionOperationResult result = response[i]; | ||
|
Meghana-Palaparthi marked this conversation as resolved.
|
||
| DistributedTransactionOperation operation = serverRequest.Operations[result.Index]; | ||
|
|
||
| if (string.IsNullOrEmpty(result.SessionToken) || string.IsNullOrEmpty(operation.CollectionResourceId)) | ||
| { | ||
| continue; | ||
| } | ||
|
|
||
| if (result.StatusCode == HttpStatusCode.NotFound | ||
| && result.SubStatusCode == SubStatusCodes.ReadSessionNotAvailable) | ||
| { | ||
| continue; | ||
| } | ||
|
|
||
| // Note: each SetSessionToken call acquires a write lock on the SessionContainer. | ||
| // For a future optimization, consider a batch-update API on ISessionContainer to | ||
| // reduce lock acquisitions when multiple operations target the same collection. | ||
| headers.Clear(); | ||
| headers[HttpConstants.HttpHeaders.SessionToken] = result.SessionToken; | ||
|
|
||
| sessionContainer.SetSessionToken( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optimization: Each operation inside does a locking, wondering if a new API for batch updates for a collection will help. /cc: @FabianMeiswinkel
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you please create a follow-up GitHub issue to track it.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Created a GitHub issue: #5729 |
||
| operation.CollectionResourceId, | ||
| DistributedTransactionConstants.GetCollectionFullName(operation.Database, operation.Container), | ||
| headers); | ||
| } | ||
| } | ||
|
|
||
| private Task AbortTransactionAsync(CancellationToken cancellationToken) | ||
| { | ||
| // TODO: Implement abort for the two-phase commit path. | ||
| throw new NotImplementedException(); | ||
| } | ||
| } | ||
|
|
||
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.
Optimization: Follow-up limit session merge for only SESSION, MM