1MONGOC_CLIENT_SESSION_START_TRANSACTlIiMObONmN(oG3nO)gCo_cCLIENT_SESSION_START_TRANSACTION(3)
2
3
4

NAME

6       mongoc_client_session_start_transaction       -      mongoc_client_ses‐
7       sion_start_transaction()
8

SYNOPSIS

10          bool
11          mongoc_client_session_start_transaction (mongoc_client_session_t *session,
12                                                   const mongoc_transaction_opt_t *opts,
13                                                   bson_error_t *error);
14
15       Start a multi-document transaction for all following operations in this
16       session.  Any  options provided in opts override options passed to mon‐
17       goc_session_opts_set_default_transaction_opts,  and  options  inherited
18       from  the mongoc_client_t. The opts argument is copied and can be freed
19       after calling this function.
20
21       The  transaction  must  be  completed  with  mongoc_client_session_com‐
22       mit_transaction    or    mongoc_client_session_abort_transaction.    An
23       in-progress transaction is automatically aborted by  mongoc_client_ses‐
24       sion_destroy.
25

PARAMETERS

27       · session: A mongoc_client_session_t.
28
29       · opts: A mongoc_transaction_opt_t or NULL.
30
31       · error: An optional location for a bson_error_t or NULL.
32

RETURN

34       Returns  true  if  the  transaction was started. Returns false and sets
35       error if there are invalid arguments, such as a session with a transac‐
36       tion already in progress.
37

EXAMPLE

