From 2a8be4d3d7b94042b6a51bd6ece0d266e2f24649 Mon Sep 17 00:00:00 2001 From: Stephanie Aurelio Date: Tue, 31 Dec 2024 10:40:50 -0800 Subject: [PATCH 1/5] add transactions page and code example --- source/includes/write/transaction.rb | 45 ++++++++ source/write/transactions.txt | 151 +++++++++++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 source/includes/write/transaction.rb create mode 100644 source/write/transactions.txt diff --git a/source/includes/write/transaction.rb b/source/includes/write/transaction.rb new file mode 100644 index 00000000..043b7c63 --- /dev/null +++ b/source/includes/write/transaction.rb @@ -0,0 +1,45 @@ +require 'bundler/inline' +gemfile do + source 'https://rubygems.org' + gem 'mongo' +end + +uri = "" + +Mongo::Client.new(uri) do |client| + #start-txn + database = client.use('sample_mflix') + movies_collection = database[:movies] + users_collection = database[:users] + + def run_transaction(session, movies_collection, users_collection) + transaction_options = { + read_concern: { level: "snapshot" }, + write_concern: { w: "majority" } + } + + session.with_transaction(transaction_options) do + # Inserts document into the "movies" collection + insert_result = movies_collection.insert_one({ name: 'The Menu', runtime: 107 }, session: session) + puts "Insert completed: #{insert_result.inspect}" + + # Updates document in the "users" collection + update_result = users_collection.update_one({ name: 'Amy Phillips'}, { "$set" => { name: 'Amy Ryan' }}, session: session) + puts "Update completed: #{update_result.inspect}" + end + end + + # Starts a session + session = client.start_session + + begin + # Runs the transaction + run_transaction(session, movies_collection, users_collection) + puts "Transaction committed successfully." + rescue Mongo::Error::OperationFailure => e + puts "Transaction failed and was aborted. Error: #{e.message}" + ensure + session.end_session + end + #end-txn + end \ No newline at end of file diff --git a/source/write/transactions.txt b/source/write/transactions.txt new file mode 100644 index 00000000..1970c123 --- /dev/null +++ b/source/write/transactions.txt @@ -0,0 +1,151 @@ +.. _ruby-transactions: + +============ +Transactions +============ + +.. contents:: On this page + :local: + :backlinks: none + :depth: 2 + :class: singlecol + +.. facet:: + :name: genre + :values: reference + +.. meta:: + :keywords: code example, ACID compliance, multi-document + +Overview +-------- + +In this guide, you can learn how to use the {+driver-short+} to perform +**transactions**. Transactions allow you to perform a series of operations that +change data only if the entire transaction is committed. If any operation in the +transaction does not succeed, the driver stops the transaction and discards all +data changes before they ever become visible. This feature is called +**atomicity**. + +In MongoDB, transactions run within logical **sessions**. A session is a +grouping of related read or write operations that you want to run sequentially. +Sessions enable causal consistency for a group of operations and allow you to +run operations in an **ACID-compliant** transaction, which is a transaction that +meets an expectation of atomicity, consistency, isolation, and durability. +MongoDB guarantees that the data involved in your transaction operations remains +consistent, even if the operations encounter unexpected errors. + +When using the {+driver-short+}, you can start a ``ClientSession`` by calling +the ``start_session`` method on your client. Then, you can perform transactions +within the session. + +.. warning:: + + Use a ``ClientSession`` only in operations running on the ``MongoClient`` + that created it. Using a ``ClientSession`` with a different ``MongoClient`` + results in operation errors. + +Methods +------- + +After calling the ``start_session`` method to start a session, you can use +methods from the ``Mongo::Session`` class to manage the session state. The +following table describes the methods you can use to manage a transaction: + +.. list-table:: + :widths: 25 75 + :stub-columns: 1 + :header-rows: 1 + + * - Method + - Description + + * - ``start_transaction`` + - | Starts a new transaction on this session. You cannot start a + transaction if there's already an active transaction running in + the session. + | + | You can set transaction options including read concern, write concern, + and read preference by passing a ``TransactionOptions`` instance as a + parameter. + + * - ``commit_transaction`` + - | Commits the active transaction for this session. This method returns an + error if there is no active transaction for the session, the + transaction was previously ended, or if there is a write conflict. + + * - ``abort_transaction`` + - | Ends the active transaction for this session. This method returns an + error if there is no active transaction for the session or if the + transaction was committed or ended. + + * - ``with_transaction`` + - | Starts a transaction prior to calling the supplied block, and commits + the transaction when the block finishes. If any of the operations in + the block, or the commit operation, result in a transient transaction + error, the block and/or the commit will be executed again. + +.. _ruby-txn-example: + +Transaction Example +------------------- + +This example defines a ``run_transaction`` method that modifies data in the +collections of the ``sample_mflix`` database. The code performs the following +actions: + +- Creates ``Mongo::Collection`` instances to access the movies and users collections. +- Specifies the read and write concerns for the transaction. +- Starts the transaction. +- Inserts a document into the ``movies`` collection and prints the results. +- Updates a document in the ``users`` collection and prints the results. + +.. literalinclude:: /includes/write/transaction.rb + :language: ruby + :start-after: start-txn + :end-before: end-txn + :dedent: + :copyable: + +.. sharedinclude:: dbx/transactions-parallelism.rst + + .. replacement:: driver-specific-content + + The {+driver-short+} does not support running parallel operations within a + single transaction. + + .. TODO: + Replace content to use this wording when the bulk write guide is added: + .. If you're using {+mdb-server+} v8.0 or later, you can perform + .. write operations on multiple namespaces within a single transaction by using + .. the ``bulk-write`` method. For more information, see the :ref:`` + .. guide. + +Additional Information +---------------------- + +To learn more about the concepts mentioned in this guide, see the +following pages in the {+mdb-server+} manual: + +- :manual:`Transactions ` +- :manual:`Server Sessions ` +- :manual:`Read Isolation, Consistency, and Recency + ` + +To learn more about ACID compliance, see the :website:`A Guide to ACID Properties in Database Management Systems +` article on the MongoDB website. + +To learn more about insert operations, see the +:ref:`ruby-write-insert` guide. + +API Documentation +~~~~~~~~~~~~~~~~~ + +To learn more about the methods and types mentioned in this +guide, see the following API documentation: + +- `Mongo::Session <{+api-root+}/Mongo/Session.html>`_ +- `start_transaction <{+api-root+}/Mongo/Session.html#start_transaction-instance_method>`_ +- `commit_transaction <{+api-root+}/Mongo/Session.html#commit_transaction-instance_method>`_ +- `abort_transaction <{+api-root+}/Mongo/Session.html#abort_transaction-instance_method>`_ +- `with_transaction <{+api-root+}/Mongo/Session.html#with_transaction-instance_method>`_ \ No newline at end of file From 05c91db7744d4387762dcd0b5949d0262f11de03 Mon Sep 17 00:00:00 2001 From: Stephanie Aurelio Date: Tue, 31 Dec 2024 13:30:33 -0800 Subject: [PATCH 2/5] edits --- source/write/transactions.txt | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/source/write/transactions.txt b/source/write/transactions.txt index 1970c123..d0b761b7 100644 --- a/source/write/transactions.txt +++ b/source/write/transactions.txt @@ -35,14 +35,14 @@ meets an expectation of atomicity, consistency, isolation, and durability. MongoDB guarantees that the data involved in your transaction operations remains consistent, even if the operations encounter unexpected errors. -When using the {+driver-short+}, you can start a ``ClientSession`` by calling +When using the {+driver-short+}, you can start a ``Mongo::Session`` by calling the ``start_session`` method on your client. Then, you can perform transactions within the session. .. warning:: - Use a ``ClientSession`` only in operations running on the ``MongoClient`` - that created it. Using a ``ClientSession`` with a different ``MongoClient`` + Use a ``Mongo::Session`` only in operations running on the ``Mongo::Client`` + that created it. Using a ``Mongo::Session`` with a different ``Mongo::Client`` results in operation errors. Methods @@ -66,8 +66,7 @@ following table describes the methods you can use to manage a transaction: the session. | | You can set transaction options including read concern, write concern, - and read preference by passing a ``TransactionOptions`` instance as a - parameter. + and read preference by passing a ``Hash`` as a parameter. * - ``commit_transaction`` - | Commits the active transaction for this session. This method returns an @@ -109,13 +108,12 @@ actions: .. sharedinclude:: dbx/transactions-parallelism.rst - .. replacement:: driver-specific-content - The {+driver-short+} does not support running parallel operations within a single transaction. .. TODO: Replace content to use this wording when the bulk write guide is added: + .. replacement:: driver-specific-content .. If you're using {+mdb-server+} v8.0 or later, you can perform .. write operations on multiple namespaces within a single transaction by using .. the ``bulk-write`` method. For more information, see the :ref:`` From 26fecbaec488083dbc7b82ae58221a605361f81c Mon Sep 17 00:00:00 2001 From: Stephanie Aurelio Date: Thu, 2 Jan 2025 10:36:13 -0800 Subject: [PATCH 3/5] clean up --- source/write/transactions.txt | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/source/write/transactions.txt b/source/write/transactions.txt index d0b761b7..211a2c21 100644 --- a/source/write/transactions.txt +++ b/source/write/transactions.txt @@ -35,15 +35,15 @@ meets an expectation of atomicity, consistency, isolation, and durability. MongoDB guarantees that the data involved in your transaction operations remains consistent, even if the operations encounter unexpected errors. -When using the {+driver-short+}, you can start a ``Mongo::Session`` by calling -the ``start_session`` method on your client. Then, you can perform transactions +When using the {+driver-short+}, you can start a session by calling the +``start_session`` method on your client. Then, you can perform transactions within the session. .. warning:: - Use a ``Mongo::Session`` only in operations running on the ``Mongo::Client`` - that created it. Using a ``Mongo::Session`` with a different ``Mongo::Client`` - results in operation errors. + Use a session only in operations running on the ``Mongo::Client`` that + created it. Using a session with a different ``Mongo::Client`` results in + operation errors. Methods ------- @@ -108,9 +108,6 @@ actions: .. sharedinclude:: dbx/transactions-parallelism.rst - The {+driver-short+} does not support running parallel operations within a - single transaction. - .. TODO: Replace content to use this wording when the bulk write guide is added: .. replacement:: driver-specific-content From 0a8e6ed0804cd2b27a3d9a6c232f078cc8f1fc4d Mon Sep 17 00:00:00 2001 From: Stephanie Aurelio Date: Mon, 6 Jan 2025 13:55:17 -0800 Subject: [PATCH 4/5] rr feedback --- source/write/transactions.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/write/transactions.txt b/source/write/transactions.txt index 211a2c21..cb8d28fe 100644 --- a/source/write/transactions.txt +++ b/source/write/transactions.txt @@ -93,7 +93,8 @@ This example defines a ``run_transaction`` method that modifies data in the collections of the ``sample_mflix`` database. The code performs the following actions: -- Creates ``Mongo::Collection`` instances to access the movies and users collections. +- Creates ``Mongo::Collection`` instances to access the ``movies`` and ``users`` + collections. - Specifies the read and write concerns for the transaction. - Starts the transaction. - Inserts a document into the ``movies`` collection and prints the results. From f2a127349dd048dd50061e34df5f53e4207d3d3e Mon Sep 17 00:00:00 2001 From: Stephanie Aurelio Date: Mon, 6 Jan 2025 15:18:36 -0800 Subject: [PATCH 5/5] fix indentation --- source/includes/write/transaction.rb | 60 ++++++++++++++-------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/source/includes/write/transaction.rb b/source/includes/write/transaction.rb index 043b7c63..a2d54cf8 100644 --- a/source/includes/write/transaction.rb +++ b/source/includes/write/transaction.rb @@ -7,39 +7,39 @@ uri = "" Mongo::Client.new(uri) do |client| - #start-txn - database = client.use('sample_mflix') - movies_collection = database[:movies] - users_collection = database[:users] + #start-txn + database = client.use('sample_mflix') + movies_collection = database[:movies] + users_collection = database[:users] - def run_transaction(session, movies_collection, users_collection) - transaction_options = { - read_concern: { level: "snapshot" }, - write_concern: { w: "majority" } - } + def run_transaction(session, movies_collection, users_collection) + transaction_options = { + read_concern: { level: "snapshot" }, + write_concern: { w: "majority" } + } - session.with_transaction(transaction_options) do - # Inserts document into the "movies" collection - insert_result = movies_collection.insert_one({ name: 'The Menu', runtime: 107 }, session: session) - puts "Insert completed: #{insert_result.inspect}" + session.with_transaction(transaction_options) do + # Inserts document into the "movies" collection + insert_result = movies_collection.insert_one({ name: 'The Menu', runtime: 107 }, session: session) + puts "Insert completed: #{insert_result.inspect}" - # Updates document in the "users" collection - update_result = users_collection.update_one({ name: 'Amy Phillips'}, { "$set" => { name: 'Amy Ryan' }}, session: session) - puts "Update completed: #{update_result.inspect}" - end + # Updates document in the "users" collection + update_result = users_collection.update_one({ name: 'Amy Phillips'}, { "$set" => { name: 'Amy Ryan' }}, session: session) + puts "Update completed: #{update_result.inspect}" end + end - # Starts a session - session = client.start_session + # Starts a session + session = client.start_session - begin - # Runs the transaction - run_transaction(session, movies_collection, users_collection) - puts "Transaction committed successfully." - rescue Mongo::Error::OperationFailure => e - puts "Transaction failed and was aborted. Error: #{e.message}" - ensure - session.end_session - end - #end-txn - end \ No newline at end of file + begin + # Runs the transaction + run_transaction(session, movies_collection, users_collection) + puts "Transaction committed successfully." + rescue Mongo::Error::OperationFailure => e + puts "Transaction failed and was aborted. Error: #{e.message}" + ensure + session.end_session + end + #end-txn +end \ No newline at end of file