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

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

RETURN

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

AUTHOR

228       MongoDB, Inc
229
231       2017-present, MongoDB, Inc
232
233
234
235
2361.17.6                           JunM0O3N,GO2C0_2C1LIENT_SESSION_START_TRANSACTION(3)
Impressum