39       The  following example demonstrates how to use error labels to reliably
40       execute a multi-document transaction despite network errors  and  other
41       transient failures.  example-transaction.c.INDENT 0.0
42
43          /* gcc example-transaction.c -o example-transaction \
44           *     $(pkg-config --cflags --libs libmongoc-1.0) */
45
46          /* ./example-transaction [CONNECTION_STRING] */
47
48          #include <stdio.h>
49          #include <mongoc/mongoc.h>
50
51
52          int
53          main (int argc, char *argv[])
54          {
55             int exit_code = EXIT_FAILURE;
56
57             mongoc_client_t *client = NULL;
58             mongoc_database_t *database = NULL;
59             mongoc_collection_t *collection = NULL;
60             mongoc_client_session_t *session = NULL;
61             mongoc_session_opt_t *session_opts = NULL;
62             mongoc_transaction_opt_t *default_txn_opts = NULL;
63             mongoc_transaction_opt_t *txn_opts = NULL;
64             mongoc_read_concern_t *read_concern = NULL;
65             mongoc_write_concern_t *write_concern = NULL;
66             const char *uri_string = "mongodb://127.0.0.1/?appname=transaction-example";
67             mongoc_uri_t *uri;
68             bson_error_t error;
69             bson_t *doc = NULL;
70             bson_t *insert_opts = NULL;
71             int32_t i;
72             int64_t start;
73             bson_t reply = BSON_INITIALIZER;
74             char *reply_json;
75             bool r;
76
77             mongoc_init ();
78
79             if (argc > 1) {
80                uri_string = argv[1];
81             }
82
83             uri = mongoc_uri_new_with_error (uri_string, &error);
84             if (!uri) {
85                MONGOC_ERROR ("failed to parse URI: %s\n"
86                              "error message:       %s\n",
87                              uri_string,
88                              error.message);
89                goto done;
90             }
91
92             client = mongoc_client_new_from_uri (uri);
93             if (!client) {
94                goto done;
95             }
96
97             mongoc_client_set_error_api (client, 2);
98             database = mongoc_client_get_database (client, "example-transaction");
99
100             /* inserting into a nonexistent collection normally creates it, but a
101              * collection can't be created in a transaction; create it now */
102             collection =
103                mongoc_database_create_collection (database, "collection", NULL, &error);
104
105             if (!collection) {
106                /* code 48 is NamespaceExists, see error_codes.err in mongodb source */
107                if (error.code == 48) {
108                   collection = mongoc_database_get_collection (database, "collection");
109                } else {
110                   MONGOC_ERROR ("Failed to create collection: %s", error.message);
111                   goto done;
112                }
113             }
114
115             /* a transaction's read preferences, read concern, and write concern can be
116              * set on the client, on the default transaction options, or when starting
117              * the transaction. for the sake of this example, set read concern on the
118              * default transaction options. */
119             default_txn_opts = mongoc_transaction_opts_new ();
120             read_concern = mongoc_read_concern_new ();
121             mongoc_read_concern_set_level (read_concern, "snapshot");
122             mongoc_transaction_opts_set_read_concern (default_txn_opts, read_concern);
123             session_opts = mongoc_session_opts_new ();
124             mongoc_session_opts_set_default_transaction_opts (session_opts,
125                                                               default_txn_opts);
126
127             session = mongoc_client_start_session (client, session_opts, &error);
128             if (!session) {
129                MONGOC_ERROR ("Failed to start session: %s", error.message);
130                goto done;
131             }
132
133             /* in this example, set write concern when starting the transaction */
134             txn_opts = mongoc_transaction_opts_new ();
135             write_concern = mongoc_write_concern_new ();
136             mongoc_write_concern_set_wmajority (write_concern, 1000 /* wtimeout */);
137             mongoc_transaction_opts_set_write_concern (txn_opts, write_concern);
138
139             insert_opts = bson_new ();
140             if (!mongoc_client_session_append (session, insert_opts, &error)) {
141                MONGOC_ERROR ("Could not add session to opts: %s", error.message);
142                goto done;
143             }
144
145          retry_transaction:
146             r = mongoc_client_session_start_transaction (session, txn_opts, &error);
147             if (!r) {
148                MONGOC_ERROR ("Failed to start transaction: %s", error.message);
149                goto done;
150             }
151
152             /* insert two documents - on error, retry the whole transaction */
153             for (i = 0; i < 2; i++) {
154                doc = BCON_NEW ("_id", BCON_INT32 (i));
155                bson_destroy (&reply);
156                r = mongoc_collection_insert_one (
157                   collection, doc, insert_opts, &reply, &error);
158
159                bson_destroy (doc);
160
161                if (!r) {
162                   MONGOC_ERROR ("Insert failed: %s", error.message);
163                   mongoc_client_session_abort_transaction (session, NULL);
164
165                   /* a network error, primary failover, or other temporary error in a
166                    * transaction includes {"errorLabels": ["TransientTransactionError"]},
167                    * meaning that trying the entire transaction again may succeed
168                    */
169                   if (mongoc_error_has_label (&reply, "TransientTransactionError")) {
170                      goto retry_transaction;
171                   }
172
173                   goto done;
174                }
175
176                reply_json = bson_as_json (&reply, NULL);
177                printf ("%s\n", reply_json);
178                bson_free (reply_json);
179             }
180
181             /* in case of transient errors, retry for 5 seconds to commit transaction */
182             start = bson_get_monotonic_time ();
183             while (bson_get_monotonic_time () - start < 5 * 1000 * 1000) {
184                bson_destroy (&reply);
185                r = mongoc_client_session_commit_transaction (session, &reply, &error);
186                if (r) {
187                   /* success */
188                   break;
189                } else {
190                   MONGOC_ERROR ("Warning: commit failed: %s", error.message);
191                   if (mongoc_error_has_label (&reply, "TransientTransactionError")) {
192                      goto retry_transaction;
193                   } else if (mongoc_error_has_label (&reply,
194                                                      "UnknownTransactionCommitResult")) {
195                      /* try again to commit */
196                      continue;
197                   }
198
199                   /* unrecoverable error trying to commit */
200                   break;
201                }
202             }
203
204             exit_code = EXIT_SUCCESS;
205
206          done:
207             bson_destroy (&reply);
208             bson_destroy (insert_opts);
209             mongoc_write_concern_destroy (write_concern);
210             mongoc_read_concern_destroy (read_concern);
211             mongoc_transaction_opts_destroy (txn_opts);
212             mongoc_transaction_opts_destroy (default_txn_opts);
213             mongoc_client_session_destroy (session);
214             mongoc_collection_destroy (collection);
215             mongoc_database_destroy (database);
216             mongoc_uri_destroy (uri);
217             mongoc_client_destroy (client);
218
219             mongoc_cleanup ();
220
221             return exit_code;
222          }
223
224

AUTHOR

226       MongoDB, Inc
227
229       2017-present, MongoDB, Inc
230
231
232
233
2341.16.2                           FebM2O5N,GO2C0_2C0LIENT_SESSION_START_TRANSACTION(3)
Impressum