-
Notifications
You must be signed in to change notification settings - Fork 396
feat: Changes for Multiplex Session in Spanner.Data #15335
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
base: main
Are you sure you want to change the base?
feat: Changes for Multiplex Session in Spanner.Data #15335
Conversation
Summary of ChangesHello @purva9413, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request implements a significant architectural change by introducing a multiplexed session management system for Google Cloud Spanner. The new Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
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.
Code Review
This pull request introduces significant changes to support multiplexed sessions in Spanner, which is a great feature. The core logic is refactored around ManagedSession and ManagedTransaction, moving away from the session pool model for this use case. The changes are extensive and touch many parts of the data access layer and tests. The new tests for ManagedSession and retriable transactions are good additions.
I've found one critical issue in the session refresh logic that could lead to race conditions. I've also suggested an improvement to an integration test to better validate the concurrency handling of multiplexed sessions. Overall, the changes are well-structured and align with the goal of the PR.
|
|
||
| // Hard refresh or initial session creation, | ||
| // wrap this in a Task since the _sessionCreationTask task could also be null if refresh completes/fails. | ||
| Task currentCreationTask = Task.Run(() => TriggerRefresh(HardRefreshIntervalInDays)); |
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.
The current implementation Task.Run(() => TriggerRefresh(HardRefreshIntervalInDays)) creates a Task<Task>. Awaiting this task only completes the outer task and returns the inner task from TriggerRefresh, but does not wait for the session creation itself to finish. This could lead to race conditions where a stale or invalid session is used. The Task.Run is unnecessary and incorrect here. You should directly assign the task returned by TriggerRefresh.
Task currentCreationTask = TriggerRefresh(HardRefreshIntervalInDays);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.
Not sure how true this explanation is, my understanding is the wrapper/outer task will act as a sort of proxy for the inner task and waiting on the outer task is as good as waiting on the inner task.
Having said that, I realized I possibly do not need this outer task and can just call TriggerRefresh directly and wait on it in this case (since the result of the function would be null and would not affect the ConfigureAwait(false) call on it).
| for (var i = 0; i < concurrentThreads; i++) | ||
| { | ||
| await IncrementByOneAsync(transactions[i], uniqueRowId); | ||
| } |
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.
The test TestMultipleTransactionWritesOnSameSession executes the transactions sequentially in a loop. To better test the capabilities of a multiplexed session to handle multiple operations, you should consider running these transactions concurrently.
var tasks = new List<Task>();
for (var i = 0; i < concurrentThreads; i++)
{
tasks.Add(IncrementByOneAsync(transactions[i], uniqueRowId));
}
await Task.WhenAll(tasks);chore: Remove Task.Run for creating the session
chore: Remove Task.Run for creating the session
b3d766e to
caef94e
Compare
…gle-cloud-dotnet into multiplex-split-v1
… dictionary in SessionPoolManager chore: Remove unused param from ManagedSession method
7162c87 to
1c83cc4
Compare
chore: Add extra condition for emulator tests with concurrent txn in ManagedSession chore: Skip paritioned tests on emulator
1c83cc4 to
7e59635
Compare
This PR is based on top off the first split PR - #15322