Transactions
The Native Client API runs transactions on the server as if they were local to the client application. Thus, the key to running client transactions lies in making sure the server is properly configured and programmed. For complete information about how transactions are conducted on the Geode server, see the Transactions section of the Geode User Guide.
Native Client Transaction APIs
The API for distributed transactions has the familiar relational database methods, begin
,
commit
, and rollback
. There are also APIs available to suspend and resume transactions.
The C++ classes for executing transactions are:
-
apache.geode.client.CacheTransactionManager
-
apache.geode.client.TransactionId
Running Native Client Transactions
The syntax for writing client transactions is the same as with server or peer transactions, but when a client performs a transaction, the transaction is delegated to a server that brokers the transaction.
Start each transaction with a begin
operation, and end the transaction with a commit
or a rollback
.
To maintain cache consistency, the local client cache is not used during a transaction. When the transaction completes or is suspended, local cache usage is reinstated.
If the transaction runs on server regions that are a mix of partitioned and replicated regions, perform the first transaction operation on a partitioned region. This sets the server data host for the entire transaction. If you are using PR single-hop, single-hop will be applied as usual to this first operation.
In addition to the failure conditions common to all transactions, client transactions can also fail
if the transaction delegate fails. If the delegate performing the transaction fails, the transaction
code throws a TransactionException
.
Client Transaction Examples
The native client release contains a transaction example in ../examples/cpp/transaction
.
The example performs a sequence of operations, displaying simple log entries as they run.
- To run an example, follow the instructions in the
README.md
file in the example directory. Review the source code in the example directory to see exactly how it operates.
You begin by running a script that sets up the server-side environment by invoking
gfsh
commands to create a region, simply called “exampleRegion.”You run the example client application, which performs the following steps:
- Connects to the server
- Begins a transaction
- Performs some
put
operations - Commits the transaction
For this example, the transaction code has these characteristics:
- To introduce the possibility of failure, values are randomized from 0 to 9, and the 0 values are treated as unsuccessful. The transaction is retried until it succeeds.
- In case the transaction repeatedly fails, the retry loop uses a counter to set a limit of 5 retries.
C++ Example
This section contains code snippets showing highlights of the C++ transaction example. They are not intended for cut-and-paste execution. For the complete source, see the example source directory.
The C++ example creates a cache, then uses it to create a connection pool.
auto cache = CacheFactory()
.set("log-level", "none")
.create();
cache.getPoolManager()
.createFactory()
.addLocator("localhost", 10334)
.create("pool");
auto regionFactory = cache.createRegionFactory(RegionShortcut::PROXY);
auto region = regionFactory.setPoolName("pool").create("exampleRegion");
The example application gets a transaction manager from the cache and a five-attempt retry loop.
If all put
operations succeed, the application commits the transaction. Otherwise, it retries up to 5 times if necessary.
auto transactionManager = cache.getCacheTransactionManager();
auto retries = 5;
while (retries--) {
try {
transactionManager->begin();
for (auto& key : keys) {
auto value = getValueFromExternalSystem();
region->put(key, value);
}
transactionManager->commit();
std::cout << "Committed transaction - exiting" << std::endl;
break;
} catch ( ... ) {
if (transactionManager->exists()){
transactionManager->rollback();
}