Batched Invocation Interceptors

3 min read

2 min read

2 min read

2 min read

2 min read

2 min read

2 min read

2 min read

2 min read

Batch invocation interceptors allow you to implement your own auto-flush algorithm or receive notification when an auto-flush fails.

You install an interceptor by setting the batchRequestInterceptor field of the InitializationDataInitializationDataInitializationDataInitializationDataInitializationDataInitializationDataInitializationDataInitializationDataInitializationData object you use to create your communicator. The communicator invokes the interceptor for each batch request, passing the following arguments:

  • req - An object representing the batch request being queued
  • count - The number of requests currently in the queue
  • size - The number of bytes consumed by the requests currently in the queue

The request represented by req is not included in the count and size figures.

A batch request is not queued until the interceptor calls enqueue. The minimal interceptor implementation is therefore:

C++
initData.batchRequestInterceptor =
[](const Ice::BatchRequest& req, int count, int size)
{
req.enqueue();
};
C#
initData.batchRequestInterceptor = (req, _, _) => req.enqueue();
Java
initData.batchRequestInterceptor = (req, count, size) -> req.enqueue();

A more sophisticated implementation might use its own logic for automatically flushing queued requests:

C++
int limit = initData.properties->getPropertyAsInt("Ice.BatchAutoFlushSize");
initData.batchRequestInterceptor =
[limit](const Ice::BatchRequest& req, int count, int size)
{
if (size + req.getSize() > limit)
{
req.getProxy()->ice_flushBatchRequestsAsync();
}
req.enqueue();
};
C#
int limit = initData.properties.getPropertyAsInt("Ice.BatchAutoFlushSize");
initData.batchRequestInterceptor = (req, _, size) =>
{
if (size + req.getSize() > limit)
{
_ = req.getProxy().ice_flushBatchRequestsAsync();
}
req.enqueue();
};
Python
def enqueue(self, request: Ice.BatchRequest, count: int, size: int):
if size + req.getSize() > limit:
_ = req.getProxy().ice_flushBatchRequestAsync()
req.enqueue()
initData.batchRequestInterceptor = enqueue

In this example, the implementation consults the existing Ice property Ice.BatchAutoFlushSize to determine the limit that triggers an automatic flush. If a flush is necessary, the interceptor can obtain the relevant proxy by calling getProxy on the BatchRequest object.

Specifying your own exception handler when calling ice_flushBatchRequestsAsync gives you the ability to take action if a failure occurs (Ice's default automatic flushing implementation ignores any errors). Aside from logging a message, your options are somewhat limited because it's not possible for the interceptor to force a retry.