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