Package com.gruelbox.transactionoutbox
Class ExecutorSubmitter
java.lang.Object
com.gruelbox.transactionoutbox.ExecutorSubmitter
- All Implemented Interfaces:
Submitter
Schedules background work using a local
Executor
implementation. Note that the Runnable
s submitted to this will not be Serializable
so will not be suitable for
remoting. Remote submission of work is not yet supported.
Note that there are some important aspects that should be considered in the configuration of this executor:
- Should use a BOUNDED blocking queue implementation such as
ArrayBlockingQueue
, otherwise under high volume, the queue may get so large it causes out-of-memory errors. - Should use a
RejectedExecutionHandler
which either throws (such asThreadPoolExecutor.AbortPolicy
), silently fails (such asThreadPoolExecutor.DiscardPolicy
) or blocks the calling thread until a thread is available. It should not execute the work in the calling thread (e.g.ThreadPoolExecutor.CallerRunsPolicy
, since this could result in unpredictable effects with tasks assuming they will be run in a different thread context corrupting thread state. Generally, throwing or silently failing are preferred since this allows the database to absorb all backpressure, but if you have a strong reason to choose a blocking policy to enforce upstream backpressure, be aware thatTransactionOutbox.flush()
can potentially block for a long period of time too, so design any background processing which calls it accordingly (e.g. avoid calling from a timed scheduled job; perhaps instead simply loop it). - The queue can afford to be quite large in most realistic production deployments, and it is advised that it be so (10000+).
-
Nested Class Summary
Nested Classes -
Method Summary
Modifier and TypeMethodDescriptionbuilder()
void
submit
(TransactionOutboxEntry entry, Consumer<TransactionOutboxEntry> localExecutor) Submits a transaction outbox task for processing.void
validate
(com.gruelbox.transactionoutbox.Validator validator)
-
Method Details
-
submit
Description copied from interface:Submitter
Submits a transaction outbox task for processing. TheTransactionOutboxEntry
is provided, along with alocalExecutor
which can run the work immediately. An implementation may validly do any of the following:- Submit a call to
localExecutor
in a local thread, e.g. using anExecutor
. This is what implementations returned bySubmitter.withExecutor(Executor)
orSubmitter.withDefaultExecutor()
will do, and is recommended in almost all cases. - Serialize the
TransactionOutboxEntry
, send it to another instance (e.g. via a queue) and have the handler code callTransactionOutbox.processNow(TransactionOutboxEntry)
. Such an approach should not generally be necessary sinceTransactionOutbox.flush()
is designed to be called repeatedly on multiple instances. This means there is a degree of load balancing built into the system, but when dealing with very high load, very low run-time tasks, this can get overwhelmed and direct multi-instance queuing can help balance the load at source. Note: it is recommended that theinvocation
property of theTransactionOutboxEntry
be serialized usingInvocationSerializer.createDefaultJsonSerializer()
- Pass the
entry
directly to thelocalExecutor
. This will run the work immediately in the calling thread and is therefore generally not recommended; the calling thread will be either the thread callingTransactionOutbox.schedule(Class)
(effectively making the work synchronous) or the background poll thread (limiting work in progress to one). It can, however, be useful for test cases.
- Specified by:
submit
in interfaceSubmitter
- Parameters:
entry
- The entry to process.localExecutor
- Provides a means of running the work directly locally (it is effectively just a call toTransactionOutbox.processNow(TransactionOutboxEntry)
).
- Submit a call to
-
validate
public void validate(com.gruelbox.transactionoutbox.Validator validator) -
builder
-