Skip to content

refactor(spanner): decouple read-only transactions from async result sets - #14902

Open
olavloite wants to merge 2 commits into
mainfrom
spanner-decouple-tx-from-async-result-set
Open

olavloite wants to merge 2 commits into
mainfrom
spanner-decouple-tx-from-async-result-set

Conversation

@olavloite

Copy link
Copy Markdown
Contributor

Decouple multi-use read-only transactions from internal async result set implementation details by introducing a dedicated lifecycle callback.

Key improvements in this change:

  • Replaces the anonymous subclass in read-only transactions with a clean callback that signals when an asynchronous query either begins execution or is closed without starting.
  • Lazily resolves the underlying query stream so that closing an async query before it begins execution no longer starts the query or opens an RPC stream, preventing unnecessary network calls and session allocations.
  • Permits safe inspection of query statistics and metadata after a result set has been closed.
  • Adds comprehensive unit tests for the decoupled lifecycle, post-close inspections, and closed-state error handling.

@olavloite
olavloite requested review from a team as code owners November 3, 2026 09:55

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

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 refactors AsyncResultSetImpl to introduce an onStartOrClose callback, allowing callers like MultiUseReadOnlyTransaction to track the query lifecycle more reliably. It simplifies the transaction logic by removing the anonymous class override and tracking state internally within AsyncResultSetImpl using synchronized monitor flags (startOrCloseNotified, delegateInitialized, delegateClosed). Additionally, it ensures that calling next() after closing the result set throws an IllegalStateException, and adds comprehensive unit tests to verify these behaviors. There are no review comments, and the implementation looks solid, so I have no feedback to provide.

@olavloite
olavloite force-pushed the spanner-decouple-tx-from-async-result-set branch from 62b05bd to aa1681b Compare November 3, 2026 15:01
@olavloite

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

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 an onStartOrClose callback to AsyncResultSetImpl to better track the query lifecycle, allowing callers like MultiUseReadOnlyTransaction to simplify pending start tracking. It also refactors delegate initialization and closing logic to prevent resource leaks and adds comprehensive unit tests. The review feedback highlights two important improvements: first, checking this.closed instead of delegateClosed in getDelegate() to prevent unnecessary RPC streams when closed immediately after setting a callback; second, wrapping the onStartOrClose callback execution in a try-catch block to avoid masking primary exceptions.

@olavloite
olavloite force-pushed the spanner-decouple-tx-from-async-result-set branch from aa1681b to 7d470a9 Compare November 3, 2026 15:25
@olavloite

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

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 refactors AsyncResultSetImpl to introduce an onStartOrClose callback, allowing callers like MultiUseReadOnlyTransaction to track the query lifecycle more reliably. It simplifies the transaction logic by removing the custom anonymous subclass and replacing it with this callback. Additionally, the changes improve resource management, ensure proper delegate closing, add robust error handling for callback execution, and introduce comprehensive unit tests to verify these behaviors. No review comments were provided, so there is no feedback to address.

@olavloite
olavloite force-pushed the spanner-decouple-tx-from-async-result-set branch from 7d470a9 to 4c74251 Compare November 3, 2026 20:02
@olavloite

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

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 refactors AsyncResultSetImpl to introduce an onStartOrClose callback, allowing callers like MultiUseReadOnlyTransaction to reliably track the query lifecycle. It improves thread safety by synchronizing listener operations, refactors delegate retrieval and exception handling into a unified getDelegate() method, and adds robust argument validation and resource cleanup. Additionally, the complex tracking logic in MultiUseReadOnlyTransaction is simplified, and comprehensive unit tests are added to cover various lifecycle and edge-case scenarios. I have no further feedback to provide as the changes are well-implemented and thoroughly tested.

@olavloite
olavloite force-pushed the spanner-decouple-tx-from-async-result-set branch from 4c74251 to 1c76f9e Compare November 4, 2026 14:59
@olavloite

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

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 refactors AsyncResultSetImpl to support an onStartOrClose callback, allowing callers like MultiUseReadOnlyTransaction to track query lifecycles more reliably. It introduces synchronized state variables to manage lazy initialization, early-close reconciliation, and exception propagation, while simplifying transaction tracking. Additionally, extensive unit tests are added to verify these behaviors. The feedback suggests optimizing listener notification in AsyncResultSetImpl by checking if the listeners list is empty before allocating a new ArrayList copy, which avoids unnecessary object allocation in the common case.

@olavloite
olavloite force-pushed the spanner-decouple-tx-from-async-result-set branch from 1c76f9e to 88a3115 Compare November 4, 2026 15:13
@olavloite

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

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 refactors AsyncResultSetImpl to introduce an onStartOrClose callback for tracking query lifecycle, simplifying the resource tracking logic in MultiUseReadOnlyTransaction. It improves thread safety by synchronizing listener operations and lazily initializing the delegate result set. Feedback suggests catching exceptions thrown by individual listeners during notification to prevent a single failing listener from blocking others.

…sets

Decouple multi-use read-only transactions from internal async result set
implementation details by introducing a dedicated lifecycle callback.

Key improvements in this change:
- Replaces the anonymous subclass in read-only transactions with a clean
  callback that signals when an asynchronous query either begins execution
  or is closed without starting.
- Lazily resolves the underlying query stream so that closing an async query
  before it begins execution no longer starts the query or opens an RPC
  stream, preventing unnecessary network calls and session allocations.
- Permits safe inspection of query statistics and metadata after a result
  set has been closed.
- Adds comprehensive unit tests for the decoupled lifecycle, post-close
  inspections, and closed-state error handling.
@olavloite
olavloite force-pushed the spanner-decouple-tx-from-async-result-set branch from 88a3115 to c35a520 Compare November 4, 2026 15:26
@olavloite

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

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 refactors AsyncResultSetImpl to introduce an onStartOrClose lifecycle callback, enabling callers like MultiUseReadOnlyTransaction to track query execution and closure. It adds lazy initialization of the underlying delegate ResultSet and improves synchronization during state transitions. Comprehensive unit tests are also added. However, a critical issue was identified in the close() method: if called during the STREAMING_INITIALIZED state, it fails to close the delegate or trigger the lifecycle callback, potentially causing resource leaks and deadlocks.

@olavloite olavloite added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Nov 4, 2026
@yoshi-kokoro yoshi-kokoro removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Nov 4, 2026

This branch has not been deployed

No deployments
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