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