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.