Class TrackingEventProcessor
- All Implemented Interfaces:
EventProcessor,StreamingEventProcessor,Lifecycle,MessageHandlerInterceptorSupport<EventMessage<?>>
StreamableMessageSource.
A supplied TokenStore allows the EventProcessor to keep track of its position in the event log. After
processing an event batch the EventProcessor updates its tracking token in the TokenStore.
A TrackingEventProcessor is able to continue processing from the last stored token when it is restarted. It is also
capable of replaying events from any starting token. To replay the entire event log, simply invoke resetTokens() on this processor to adjust the positions of the TrackingToken(s) within the TokenStore. To replay from a specific point, resetTokens(Function) can be utilized to define the new point
to start at.
Note, the AbstractEventProcessor.getName() of this StreamingEventProcessor is used to obtain the tracking token from the
TokenStore, so take care when renaming a TrackingEventProcessor.
- Since:
- 3.0
- Author:
- Rene de Waele, Christophe Bouhier
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classBuilder class to instantiate aTrackingEventProcessor.protected static enumEnum representing the possible states of the ProcessorNested classes/interfaces inherited from interface org.axonframework.lifecycle.Lifecycle
Lifecycle.LifecycleHandler, Lifecycle.LifecycleRegistry -
Field Summary
Fields inherited from class org.axonframework.eventhandling.AbstractEventProcessor
spanFactory -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedInstantiate aTrackingEventProcessorbased on the fields contained in theTrackingEventProcessor.Builder. -
Method Summary
Modifier and TypeMethodDescriptionintReturns an approximation of the number of threads currently processing events.intReturns the number of threads this processor has available to assign segments.builder()Instantiate a Builder to be able to create aTrackingEventProcessor.protected booleancanHandle(EventMessage<?> eventMessage, Collection<Segment> segments) Indicates whether any of the components handling events for this Processor are able to handle the giveneventMessagefor any of the givensegments.claimSegment(int segmentId) Instructs the processor to claim the segment with givensegmentIdand start processing it as soon as possible.protected voiddoSleepFor(long millisToSleep) Instructs the current Thread to sleep until the given deadline.protected voiddoSleepFor(long millisToSleep, AtomicBoolean interruptFlag) Instructs the current Thread to sleep until the given deadline.StreamableMessageSource<? extends TrackedEventMessage<?>> Returns theStreamableMessageSourcethis processor is usingprotected TrackingEventProcessor.StategetState()Get the state of the event processor.Returns the unique identifier of theTokenStoreused by thisStreamingEventProcessor.booleanisError()Indicates whether the processor has been shut down due to an error.booleanIndicates whether this processor is currently running (i.e. consuming events from its message source).intSpecifies the maximum amount of segments thisEventProcessorcan process at the same time.mergeSegment(int segmentId) Instruct the processor to merge the segment with givensegmentIdback with the segment that it was originally split from.protected voidprocessingLoop(Segment segment) Fetch and process event batches continuously for as long as the processor is not shutting down.processingSegments(TrackingToken token, Segment segment) Indicates whether theeventMessageidentified with giventokenshould be processed as part of the givensegment.Returns the status for each of the segments processed by this processor asEventTrackerStatusinstances.voidRegisters the activities to be executed in the various phases of an application's lifecycle.voidreleaseSegment(int segmentId) Instructs the processor to release the segment with givensegmentId.voidreleaseSegment(int segmentId, long releaseDuration, TimeUnit unit) Instructs the processor to release the segment with givensegmentId.voidResets tokens to their initial state.voidresetTokens(Function<StreamableMessageSource<TrackedEventMessage<?>>, TrackingToken> initialTrackingTokenSupplier) Reset tokens to the position as return by the giveninitialTrackingTokenSupplier.<R> voidresetTokens(Function<StreamableMessageSource<TrackedEventMessage<?>>, TrackingToken> initialTrackingTokenSupplier, R resetContext) Reset tokens to the position as return by the giveninitialTrackingTokenSupplier.voidresetTokens(TrackingToken startPosition) Resets tokens to the givenstartPosition.<R> voidresetTokens(TrackingToken startPosition, R resetContext) Resets tokens to the givenstartPosition.<R> voidresetTokens(R resetContext) Resets tokens to their initial state.voidshutDown()Shuts down the processor.Initiates a shutdown, providing aCompletableFuturethat completes when the shutdown process is finished.splitSegment(int segmentId) Instruct the processor to split the segment with givensegmentIdinto two segments, allowing an additional process to start processing events from it.voidstart()Start this processor.protected voidStarts workers for a number of segments.booleanIndicates whether thisStreamingEventProcessorsupports a "reset".Methods inherited from class org.axonframework.eventhandling.AbstractEventProcessor
canHandle, canHandleType, eventHandlerInvoker, getHandlerInterceptors, getName, processInUnitOfWork, processInUnitOfWork, registerHandlerInterceptor, reportIgnored, toStringMethods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, waitMethods inherited from interface org.axonframework.eventhandling.EventProcessor
getHandlerInterceptors, getNameMethods inherited from interface org.axonframework.messaging.MessageHandlerInterceptorSupport
registerHandlerInterceptorMethods inherited from interface org.axonframework.eventhandling.StreamingEventProcessor
isReplaying
-
Constructor Details
-
TrackingEventProcessor
Instantiate aTrackingEventProcessorbased on the fields contained in theTrackingEventProcessor.Builder.Will assert that the Event Processor
name,EventHandlerInvoker,StreamableMessageSource,TokenStoreandTransactionManagerare notnull, and will throw anAxonConfigurationExceptionif any of them isnull.- Parameters:
builder- theTrackingEventProcessor.Builderused to instantiate aTrackingEventProcessorinstance
-
-
Method Details
-
builder
Instantiate a Builder to be able to create aTrackingEventProcessor.The
RollbackConfigurationTypedefaults to aRollbackConfigurationType.ANY_THROWABLE, theErrorHandleris defaulted to aPropagatingErrorHandler, theMessageMonitordefaults to aNoOpMessageMonitor, theTrackingEventProcessorConfigurationto aTrackingEventProcessorConfiguration.forSingleThreadedProcessing()call, and theEventProcessorSpanFactoryto aDefaultEventProcessorSpanFactorybacked by aNoOpSpanFactory. The Event Processorname,EventHandlerInvoker,StreamableMessageSource,TokenStoreandTransactionManagerare hard requirements and as such should be provided.- Returns:
- a Builder to be able to create a
TrackingEventProcessor
-
registerLifecycleHandlers
Description copied from interface:LifecycleRegisters the activities to be executed in the various phases of an application's lifecycle. This could either be at startup, shutdown, or both.- Specified by:
registerLifecycleHandlersin interfaceLifecycle- Parameters:
handle- the lifecycle instance to register the handlers with- See Also:
-
start
public void start()Start this processor. The processor will open an event stream on its message source in a new thread usingStreamableMessageSource.openStream(TrackingToken). TheTrackingTokenused to open the stream will be fetched from theTokenStore.Upon start up of an application, this method will be invoked in the
Phase.INBOUND_EVENT_CONNECTORSphase.- Specified by:
startin interfaceEventProcessor
-
splitSegment
Description copied from interface:StreamingEventProcessorInstruct the processor to split the segment with givensegmentIdinto two segments, allowing an additional process to start processing events from it.To be able to split segments, the
TokenStoreconfigured with this processor must use explicitly initialized tokens. SeeTokenStore.requiresExplicitSegmentInitialization(). Also, the givensegmentIdmust be currently processed by a process owned by this processor instance.- Specified by:
splitSegmentin interfaceStreamingEventProcessor- Parameters:
segmentId- the identifier of the segment to split- Returns:
- a
CompletableFutureproviding the result of the split operation
-
getTokenStoreIdentifier
Description copied from interface:StreamingEventProcessorReturns the unique identifier of theTokenStoreused by thisStreamingEventProcessor.- Specified by:
getTokenStoreIdentifierin interfaceStreamingEventProcessor- Returns:
- the unique identifier of the
TokenStoreused by thisStreamingEventProcessor
-
mergeSegment
Description copied from interface:StreamingEventProcessorInstruct the processor to merge the segment with givensegmentIdback with the segment that it was originally split from. The processor must be able to claim the other segment, in order to merge it. Therefore, this other segment must not have any active claims in theTokenStore.The processor must currently be actively processing the segment with given
segmentId.Use
StreamingEventProcessor.releaseSegment(int)to force this processor to release any claims with tokens required to merge the segments.To find out which segment a given
segmentIdshould be merged with, use the following procedure:EventTrackerStatus status = processor.processingStatus().get(segmentId); if (status == null) { // this processor is not processing segmentId, and will not be able to merge } return status.getSegment().mergeableSegmentId();- Specified by:
mergeSegmentin interfaceStreamingEventProcessor- Parameters:
segmentId- the identifier of the segment to merge- Returns:
- a
CompletableFutureindicating whether the merge was executed successfully
-
processingLoop
Fetch and process event batches continuously for as long as the processor is not shutting down. The processor will process events in batches. The maximum size of size of each event batch is configurable.Events with the same tracking token (which is possible as result of upcasting) should always be processed in the same batch. In those cases the batch size may be larger than the one configured.
- Parameters:
segment- TheSegmentof the Stream that should be processed.
-
processingSegments
Indicates whether theeventMessageidentified with giventokenshould be processed as part of the givensegment. This implementation is away of merge tokens and will recursively detect the (sub)segment in which an event should be handled.- Parameters:
token- The token to check segment validity forsegment- The segment to process the event in- Returns:
trueif this event should be handled, otherwisefalse
-
canHandle
protected boolean canHandle(EventMessage<?> eventMessage, Collection<Segment> segments) throws Exception Indicates whether any of the components handling events for this Processor are able to handle the giveneventMessagefor any of the givensegments.- Parameters:
eventMessage- The message to handlesegments- The segments to handle the message in- Returns:
- whether the given message should be handled as part of anyof the give segments
- Throws:
Exception- when an exception occurs evaluating the message
-
releaseSegment
public void releaseSegment(int segmentId) Instructs the processor to release the segment with givensegmentId.This will also ignore the specified this segment for "re-claiming" for twice the
TrackingEventProcessorConfiguration.getTokenClaimInterval()token claim interval.- Specified by:
releaseSegmentin interfaceStreamingEventProcessor- Parameters:
segmentId- the id of the segment to release
-
releaseSegment
Instructs the processor to release the segment with givensegmentId. This processor will not try to claim the given segment for the specifiedreleaseDurationin the givenunit, to ensure it is not immediately reclaimed. Note that this will override any previous release duration that existed for this segment. Providing a negative value will allow the segment to be immediately claimed.If the processor is not actively processing the segment with given
segmentId, claiming it will be ignored for the given timeframe nonetheless.This method will put the segment on a non-claim map. During the next iteration of the
processingLoop(Segment)the segments will be unclaimed and the worker stopped if it is found to be in this map. This means it can take up to the batch processing time, or up to theeventAvailabilityTimeoutif there are no events in the stream for the segment to be unclaimed.- Specified by:
releaseSegmentin interfaceStreamingEventProcessor- Parameters:
segmentId- the id of the segment to be released for the specifiedreleaseDurationreleaseDuration- the amount of time to disregardsegmentIdfor processingunit- the unit of time used to express thereleaseDuration
-
claimSegment
Instructs the processor to claim the segment with givensegmentIdand start processing it as soon as possible.The given
segmentIdmust not be currently processed by a different processor instance, as that will have an active claim on the token. Claiming a segment that is already being processed will have no effect and returntrue.A
truereturn value indicates that the segment has been claimed and will be processed by this processor. TheStreamingEventProcessormay postpone start of work until after completion of this task, as long as the token has been claimed so work can be started. A return value offalseindicates that the segment has not been claimed due to the token for that segment not being available.This method will add an instruction for the
TrackingEventProcessor.WorkerLauncherand set a flag that interrupts its sleep to reduce the time it takes for the processor to claim the segment. Note that a thread has to be available for a segment to start processing. The result will befalseif there is none available.- Specified by:
claimSegmentin interfaceStreamingEventProcessor- Parameters:
segmentId- the identifier of the segment to claim and start processing- Returns:
- a
CompletableFutureproviding the result of the claim operation
-
resetTokens
public void resetTokens()Description copied from interface:StreamingEventProcessorResets tokens to their initial state. This effectively causes a replay.Before attempting to reset the tokens, the caller must stop this processor, as well as any instances of the same logical processor that may be running in the cluster. Failure to do so will cause the reset to fail, as a processor can only reset the tokens if it is able to claim them all.
- Specified by:
resetTokensin interfaceStreamingEventProcessor
-
resetTokens
public <R> void resetTokens(R resetContext) Description copied from interface:StreamingEventProcessorResets tokens to their initial state. This effectively causes a replay. The givenresetContextwill be used to support the (optional) reset operation in an Event Handling Component.Before attempting to reset the tokens, the caller must stop this processor, as well as any instances of the same logical processor that may be running in the cluster. Failure to do so will cause the reset to fail, as a processor can only reset the tokens if it is able to claim them all.
- Specified by:
resetTokensin interfaceStreamingEventProcessor- Type Parameters:
R- the type of the providedresetContext- Parameters:
resetContext- aRused to support the reset operation
-
resetTokens
public void resetTokens(@Nonnull Function<StreamableMessageSource<TrackedEventMessage<?>>, TrackingToken> initialTrackingTokenSupplier) Description copied from interface:StreamingEventProcessorReset tokens to the position as return by the giveninitialTrackingTokenSupplier. This effectively causes a replay since that position.Note that the new token must represent a position that is before the current position of the processor.
Before attempting to reset the tokens, the caller must stop this processor, as well as any instances of the same logical processor that may be running in the cluster. Failure to do so will cause the reset to fail, as a processor can only reset the tokens if it is able to claim them all.
- Specified by:
resetTokensin interfaceStreamingEventProcessor- Parameters:
initialTrackingTokenSupplier- a function returning the token representing the position to reset to
-
resetTokens
public <R> void resetTokens(@Nonnull Function<StreamableMessageSource<TrackedEventMessage<?>>, TrackingToken> initialTrackingTokenSupplier, R resetContext) Description copied from interface:StreamingEventProcessorReset tokens to the position as return by the giveninitialTrackingTokenSupplier. This effectively causes a replay since that position. The givenresetContextwill be used to support the (optional) reset operation in an Event Handling Component.Note that the new token must represent a position that is before the current position of the processor.
Before attempting to reset the tokens, the caller must stop this processor, as well as any instances of the same logical processor that may be running in the cluster. Failure to do so will cause the reset to fail, as a processor can only reset the tokens if it is able to claim them all.
- Specified by:
resetTokensin interfaceStreamingEventProcessor- Type Parameters:
R- the type of the providedresetContext- Parameters:
initialTrackingTokenSupplier- a function returning the token representing the position to reset toresetContext- aRused to support the reset operation
-
resetTokens
Description copied from interface:StreamingEventProcessorResets tokens to the givenstartPosition. This effectively causes a replay of events since that position.Note that the new token must represent a position that is before the current position of the processor.
Before attempting to reset the tokens, the caller must stop this processor, as well as any instances of the same logical processor that may be running in the cluster. Failure to do so will cause the reset to fail, as a processor can only reset the tokens if it is able to claim them all.
- Specified by:
resetTokensin interfaceStreamingEventProcessor- Parameters:
startPosition- the token representing the position to reset the processor to
-
resetTokens
Description copied from interface:StreamingEventProcessorResets tokens to the givenstartPosition. This effectively causes a replay of events since that position. The givenresetContextwill be used to support the (optional) reset operation in an Event Handling Component.Note that the new token must represent a position that is before the current position of the processor.
Before attempting to reset the tokens, the caller must stop this processor, as well as any instances of the same logical processor that may be running in the cluster. Failure to do so will cause the reset to fail, as a processor can only reset the tokens if it is able to claim them all.
- Specified by:
resetTokensin interfaceStreamingEventProcessor- Type Parameters:
R- the type of the providedresetContext- Parameters:
startPosition- the token representing the position to reset the processor toresetContext- aRused to support the reset operation
-
supportsReset
public boolean supportsReset()Description copied from interface:StreamingEventProcessorIndicates whether thisStreamingEventProcessorsupports a "reset". Generally, a reset is supported if at least one of the Event Handling Components assigned to this processor supports it, and no handlers explicitly prevent the resets.This method should be invoked prior to invoking any of the
StreamingEventProcessor.resetTokens()operations as an early validation.- Specified by:
supportsResetin interfaceStreamingEventProcessor- Returns:
trueif resets are supported,falseotherwise
-
isRunning
public boolean isRunning()Description copied from interface:EventProcessorIndicates whether this processor is currently running (i.e. consuming events from its message source).- Specified by:
isRunningin interfaceEventProcessor- Returns:
truewhen running, otherwisefalse
-
isError
public boolean isError()Description copied from interface:EventProcessorIndicates whether the processor has been shut down due to an error. In such case, the processor has forcefully shut down, as it wasn't able to automatically recover.Note that this method returns
falsewhen the processor was stopped usingEventProcessor.shutDown().- Specified by:
isErrorin interfaceEventProcessor- Returns:
truewhen paused due to an error, otherwisefalse
-
getMessageSource
Returns theStreamableMessageSourcethis processor is using- Returns:
StreamableMessageSource
-
shutDown
public void shutDown()Shuts down the processor. Blocks until shutdown is complete.- Specified by:
shutDownin interfaceEventProcessor
-
shutdownAsync
Initiates a shutdown, providing aCompletableFuturethat completes when the shutdown process is finished.Will be shutdown on the
Phase.INBOUND_EVENT_CONNECTORSphase.- Specified by:
shutdownAsyncin interfaceEventProcessor- Returns:
- a CompletableFuture that completes when the shutdown process is finished.
-
availableProcessorThreads
public int availableProcessorThreads()Returns the number of threads this processor has available to assign segments. These threads may or may not already be active.- Returns:
- the number of threads this processor has available to assign segments.
-
maxCapacity
public int maxCapacity()Description copied from interface:StreamingEventProcessorSpecifies the maximum amount of segments thisEventProcessorcan process at the same time.- Specified by:
maxCapacityin interfaceStreamingEventProcessor- Returns:
- the maximum amount of segments this
EventProcessorcan process at the same time
-
activeProcessorThreads
public int activeProcessorThreads()Returns an approximation of the number of threads currently processing events.- Returns:
- an approximation of the number of threads currently processing events
-
processingStatus
Description copied from interface:StreamingEventProcessorReturns the status for each of the segments processed by this processor asEventTrackerStatusinstances. The key of theMaprepresent the segment ids processed by this instance. The values of the returnedMaprepresent the last known status of that segment.Note that the returned
Mapis unmodifiable, but does reflect any changes made to the status as the processor is processing Events.- Specified by:
processingStatusin interfaceStreamingEventProcessor- Returns:
- the status for each of the segments processed by the current processor
-
getState
Get the state of the event processor. This will indicate whether or not the processor has started or is shutting down.- Returns:
- the processor state
-
startSegmentWorkers
protected void startSegmentWorkers()Starts workers for a number of segments. When only therootsegmentexistsin the TokenStore, it will be split in multiple segments as configured by theTrackingEventProcessorConfiguration.andInitialSegmentsCount(int), otherwise the existing segments in the TokenStore will be used. An attempt will be made to instantiate a worker for each segment. This will succeed when the number of threads matches the requested segments. The number of active threads can be configured withTrackingEventProcessorConfiguration.forParallelProcessing(int). When insufficient threads are available to serve the number of segments, it will result in some segments not being processed. -
doSleepFor
protected void doSleepFor(long millisToSleep) Instructs the current Thread to sleep until the given deadline. This method may be overridden to check for flags that have been set to return earlier than the given deadline.The default implementation will sleep in blocks of 100ms, intermittently checking for the processor's state. Once the processor stops running, this method will return immediately (after detecting the state change).
- Parameters:
millisToSleep- The number of milliseconds to sleep
-
doSleepFor
Instructs the current Thread to sleep until the given deadline. This method may be overridden to check for flags that have been set to return earlier than the given deadline.The default implementation will sleep in blocks of 100ms, intermittently checking for the processor's state. Once the processor stops running, this method will return immediately (after detecting the state change).
This method will also return when the given interruptFlag is set to
true. This can facilitate immediately needed actions for the sleeping thread.- Parameters:
millisToSleep- The number of milliseconds to sleepinterruptFlag- A flag that is set when the thread should stop sleeping
-