Couchbase Transactions C++ Client  1.0.0
Transactions client for couchbase
Couchbase Transactions C++ Client Documentation

A transaction consists of a lambda containing all the operations you wish to perform within a transaction. The transactions.run() call yields an attempt_context which you use for those operations.

Overview

A very simple transaction:

cluster c("couchbase://127.0.0.1", "Administrator", "password");
transaction_config config;
config.durability_level(transactions::durability_level::MAJORITY);
auto b = cluster.bucket("default");
auto coll = b->default_collection();
transactions txn(c, config);
try {
txn.run([&](transactions::attempt_context& ctx) {
ctx.upsert(coll, "somekey", nlohmann::json::parse("{\"a\":\"thing\"}"));
ctx.insert(coll, "someotherkey", nlohmann::json::parse("{"\a\":\"different thing\"}"));
});
cout << "txn successful" << endl;
} catch (const transaction_failed& failed) {
cerr << "txn failed: " << failed.what() << endl;
} catch (const transaction_expired& expired) {
cerr << "txn timed out" << expired.what() << endl;
}

This upserts a document, and inserts another into the default collection in the bucket named "default". If unsuccessful, an exception will be raised.

For a much more detailed example, see examples/game_server.cxx

Best Practices

Each transactions instances spins up background threads to perform cleanup of metadata that could be left behind after failed transactions. For that reason, creating many transactions objects, especially if they are long-lived, will consume resources. We recommend simply creating one transactions object per process, and using that for the life of the process, when possible.

The transactions, cluster, bucket, and collection instances are all safe to use across threads. The cluster and bucket use libcouchbase internally, and manage a pool of libcouchbase instances, since those instances are not to be used across threads. The maximum number of instances in the pools (for either the cluster or bucket) can be specified at the time you construct the cluster. See cluster_options for details.

Since a transactions instance spins up one thread per bucket for background cleanup tasks, a reasonable starting point for sizing the cluster_options::max_bucket_instances would be one per bucket, plus one per thread that uses the cluster (or the transactions object constructed with that cluster). This could be tuned lower potentially, but this is a the maxmimum one should need. The pool only creates a new instance when it needs one, so the actual number created may never hit the max. When the maximum is reached, the thread will block until one is available.