Skip to content

Conversation

@purva9413
Copy link
Contributor

This PR is based on top off the first split PR - #15322

@purva9413 purva9413 requested a review from a team as a code owner December 18, 2025 00:09
@purva9413 purva9413 changed the title Multiplex split spanner data feat: Changes for Multiplex Session in Spanner.Data Dec 18, 2025
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @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 ManagedSession and ManagedTransaction components streamline how database sessions and transactions are acquired, refreshed, and utilized, aiming to enhance efficiency and resource management. This refactoring impacts core connection and transaction logic, with corresponding updates across the test suite to validate the new behavior.

Highlights

  • Multiplexed Session Management: Introduced new ManagedSession and ManagedTransaction classes to handle multiplexed Spanner sessions, allowing multiple concurrent transactions or operations to share a single underlying database connection.
  • Session Lifecycle Refactoring: Refactored SpannerConnection to utilize the new ManagedSession model, replacing the previous SessionPool mechanism for acquiring and managing sessions. This includes updates to connection opening, transaction acquisition, and session shutdown logic.
  • Retriable Transaction Enhancements: The RetriableTransaction now explicitly tracks the _prevTransactionId to correctly handle transaction retries within multiplexed sessions, ensuring continuity and proper state management.
  • Integration and Unit Test Updates: Extensive updates to integration and unit tests across the Google.Cloud.Spanner.Data and Google.Cloud.Spanner.V1 projects to align with the new ManagedSession and ManagedTransaction architecture. This includes new test files and modifications to existing test setups and assertions.
  • Emulator vs. Production Error Handling: Adjusted error handling in integration tests (MutationsTests.cs, WriteTests.cs) to account for differences in exception messages and error codes between the Spanner emulator and the production environment when using multiplexed sessions.
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a 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));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

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);

Copy link
Contributor Author

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).

Comment on lines +102 to +105
for (var i = 0; i < concurrentThreads; i++)
{
await IncrementByOneAsync(transactions[i], uniqueRowId);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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);

@purva9413 purva9413 force-pushed the multiplex-split-spanner-data branch 4 times, most recently from b3d766e to caef94e Compare December 26, 2025 19:45
@purva9413 purva9413 force-pushed the multiplex-split-spanner-data branch 2 times, most recently from 7162c87 to 1c83cc4 Compare December 26, 2025 21:43
chore: Add extra condition for emulator tests with concurrent txn in ManagedSession

chore: Skip paritioned tests on emulator
@purva9413 purva9413 force-pushed the multiplex-split-spanner-data branch from 1c83cc4 to 7e59635 Compare December 26, 2025 22:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants