1MONGOC_CLIENT_SESSION_START_TRANMSoAnCgToIDMOBONN(CG3O)DCr_iCvLeIrENT_SESSION_START_TRANSACTION(3)
2
3
4
6 mongoc_client_session_start_transaction - mongoc_client_ses‐
7 sion_start_transaction()
8
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
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
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
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
226 MongoDB, Inc
227
229 2017-present, MongoDB, Inc
230
231
232
233
2341.14.0 FebM2O2N,GO2C0_1C9LIENT_SESSION_START_TRANSACTION(3)