Synchronous and asynchronous transactions

Some Couchbase SDKs support both synchronous and asynchronous transactions. In the case of synchronous transactions, your application pauses its execution until a response is returned from the Couchbase Server. In the case of asynchronous commands, your application can continue performing other, background operations until Couchbase Server responds. Asynchronous operations are particularly useful when your application accesses persisted data, or when you are performing data sets and updates.

In the case of a typical asynchronous call, your application handles something that does not depend on a server response, and the result is still being computed on the server. The object that is eventually returned by an asynchronous call is often referred to as a future object, which is non-blocking. That is, the server returns the object sometime in the future, after the original method call requesting it, and the object is non-blocking because it does not interfere with the continued execution of the application.

Please refer to your chosen SDK to find out more about which methods are available for asynchronous transactions, as of this writing, asynchronous calls are available in the Java and Ruby SDKs only.

The following is an example showing the typical pattern you use to create an asynchronous transaction; in an asynchronous transaction, we store a record and process something in the meantime. Then we either successfully perform a get() and retrieve the future object, or cancel the process. This example is in Java:

//perform a set asynchronously; return from set not important now

OperationFuture<Boolean> setOp = client.set(KEY, EXP_TIME, VALUE);

//do something in meantime

//check to see if set successful via get, if not fail
//the get will block application flow

if (setOp.get().booleanValue()) {
    System.out.println("Set Succeeded");
} else {
    System.err.println("Set failed:" + setOp.getStatus().getMessage());
}

Other operations such as get() can be used asynchronously in your application. Here is a second example in Java:

GetFuture getOp = client.asyncGet(KEY);

//do something in meantime

//check to see if get successful
//if not cancel

if ((getObject = getOp.get()) != null {
    System.out.println("Asynchronous get succeeded: " + getObject);
} else {
    System.err.println("Asynchronous get failed: " + getOp.getStatus().getMessage());
}

This last example demonstrates use of delete() in Java as in an asynchronous transaction:

// Do an asynchronous delete
OperationFuture<Boolean> delOp = null;

if (do_delete) {
     delOp = client.delete(KEY);
}

//do something in meantime

// Check to see if our delete succeeded

if (do_delete) {
    try {
        if (delOp.get().booleanValue()) {
            System.out.println("Delete Succeeded");
    } else {
        System.err.println("Delete failed: " + delOp.getStatus().getMessage());
    }
    } catch (Exception e) {
            System.err.println("Exception while doing delete: " + e.getMessage());
  }
}

This next example shows how asynchronous call can be made using the Ruby SDK. When you use this mode in the Ruby SDK, you execute the operation and it returns control immediately without performing any input/output. As in the case of Java, we perform the asynchronous operation and later we use a callback that either successfully retrieve the future value or it fails and reports on the error:

Couchbase.bucket.run do |c|
    c.set("foo", "bar") do |res1|
      # res1 is the Couchbase::Bucket::Result instance
      if res1.success?
        c.get("foo") do |res2|
          puts res.value if res2.success?
      end
      else
            puts "Something wrong happened: #{res1.error.message}"
        end
    end
end

In the callback for our Ruby example, we perform a get from the SDK that will be called as soon as a response is ready. The callback received a result object, and we can check if the value was set with the success? method. If the value is true, then the record has been successfully set; otherwise you should assume call failed and check the error property of the result, which will be an exception object.

In the case of PHP, getDelayed() and getDelayedByKey() are the two available asynchronous methods for the SDK. Both methods can retrieve one or more key; the major difference between getDelayed() and getDelayedByKey() is that the later will retrieve a record from a specified node. Here is an example of getDelayed() :

<?php

$cb = new Couchbase("127.0.0.1:8091");

$cb->set('int', 99);
$cb->set('string', 'a simple string');
$cb->set('array', array(11, 12));

$cb->getDelayed(array('int', 'array'), true);
var_dump($cb->fetchAll());

?>

In this case getDelayed() will make a request to Couchbase Server for multiple items in the array. The method does not wait and returns immediately. When you want to collect all the items, you perform a fetch() or fetchAll() as well do in the last line of this example.

All the Couchbase SDKs support synchronous transactions. In the most basic form a synchronous call will block, or wait for a response from the Couchbase Server before program execution continues. The most standard form of any method in a Couchbase SDK is synchronous in its functioning. In this case of synchronous calls, typically the return is assigned to variable, or used immediately afterwards in the applications, such as output or display.