diff --git a/source/connection/specify-connection-options.txt b/source/connection/specify-connection-options.txt index 73bdad749..e793af476 100644 --- a/source/connection/specify-connection-options.txt +++ b/source/connection/specify-connection-options.txt @@ -22,6 +22,7 @@ Specify Connection Options .. toctree:: Stable API + Limit Execution Time Connection Pools Cluster Settings Server Settings @@ -38,6 +39,7 @@ This section describes the MongoDB connection and authentication options available in the {+driver-short+}. You can specify the following connection options: - :ref:`Stable API ` +- :ref:`Limit Server Execution Time ` - :ref:`Connection Pools ` - :ref:`Cluster Settings ` - :ref:`Server Settings ` diff --git a/source/connection/specify-connection-options/connection-pools.txt b/source/connection/specify-connection-options/connection-pools.txt index 4fdc3bf2e..788f1ac4f 100644 --- a/source/connection/specify-connection-options/connection-pools.txt +++ b/source/connection/specify-connection-options/connection-pools.txt @@ -87,10 +87,12 @@ see the corresponding syntax: * - ``maxPoolSize`` - - Maximum number of connections opened in the pool. When the - connection pool reaches the maximum number of connections, new - connections wait up until to the value of - ``waitQueueTimeoutMS``. + - Maximum number of connections opened in the pool. If an + operation needs a new connection while the connection pool has + ``maxPoolSize`` connections open, the new + operation waits for a new connection to open. To limit this + waiting time, use the single timeout setting. To learn more, + see the :ref:`java-csot` guide. *Default:* ``100`` @@ -102,11 +104,15 @@ see the corresponding syntax: *Default*: ``0`` - * - ``waitQueueTimeoutMS`` + * - ``waitQueueTimeoutMS`` *(deprecated)* - - Maximum wait time in milliseconds that an operation can wait for + - This option is deprecated. You can configure this timeout by + setting the the :ref:`client-level timeout ` + instead. + + Maximum wait time in milliseconds that an operation can wait for a connection to become available. A value of ``0`` means there - is no limit. + is no limit. *Default*: ``120000`` (120 seconds) diff --git a/source/connection/specify-connection-options/csot.txt b/source/connection/specify-connection-options/csot.txt new file mode 100644 index 000000000..cda0ec56c --- /dev/null +++ b/source/connection/specify-connection-options/csot.txt @@ -0,0 +1,319 @@ +.. _java-csot: + +=========================== +Limit Server Execution Time +=========================== + +.. contents:: On this page + :local: + :backlinks: none + :depth: 2 + :class: singlecol + +.. facet:: + :name: genre + :values: reference + +.. meta:: + :keywords: error, blocking, thread, task, code example + +Overview +-------- + +When you use the {+driver-short+} to perform a server operation, you can also +limit the amount of time in which the server can finish the operation. To do so, +specify a **client-side operation timeout (CSOT)**. The timeout applies to all +steps needed to complete the operation, including server selection, connection +checkout, and server-side execution. When the timeout expires, the +{+driver-short+} raises a timeout exception. + +.. note:: Experimental Feature + + The CSOT feature is experimental and might change in future driver + releases. + +timeoutMS Option +---------------- + +To specify a timeout when connecting to a MongoDB deployment, set the +``timeoutMS`` connection option to the timeout length in milliseconds. You can +set the ``timeoutMS`` option in the following ways: + +- Calling the ``timeout()`` method from the + ``MongoClientSettings.Builder`` class +- Setting the ``timeoutMS`` parameter in your connection string + +The following code examples set a client-level timeout of ``200`` milliseconds. +Select the :guilabel:`MongoClientSettings` or :guilabel:`Connection +String` tab to see the corresponding code. + +.. tabs:: + + .. tab:: MongoClientSettings + :tabid: mongoclientsettings + + .. literalinclude:: /includes/connect/CsotExample.java + :language: java + :start-after: start-mongoclientsettings + :end-before: end-mongoclientsettings + :dedent: + :emphasize-lines: 3 + + .. tab:: Connection String + :tabid: connection-string + + .. literalinclude:: /includes/connect/CsotExample.java + :language: java + :start-after: start-string + :end-before: end-string + :dedent: + +Accepted Timeout Values +~~~~~~~~~~~~~~~~~~~~~~~ + +The following table describes the timeout behavior corresponding to the +accepted values for ``timeoutMS``: + +.. list-table:: + :header-rows: 1 + :widths: 25 75 + + * - Value + - Behavior + + * - Positive integer + - Sets the timeout to use for operation completion. + + * - ``0`` + - Specifies that operations never time out. + + * - ``null`` or unset + - | Defers the timeout behavior to the following settings: + + - :manual:`waitQueueTimeoutMS ` + - :manual:`socketTimeoutMS ` + - :manual:`wTimeoutMS ` + - :manual:`maxTimeMS ` + - `maxCommitTimeMS <{+core-api+}/TransactionOptions.Builder.html#maxCommitTime(java.lang.Long,java.util.concurrent.TimeUnit)>`__ + + | These settings are deprecated and are ignored if you set ``timeoutMS``. + +If you specify the ``timeoutMS`` option, the driver automatically applies the +specified timeout to each server operation. The following code example specifies +a timeout of ``200`` milliseconds at the client level, and then calls the +``MongoCollection.insertOne()`` method: + +.. literalinclude:: /includes/connect/CsotExample.java + :language: java + :start-after: start-operation-timeout + :end-before: end-operation-timeout + :dedent: + +Timeout Inheritance +~~~~~~~~~~~~~~~~~~~ + +When you specify the ``timeoutMS`` option, the driver applies the timeout +according to the same inheritance behaviors as the other {+driver-short+} options. +The following table describes how the timeout value is inherited at each level: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Level + - Inheritance Description + + * - Operation + - Takes the highest precedence and overrides the timeout + options that you set at any other level. + + * - Transaction + - Takes precedence over the timeout value that you set at the session, + collection, database, or client level. + + * - Session + - Applies to all transactions and operations within + that session, unless you set a different timeout value at those + levels. + + * - Database + - Applies to all sessions and operations within that + database, unless you set a different timeout value at those + levels. + + * - Collection + - Applies to all sessions and operations on that + collection, unless you set a different timeout value at those + levels. + + * - Client + - Applies to all databases, collections, sessions, transactions, and + operations within that client that do not otherwise specify + ``timeoutMS``. + +For more information on overrides and specific options, see the following +:ref:`java-csot-overrides` section. + +.. _java-csot-overrides: + +Overrides +--------- + +The {+driver-short+} supports various levels of configuration to control the +behavior and performance of database operations. + +You can specify a ``timeoutMS`` option at a more specific level to override the +client-level configuration. The table in the preceding section describes +the levels at which you can specify a timeout setting. This allows you +to customize timeouts based on the needs of individual operations. + +The following example demonstrates how a collection-level timeout +configuration can override a client-level timeout configuration: + +.. literalinclude:: /includes/connect/CsotExample.java + :language: java + :start-after: start-override + :end-before: end-override + :dedent: + :emphasize-lines: 10 + +.. _java-csot-transaction: + +Transactions +~~~~~~~~~~~~ + +When you create a new `ClientSession <{+driver-api+}/ClientSession.html>`__ +instance to implement a transaction, use the ``defaultTimeout()`` method +when building a ``ClientSessionOptions`` instance. You can use this +option to specify the timeout for the following methods: + +- `commitTransaction() <{+driver-api+}/ClientSession.html#commitTransaction()>`__ +- `abortTransaction() <{+driver-api+}/ClientSession.html#abortTransaction()>`__ +- `withTransaction() <{+driver-api+}/ClientSession.html#withTransaction(com.mongodb.client.TransactionBody)>`__ +- `close() <{+core-api+}/session/ClientSession.html#close()>`__ + +The following code demonstrates how to set the ``defaultTimeout`` when +instantiating a ``ClientSession``: + +.. literalinclude:: /includes/connect/CsotExample.java + :language: java + :start-after: start-session-timeout + :end-before: end-session-timeout + :dedent: + +If you do not specify the ``defaultTimeout``, the driver uses the timeout +value set on the parent ``MongoClient``. + +You can also set a transaction-level timeout by calling the ``timeout()`` +method when building a ``TransactionOptions`` instance. Setting this +option applies a timeout to all operations performed in the scope of the +transaction: + +.. literalinclude:: /includes/connect/CsotExample.java + :language: java + :start-after: start-transaction-timeout + :end-before: end-transaction-timeout + :dedent: + +To learn more about transactions, see the :ref:`java-fundamentals-transactions` guide. + +Client Encryption +~~~~~~~~~~~~~~~~~ + +When you use Client-Side Field Level Encryption (CSFLE), the driver uses the +``timeoutMS`` option to limit the time allowed for encryption and decryption +operations. You can set a timeout option for your ``ClientEncryption`` +instance by calling the ``timeout()`` method when building a +``ClientEncryptionSettings`` instance. + +If you specify the timeout when you construct a +``ClientEncryption`` instance, the timeout controls the lifetime of all operations +performed on that instance. If you do not provide a timeout when +instantiating ``ClientEncryption``, the instance +inherits the timeout setting from the ``MongoClient`` used in the +``ClientEncryption`` constructor. + +If you set ``timeoutMS`` both on the client and directly in +``ClientEncryption``, the value provided to ``ClientEncryption`` takes +precedence. + +.. _java-csot-cursor: + +Cursors +------- + +Cursors offer configurable timeout settings when using the CSOT feature. You can +adjust cursor handling by configuring either the cursor lifetime or cursor +iteration mode. To configure the timeout mode, use the ``timeoutMode()`` +method when performing any operation that returns an ``Iterable``. + +For operations that create cursors, the timeout setting can either cap the +lifetime of the cursor or be applied separately to the original +operation and all subsequent calls. + +.. note:: Inherited Timeout + + Setting a cursor timeout mode requires that you set a timeout either + in the ``MongoClientSettings``, on ``MongoDatabase``, or on + ``MongoCollection``. + +To learn more about cursors, see the :ref:`java-fundamentals-cursor` guide. + +Cursor Lifetime Mode +~~~~~~~~~~~~~~~~~~~~ + +The cursor lifetime mode uses the timeout setting to limit the entire lifetime of a +cursor. In this mode, your application must initialize the cursor, complete +all calls to the cursor methods, and return all documents within the specified +time limit. Otherwise, the cursor's lifetime expires and the driver +raises a timeout error. + +When you close a cursor by calling the ``close()`` method, the +timeout resets for the ``killCursors`` command to ensure server-side resources are +cleaned up. + +The following example shows how to set a cursor timeout to ensure that +the cursor is initialized and all documents are retrieved within the +inherited timeout: + +.. literalinclude:: /includes/connect/CsotExample.java + :language: java + :start-after: start-cursor-lifetime + :end-before: end-cursor-lifetime + :dedent: + :emphasize-lines: 3 + +Cursor Iteration Mode +~~~~~~~~~~~~~~~~~~~~~ + +The cursor iteration mode sets the timeout to limit each call to +the ``next()``, ``hasNext()``, and ``tryNext()`` methods. The timeout refreshes +after each call completes. This is the default mode for all tailable cursors, +such as the tailable cursors returned by the ``find()`` method on capped +collections or change streams. + +The following code example iterates over documents in the ``db.people`` collection +by using a cursor with the ``ITERATION`` timeout mode, and then retrieves +and prints the ``name`` field value for each document: + +.. literalinclude:: /includes/connect/CsotExample.java + :language: java + :start-after: start-cursor-iteration + :end-before: end-cursor-iteration + :dedent: + :emphasize-lines: 3 + +API Documentation +----------------- + +To learn more about using timeouts with the {+driver-short+}, see the following +API documentation: + +- `MongoClientSettings <{+core-api+}/MongoClientSettings.html>`__ +- `MongoClientSettings.Builder.timeout() <{+core-api+}/MongoClientSettings.Builder.html#timeout(long,java.util.concurrent.TimeUnit)>`__ +- `MongoCollection.withTimeout() <{+driver-api+}/MongoCollection.html#withTimeout(long,java.util.concurrent.TimeUnit)>`__ +- `ClientSessionOptions.Builder.defaultTimeout() <{+core-api+}/ClientSessionOptions.Builder.html#defaultTimeout(long,java.util.concurrent.TimeUnit)>`__ +- `TransactionOptions.Builder.timeout() <{+core-api+}/TransactionOptions.Builder.html#timeout(java.lang.Long,java.util.concurrent.TimeUnit)>`__ +- `ClientEncryptionSettings.Builder.timeout() <{+core-api+}/ClientEncryptionSettings.Builder.html#timeout(long,java.util.concurrent.TimeUnit)>`__ +- `FindIterable.timeoutMode() <{+driver-api+}/FindIterable.html#timeoutMode(com.mongodb.client.cursor.TimeoutMode)>`__ +- `TimeoutMode <{+core-api+}/client/cursor/TimeoutMode.html>`__ diff --git a/source/connection/specify-connection-options/stable-api.txt b/source/connection/specify-connection-options/stable-api.txt index 042a946f6..b50973b0f 100644 --- a/source/connection/specify-connection-options/stable-api.txt +++ b/source/connection/specify-connection-options/stable-api.txt @@ -5,8 +5,6 @@ {+stable-api+} ============== - - .. contents:: On this page :local: :backlinks: none @@ -147,4 +145,3 @@ API Documentation: - `strict() <{+core-api+}/ServerApi.Builder.html#strict(boolean)>`__ - `deprecationErrors() <{+core-api+}/ServerApi.Builder.html#>`__ - diff --git a/source/crud/compound-operations.txt b/source/crud/compound-operations.txt index 89f9cc21b..3fe24b6b5 100644 --- a/source/crud/compound-operations.txt +++ b/source/crud/compound-operations.txt @@ -83,9 +83,6 @@ following options: - Exclude the ``_id`` field from the found document with a projection. - Specify an upsert, which inserts the document specified by the query filter if no documents match the query. -- Set a maximum execution time of 5 seconds for this operation on the MongoDB - instance. If the operation takes longer, the ``findOneAndUpdate()`` method - will throw a ``MongoExecutionTimeoutException``. .. literalinclude:: /includes/fundamentals/code-snippets/CompoundOperatorsIndividualExamples.java :language: java diff --git a/source/crud/query-documents/cursor.txt b/source/crud/query-documents/cursor.txt index e84efd771..cb39b42f1 100644 --- a/source/crud/query-documents/cursor.txt +++ b/source/crud/query-documents/cursor.txt @@ -4,8 +4,6 @@ Access Data From a Cursor ========================= - - .. contents:: On this page :local: :backlinks: none @@ -15,8 +13,8 @@ Access Data From a Cursor Overview -------- -In this guide, you can learn how to access data using a **cursor** with the -MongoDB Java driver. +In this guide, you can learn how to access data by using a **cursor** in +the {+driver-short+}. A cursor is a mechanism that allows an application to iterate over database results while only holding a subset of them in memory at a given time. The @@ -38,6 +36,12 @@ The ``find()`` method creates and returns an instance of a matched by your search criteria and to further specify which documents to see by setting parameters through methods. +.. tip:: Cursor Timeout + + You can set a timeout on your cursor to return query results. + To learn more, see the :ref:`java-csot-cursor` section of the Limit + Server Execution Time guide. + Terminal Methods ---------------- diff --git a/source/crud/transactions.txt b/source/crud/transactions.txt index 47f02dc1c..25013ecdd 100644 --- a/source/crud/transactions.txt +++ b/source/crud/transactions.txt @@ -125,6 +125,12 @@ A ``ClientSession`` also has methods to retrieve session properties and modify m session properties. View the :ref:`API documentation ` to learn more about these methods. +.. tip:: Transaction Timeout + + You can set a limit on amount of time that operations can take + to complete in your transactions. To learn more, see the + :ref:`java-csot-transaction` section of the Limit Server Execution Time guide. + Example ------- diff --git a/source/includes/connect/CsotExample.java b/source/includes/connect/CsotExample.java new file mode 100644 index 000000000..f8c775fcc --- /dev/null +++ b/source/includes/connect/CsotExample.java @@ -0,0 +1,136 @@ +package org.example; + +import static com.mongodb.client.model.Filters.gte; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import com.mongodb.ClientSessionOptions; +import com.mongodb.ConnectionString; +import com.mongodb.MongoClientSettings; +import com.mongodb.TransactionOptions; +import com.mongodb.client.*; +import com.mongodb.client.cursor.TimeoutMode; +import org.bson.Document; + + +public class CsotExample { + + public static void main(String[] args) { + MongoClient mongoClient = new CsotExample().mongoClientSettings(); + } + + private MongoClient mongoClientSettings(){ + // start-mongoclientsettings + MongoClientSettings settings = MongoClientSettings.builder() + .applyConnectionString(new ConnectionString("")) + .timeout(200L, MILLISECONDS) + .build(); + + MongoClient mongoClient = MongoClients.create(settings); + // end-mongoclientsettings + + return mongoClient; + } + + private MongoClient connectionString(){ + // start-string + String uri = "/?timeoutMS=200"; + MongoClient mongoClient = MongoClients.create(uri); + // end-string + + return mongoClient; + } + + private void operationTimeout(){ + // start-operation-timeout + MongoClientSettings settings = MongoClientSettings.builder() + .applyConnectionString(new ConnectionString("")) + .timeout(200L, MILLISECONDS) + .build(); + + try (MongoClient mongoClient = MongoClients.create(settings)) { + MongoDatabase database = mongoClient.getDatabase("db"); + MongoCollection collection = database.getCollection("people"); + + collection.insertOne(new Document("name", "Francine Loews")); + } + // end-operation-timeout + } + + private void overrideTimeout(){ + // start-override + MongoClientSettings settings = MongoClientSettings.builder() + .applyConnectionString(new ConnectionString("")) + .timeout(200L, MILLISECONDS) + .build(); + + try (MongoClient mongoClient = MongoClients.create(settings)) { + MongoDatabase database = mongoClient.getDatabase("db"); + MongoCollection collection = database + .getCollection("people") + .withTimeout(300L, MILLISECONDS); + + // ... perform operations on MongoCollection + } + // end-override + } + + private void transactionTimeout(){ + MongoClientSettings settings = MongoClientSettings.builder() + .applyConnectionString(new ConnectionString("")) + .build(); + + try (MongoClient mongoClient = MongoClients.create(settings)) { + MongoCollection collection = mongoClient + .getDatabase("db") + .getCollection("people"); + + // start-session-timeout + ClientSessionOptions opts = ClientSessionOptions.builder() + .defaultTimeout(200L, MILLISECONDS) + .build(); + + ClientSession session = mongoClient.startSession(opts); + // ... perform operations on ClientSession + // end-session-timeout + + // start-transaction-timeout + TransactionOptions transactionOptions = TransactionOptions.builder() + .timeout(200L, MILLISECONDS) + .build(); + // end-transaction-timeout + } + + } + + private void cursorTimeout(){ + MongoClientSettings settings = MongoClientSettings.builder() + .applyConnectionString(new ConnectionString("")) + .timeout(200L, MILLISECONDS) + .build(); + + try (MongoClient mongoClient = MongoClients.create(settings)) { + MongoCollection collection = mongoClient + .getDatabase("db") + .getCollection("people"); + + // start-cursor-lifetime + FindIterable cursorWithLifetimeTimeout = collection + .find(gte("age", 40)) + .timeoutMode(TimeoutMode.CURSOR_LIFETIME); + // end-cursor-lifetime + + // start-cursor-iteration + try (MongoCursor cursorWithIterationTimeout = collection + .find(gte("age", 40)) + .timeoutMode(TimeoutMode.ITERATION) + .cursor() + ) { + while (cursorWithIterationTimeout.hasNext()) { + System.out.println(cursorWithIterationTimeout.next().toJson()); + } + } + // end-cursor-iteration + } + + } +} diff --git a/source/includes/fundamentals/code-snippets/CompoundOperatorsIndividualExamples.java b/source/includes/fundamentals/code-snippets/CompoundOperatorsIndividualExamples.java index 3102c5120..f2a95c5ec 100644 --- a/source/includes/fundamentals/code-snippets/CompoundOperatorsIndividualExamples.java +++ b/source/includes/fundamentals/code-snippets/CompoundOperatorsIndividualExamples.java @@ -66,11 +66,10 @@ private void findOneAndUpdateExample() { // Creates an update document to set the value of "food" to "pizza" Bson update = Updates.set("food", "pizza"); - // Defines options that specify projected fields, permit an upsert and limit execution time - FindOneAndUpdateOptions options = new FindOneAndUpdateOptions(). - projection(projection). - upsert(true). - maxTime(5, TimeUnit.SECONDS); + // Defines options that specify projected fields and permit upserts + FindOneAndUpdateOptions options = new FindOneAndUpdateOptions() + .projection(projection) + .upsert(true); // Updates the first matching document with the content of the update document, applying the specified options Document result = collection.findOneAndUpdate(filter, update, options); diff --git a/source/includes/fundamentals/code-snippets/Transaction.java b/source/includes/fundamentals/code-snippets/Transaction.java index 1756b41dd..0cd75b0da 100644 --- a/source/includes/fundamentals/code-snippets/Transaction.java +++ b/source/includes/fundamentals/code-snippets/Transaction.java @@ -18,7 +18,7 @@ public static void main(String[] args) { MongoCollection collection = database.getCollection("books"); // Sets transaction options - TransactionOptions txnOptions = TransactionOptions.builder() + TransactionOptions transactionOptions = TransactionOptions.builder() .writeConcern(WriteConcern.MAJORITY) .build(); @@ -32,7 +32,7 @@ public static void main(String[] args) { new Document("title", "Song of Solomon").append("author", "Toni Morrison") )); return null; // Return value as expected by the lambda - }, txnOptions); + }, transactionOptions); } } catch (Exception e) { e.printStackTrace(); diff --git a/source/references/whats-new.txt b/source/references/whats-new.txt index 197fd8e7e..f8c66d6e8 100644 --- a/source/references/whats-new.txt +++ b/source/references/whats-new.txt @@ -124,6 +124,10 @@ and features: .. sharedinclude:: dbx/jvm/v5.2-wn-items.rst + .. replacement:: csot-link + + the :ref:`java-csot` guide + .. replacement:: avs-index-link :ref:`java-search-indexes` in the Indexes guide