Skip to content

Conversation

vbabanin
Copy link
Member

@vbabanin vbabanin commented Aug 10, 2025

Description

Following a CSOT code walkthrough in scope of Client Bulk Write API, we identified several improvements to make the Client-Side Operations Timeout (CSOT) code more predictable, consistent, and maintainable. This PR introduces naming refinements, clearer APIs, and safer handling of TimeoutContext to improve readability and reduce potential misuse.

The main change in this PR is that methods whose execution time can be limited by a timeout, or which are executed on a particular ClientSession or RequestContext, must now accept a separate OperationContext parameter.

The guiding principle is to avoid storing OperationContext in fields whenever possible. Instead, the OperationContext is passed explicitly, making it more predictable where a timeout originates and easier to trace through the call chain. Since OperationContext propagates down the tree of method calls, it can also be overridden at any level.

Some exceptions remain in entities such as Cursor and ClientSession, which must hold a reference to a specific OperationContext for their entire lifecycle. However, when any of their methods is called, a new OperationContext is created from the original to overrode a tImeout and passed down the call chain. This makes it easier to trace overrides and insert debugging hooks in the methods where contexts are instantiated.

To further improve predictability and reasoning about the code, both OperationContext and TimeoutContext are now immutable.

Key changes

  • Previously, ClusterBinding, ConnectionSource, and Cursor all shared the same OperationContext (and thus the same TimeoutContext), creating hidden coupling that required ad-hoc workarounds such as overriding the global timeout state and rolling it back to avoid side effects , see TimeoutContext.java#L298-L305. This change decouples OperationContext from ClusterBinding and ConnectionSource, requiring callers to explicitly provide it when invoking APIs such as getConnectionSource(OperationContext) and getConnection(OperationContext). By making the context an explicit parameter rather than relying on scattered internal state, the API becomes more predictable, easier to reason about, less prone to subtle lifecycle bugs and easier to compare with the CSOT spec.
  • The core cursor logic has been extracted into CoreCursor, allowing both tailable and non-tailable cursor operations -whether in ITERATION or CURSOR_LIFETIME mode (as implemented by CommandBatchCursor) to wrap a CoreCursor and manage timeouts by passing an OperationContext to next, tryNext, and closemethods. This separation also enablesChangeStreamCursorto wrapCoreCursorand implement its distinct timeout semantics without conflicting withCommandBatchCursor’slogic. Previously,CommandBatchCursorcarried two unrelated concerns, including the resetTimeoutOnClosing flag, which existed solely to letChangeStreamCursor` override timeout behavior. The new approach enforces a more clear separation of concerns, with each cursor type independently managing its timeout policy.
    Diagrams to present the changes made in cursors: CSOT refactoring #1781 (comment)
  • SyncOperationHelper and AsyncOperationHelper now propagate OperationContext to callbacks passed into withSourceAndConnection. Callbacks receive both the Connection and the OperationContext. Within withSourceAndConnection, the OperationContext passed to the callback includes minRTT, as the method creates a new context after selecting the ConnectionSource. This allows setting minRtt without mutating the original context from Operation.execute(), so in a callback a caller can chose what OperationContext to use further in the call chain, the original one without minRtt or the one with minRtt set.
  • withSourceAndConnection encapsulates the server selection timeout logic, computing the effective timeout (min(serverSelectionTimeout, timeoutMS)) per the specification and applying it to both server selection and connection checkout. This keeps the logic centralized and original context immutable.

JAVA-5640 - CSOT clarity enhancement/refactoring.
JAVA-5644 - this issue is also fixed since TimeoutContext is fully immutable now.

katcharov and others added 6 commits July 4, 2025 10:54
Make TimeoutContext immutable.
# Conflicts:
#	driver-core/src/main/com/mongodb/internal/connection/OperationContext.java
#	driver-core/src/main/com/mongodb/internal/operation/AggregateOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/AggregateOperationImpl.java
#	driver-core/src/main/com/mongodb/internal/operation/AggregateToCollectionOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/BaseFindAndModifyOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/ChangeStreamOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/ClientBulkWriteOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/CommandReadOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/CountDocumentsOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/CountOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/CreateCollectionOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/CreateIndexesOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/CreateViewOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/DistinctOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/DropCollectionOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/DropDatabaseOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/DropIndexOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/EstimatedDocumentCountOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/FindOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/ListCollectionsOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/ListDatabasesOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/ListIndexesOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/ListSearchIndexesOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/MapReduceToCollectionOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/MapReduceWithInlineResultsOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/MixedBulkWriteOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/ReadOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/ReadOperationCursor.java
#	driver-core/src/main/com/mongodb/internal/operation/ReadOperationMapReduceCursor.java
#	driver-core/src/main/com/mongodb/internal/operation/RenameCollectionOperation.java
#	driver-core/src/main/com/mongodb/internal/operation/WriteOperation.java
#	driver-core/src/test/functional/com/mongodb/ClusterFixture.java
#	driver-core/src/test/functional/com/mongodb/OperationFunctionalSpecification.groovy
#	driver-core/src/test/unit/com/mongodb/internal/operation/OperationUnitSpecification.groovy
#	driver-legacy/src/main/com/mongodb/LegacyMixedBulkWriteOperation.java
#	driver-legacy/src/main/com/mongodb/MongoClient.java
#	driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/MapReducePublisherImpl.java
#	driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/OperationExecutorImpl.java
#	driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/VoidReadOperationThenCursorReadOperation.java
#	driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/VoidWriteOperationThenCursorReadOperation.java
#	driver-sync/src/main/com/mongodb/client/internal/MapReduceIterableImpl.java
#	driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java
@vbabanin vbabanin self-assigned this Aug 10, 2025
Copy link
Member Author

@vbabanin vbabanin Aug 13, 2025

Choose a reason for hiding this comment

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

Current cursor diagram

diagram

Refactored cursor diagram

diagram

@vbabanin vbabanin requested a review from Copilot August 13, 2025 05:14
Copilot

This comment was marked as outdated.

@vbabanin vbabanin requested a review from Copilot August 13, 2025 18:02
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors the Client Side Operation Timeout (CSOT) implementation by removing the OperationContext from binding classes and instead passing it explicitly to operation execution methods. The changes modernize the API design and improve consistency across sync and async operations.

Key changes:

  • Removed getOperationContext() methods from binding interfaces and implementations
  • Modified operation execution methods to accept OperationContext as an explicit parameter
  • Updated connection source methods to take OperationContext as parameter
  • Refactored ClientSessionBinding to create session contexts at execution time rather than during binding creation

Reviewed Changes

Copilot reviewed 149 out of 150 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
driver-sync/src/test/unit/com/mongodb/client/internal/ClientSessionBindingSpecification.groovy Updated test to verify binding delegates to wrapped binding with explicit OperationContext
driver-sync/src/test/resources/logback-test.xml Changed log level from INFO to DEBUG for testing
driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java Added imports and minor test method name changes
driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java Refactored to create OperationContext with session context at execution time
driver-sync/src/main/com/mongodb/client/internal/MapReduceIterableImpl.java Updated operation execution methods to accept OperationContext parameter
driver-sync/src/main/com/mongodb/client/internal/CryptConnection.java Renamed timeout variable for consistency
driver-sync/src/main/com/mongodb/client/internal/CryptBinding.java Removed getOperationContext() method and updated connection source methods
driver-sync/src/main/com/mongodb/client/internal/Crypt.java Parameter renaming and method signature updates
driver-sync/src/main/com/mongodb/client/internal/CommandMarker.java Parameter renaming from operationTimeout to timeout
driver-sync/src/main/com/mongodb/client/internal/CollectionInfoRetriever.java Parameter renaming for consistency
driver-sync/src/main/com/mongodb/client/internal/ClientSessionBinding.java Major refactoring to remove OperationContext from binding and create session context at execution time
driver-reactive-streams/src/test/unit/com/mongodb/reactivestreams/client/internal/ClientSessionBindingSpecification.groovy Similar updates to sync version for async binding tests

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@vbabanin vbabanin requested a review from rozza August 13, 2025 19:20
@vbabanin vbabanin marked this pull request as ready for review August 19, 2025 15:11
@vbabanin vbabanin requested a review from a team as a code owner August 19, 2025 15:11
Copy link
Member

@rozza rozza left a comment

Choose a reason for hiding this comment

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

Looks really good, some questions, comments, minor nits and suggested changes :)

vbabanin and others added 6 commits September 5, 2025 20:27
…Context.java

Co-authored-by: Ross Lawley <ross.lawley@gmail.com>
…dOperation.java

Co-authored-by: Ross Lawley <ross.lawley@gmail.com>
Remove DEBUG level logging.
Remove redundant methods.
# Conflicts:
#	driver-core/src/main/com/mongodb/internal/operation/AsyncCommandBatchCursor.java
#	driver-core/src/main/com/mongodb/internal/operation/CommandBatchCursor.java
@vbabanin vbabanin requested a review from rozza September 17, 2025 14:54
Copy link
Member

@rozza rozza left a comment

Choose a reason for hiding this comment

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

A few more nits but looking very close

vbabanin and others added 8 commits September 23, 2025 04:26
…eStreamBatchCursor.java

Co-authored-by: Ross Lawley <ross.lawley@gmail.com>
…eStreamBatchCursor.java

Co-authored-by: Ross Lawley <ross.lawley@gmail.com>
…eStreamBatchCursor.java

Co-authored-by: Ross Lawley <ross.lawley@gmail.com>
…amBatchCursor.java

Co-authored-by: Ross Lawley <ross.lawley@gmail.com>
…eStreamBatchCursor.java

Co-authored-by: Ross Lawley <ross.lawley@gmail.com>
@vbabanin vbabanin requested a review from rozza September 24, 2025 10:15
Copy link
Member

@rozza rozza left a comment

Choose a reason for hiding this comment

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

LGTM!

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.

3 participants