Calling stored procedures synchronously simplifies the program logic because your client application waits for the procedure to complete before continuing. However, for high performance applications looking to maximize throughput, it is better to queue stored procedure invocations asynchronously.
To invoke stored procedures asynchronously, use the callProcedureAsync()
method.
The procedure call will be queued internally for transmission. The immediate return value is a standard
Java CompletableFuture
object, which will be "completed" when the procedure completes
(or an error occurs). For example, to invoke a
NewCustomer()
stored procedure asynchronously, the call to callProcedureAsync()
might look
like the following:
CompletableFuture<ClientResponse> future = client.callProcedureAsync("NewCustomer", firstname, lastname, custID};
To handle the eventual ClientResponse, you can use any of the features of CompletableFuture
that Java provides. These include awaiting completion with get()
, declaring a handler for the
eventual completion with handle()
, and so on.
The following are other important points to note when making asynchronous invocations of stored procedures:
Calls to callProcedureAsync()
return control to the calling application as soon as the
procedure call is locally queued.
Errors that occur before the procedure call is queued may be reported via a Java exception. The calling application should include appropriate handling.
Once the procedure is queued, any subsequent error (such as an exception in the stored procedure itself or loss
of connection to the database) is returned via the CompletableFuture
.
There is a limit on the local queue size, after which calls will be rejected. The default queue size
is 1000 calls, but this can be changed with Client2Config
. Robust applications should
either ensure they can never exceed the local queue size, or implement appropriate handling. You can
configure a handler to receive notifications when the queue is approaching capacity; see the
requestBackpressureHandler()
method of Client2Config.
If the database server queue is full, transmission is temporarily suspended. This condition,
known as network backpressure (distinct from request-queue backpressure), is handled internally
to the Client2
API. This situation
does not normally happen unless the database cluster is not scaled sufficiently for the workload,
or there are abnormal spikes in the workload. See Section 6.6.3, “Writing Handlers to Interpret Other Errors” for more information.
The CompletableFuture
is "completed normally" when the called procedure has been
executed on the cluster, and has returned a response. It can also be completed, in this case "exceptionally",
when an error or timeout occurs.
Normal completion allows access to a ClientResponse
structure, the same structure
that is returned in a synchronous invocation. The ClientResponse
contains information
about the results of execution. In particular, the methods getStatus()
and getResults()
let you determine whether the stored procedure was successful and evaluate the results of the procedure.
Exceptional completion does not have a ClientResponse
structure; the exception
itself conveys the error information.
Completions themselves can be processed synchronously or asynchronously, using the standard facilities of
CompletableFuture
. The VoltDB Java client is single threaded, so synchronous completions are
processed one at a time. Consequently, it is good practice to keep synchronous completion processing to a minimum,
returning control to the main thread as soon as possible. If more complex processing is required, use one of
the available methods for handling the completion asynchronously.