Class JpaTokenStore
- All Implemented Interfaces:
TokenStore
TokenEntry
entities.- Since:
- 3.0
- Author:
- Rene de Waele
-
Nested Class Summary
Nested Classes -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedJpaTokenStore(JpaTokenStore.Builder builder) Instantiate aJpaTokenStorebased on the fields contained in theJpaTokenStore.Builder. -
Method Summary
Modifier and TypeMethodDescriptionstatic JpaTokenStore.Builderbuilder()Instantiate a Builder to be able to create aJpaTokenStore.voiddeleteToken(String processorName, int segment) Deletes the token for the processor with givenprocessorNameandsegment.voidextendClaim(String processorName, int segment) Extends the claim on the current token held by the this node for the givenprocessorNameandsegment.fetchAvailableSegments(String processorName) Returns a List of known availablesegmentsfor a givenprocessorName.int[]fetchSegments(String processorName) Returns an array of knownsegmentsfor a givenprocessorName.fetchToken(String processorName, int segment) fetchToken(String processorName, Segment segment) voidinitializeSegment(TrackingToken token, String processorName, int segment) Initializes a segment with givensegmentfor the processor with givenprocessorNameto contain the giventoken.voidinitializeTokenSegments(String processorName, int segmentCount) Initializes the givensegmentCountnumber of segments for the givenprocessorNameto track its tokens.voidinitializeTokenSegments(String processorName, int segmentCount, TrackingToken initialToken) Initializes the givensegmentCountnumber of segments for the givenprocessorNameto track its tokens.protected TokenEntryLoads an existingTokenEntryor creates a new one using the givenentityManagerfor givenprocessorNameandsegment.protected TokenEntryTries loading an existing token owned by a processor with givenprocessorNameandsegment.voidreleaseClaim(String processorName, int segment) Release a claim of the token for givenprocessorNameandsegment.booleanIndicates whether this TokenStore instance requires segments to be explicitly initialized, before any tokens can be claimed for that segment.Returns a unique identifier that uniquely identifies the storage location of the tokens in this store.Returns the serializer used by the Token Store to serialize tokens.voidstoreToken(TrackingToken token, String processorName, int segment) Stores the giventokenin the store.
-
Constructor Details
-
JpaTokenStore
Instantiate aJpaTokenStorebased on the fields contained in theJpaTokenStore.Builder.Will assert that the
EntityManager,Serializer,claimTimeoutandnodeIdare notnull, and will throw anAxonConfigurationExceptionif any of them isnull.- Parameters:
builder- theJpaTokenStore.Builderused to instantiate aJpaTokenStoreinstance
-
-
Method Details
-
builder
Instantiate a Builder to be able to create aJpaTokenStore.The
claimTimeoutto a 10 seconds duration, andnodeIdis defaulted to the name of the managed bean for the runtime system of the Java virtual machine. TheEntityManagerProviderandSerializerare a hard requirements and as such should be provided.- Returns:
- a Builder to be able to create a
JpaTokenStore
-
initializeTokenSegments
public void initializeTokenSegments(@Nonnull String processorName, int segmentCount) throws UnableToClaimTokenException Description copied from interface:TokenStoreInitializes the givensegmentCountnumber of segments for the givenprocessorNameto track its tokens. This method should only be invoked when no tokens have been stored for the given processor, yet.This method will initialize the tokens, but not claim them. It will create the segments ranging from
0untilsegmentCount - 1.The exact behavior when this method is called while tokens were already present, is undefined in case the token already present is not owned by the initializing process.
- Specified by:
initializeTokenSegmentsin interfaceTokenStore- Parameters:
processorName- The name of the processor to initialize segments forsegmentCount- The number of segments to initialize- Throws:
UnableToClaimTokenException- when a segment has already been created
-
initializeTokenSegments
public void initializeTokenSegments(@Nonnull String processorName, int segmentCount, @Nullable TrackingToken initialToken) throws UnableToClaimTokenException Description copied from interface:TokenStoreInitializes the givensegmentCountnumber of segments for the givenprocessorNameto track its tokens. This method should only be invoked when no tokens have been stored for the given processor, yet.This method will store
initialTokenfor all segments as starting point for processor, but not claim them. It will create the segments ranging from0untilsegmentCount - 1.The exact behavior when this method is called while tokens were already present, is undefined in case the token already present is not owned by the initializing process.
- Specified by:
initializeTokenSegmentsin interfaceTokenStore- Parameters:
processorName- The name of the processor to initialize segments forsegmentCount- The number of segments to initializeinitialToken- The initial token which is used as a starting point for processor- Throws:
UnableToClaimTokenException- when a segment has already been created
-
storeToken
Description copied from interface:TokenStoreStores the giventokenin the store. The token marks the current position of the process with givenprocessorNameandsegment. The giventokenmay benull. Any claims made by the current process have their timestamp updated.This method should throw an
UnableToClaimTokenExceptionwhen the givensegmenthas not been initialized with a Token (albeitnull) yet. In that case, a segment must have been explicitly initialized. A TokenStore implementation's ability to do so is exposed by theTokenStore.requiresExplicitSegmentInitialization()method. If that method returns false, this method may implicitly initialize a token and return that token upon invocation.- Specified by:
storeTokenin interfaceTokenStore- Parameters:
token- The token to store for a given process and segment. May benull.processorName- The name of the process for which to store the tokensegment- The index of the segment for which to store the token
-
releaseClaim
Description copied from interface:TokenStoreRelease a claim of the token for givenprocessorNameandsegment. If no such claim existed, nothing happens.The caller must ensure not to use any streams opened based on the token for which the claim is released.
- Specified by:
releaseClaimin interfaceTokenStore- Parameters:
processorName- The name of the process owning the token (e.g. a TrackingEventProcessor name)segment- the segment for which a token was obtained
-
initializeSegment
public void initializeSegment(@Nullable TrackingToken token, @Nonnull String processorName, int segment) throws UnableToInitializeTokenException Description copied from interface:TokenStoreInitializes a segment with givensegmentfor the processor with givenprocessorNameto contain the giventoken.This method fails if a Token already exists for the given processor and segment, even if that token has been claimed by the active instance.
This method will not claim the initialized segment. Use
TokenStore.fetchToken(String, int)to retrieve and claim the token.- Specified by:
initializeSegmentin interfaceTokenStore- Parameters:
token- The token to initialize the segment withprocessorName- The name of the processor to create the segment forsegment- The identifier of the segment to initialize- Throws:
UnableToInitializeTokenException- if a Token already exists
-
requiresExplicitSegmentInitialization
public boolean requiresExplicitSegmentInitialization()Description copied from interface:TokenStoreIndicates whether this TokenStore instance requires segments to be explicitly initialized, before any tokens can be claimed for that segment.- Specified by:
requiresExplicitSegmentInitializationin interfaceTokenStore- Returns:
trueif this instance requires tokens to be explicitly initialized, otherwisefalse.- See Also:
-
deleteToken
public void deleteToken(@Nonnull String processorName, int segment) throws UnableToClaimTokenException Description copied from interface:TokenStoreDeletes the token for the processor with givenprocessorNameandsegment. The token must be owned by the current node, to be able to delete it.Implementations should implement this method only when
TokenStore.requiresExplicitSegmentInitialization()is overridden to returntrue. Deleting tokens using implementations that do not require explicit token initialization is unsafe, as a claim will automatically recreate the deleted token instance, which may result in concurrency issues.- Specified by:
deleteTokenin interfaceTokenStore- Parameters:
processorName- The name of the processor to remove the token forsegment- The segment to delete- Throws:
UnableToClaimTokenException- if the token is not currently claimed by this node
-
fetchToken
Description copied from interface:TokenStoreReturns the last storedtokenfor the givenprocessorNameandsegment. Returnsnullif the stored token for the given process and segment isnull.This method should throw an
UnableToClaimTokenExceptionwhen the givensegmenthas not been initialized with a Token (albeitnull) yet. In that case, a segment must have been explicitly initialized. A TokenStore implementation's ability to do so is exposed by theTokenStore.requiresExplicitSegmentInitialization()method. If that method returns false, this method may implicitly initialize a token and return that token upon invocation.The token will be claimed by the current process (JVM instance), preventing access by other instances. To release the claim, use
TokenStore.releaseClaim(String, int)- Specified by:
fetchTokenin interfaceTokenStore- Parameters:
processorName- The process name for which to fetch the tokensegment- The segment index for which to fetch the token- Returns:
- The last stored TrackingToken or
nullif the store holds no token for given process and segment
-
fetchToken
public TrackingToken fetchToken(@Nonnull String processorName, @Nonnull Segment segment) throws UnableToClaimTokenException Description copied from interface:TokenStoreReturns the last storedtokenfor the givenprocessorNameandsegment. Returnsnullif the stored token for the given process and segment isnull.This method should throw an
UnableToClaimTokenExceptionwhen the givensegmenthas not been initialized with a Token (albeitnull) yet. In that case, a segment must have been explicitly initialized. A TokenStore implementation's ability to do so is exposed by theTokenStore.requiresExplicitSegmentInitialization()method. If that method returns false, this method may implicitly initialize a token and return that token upon invocation.The token will be claimed by the current process (JVM instance), preventing access by other instances. To release the claim, use
TokenStore.releaseClaim(String, int)- Specified by:
fetchTokenin interfaceTokenStore- Parameters:
processorName- The process name for which to fetch the tokensegment- The segment for which to fetch the token- Returns:
- The last stored TrackingToken or
nullif the store holds no token for given process and segment - Throws:
UnableToClaimTokenException- if there is a token for givenprocessorNameandsegment, but they are claimed by another process, or if thesegment has been split or merged concurrently
-
extendClaim
public void extendClaim(@Nonnull String processorName, int segment) throws UnableToClaimTokenException Description copied from interface:TokenStoreExtends the claim on the current token held by the this node for the givenprocessorNameandsegment.- Specified by:
extendClaimin interfaceTokenStore- Parameters:
processorName- The process name for which to fetch the tokensegment- The segment index for which to fetch the token- Throws:
UnableToClaimTokenException- if there is no token for givenprocessorNameandsegment, or if it has been claimed by another process.
-
fetchSegments
Description copied from interface:TokenStoreReturns an array of knownsegmentsfor a givenprocessorName.The segments returned are segments for which a token has been stored previously. When the
TokenStoreis empty, an empty array is returned.- Specified by:
fetchSegmentsin interfaceTokenStore- Parameters:
processorName- The process name for which to fetch the segments- Returns:
- an array of segment identifiers.
-
fetchAvailableSegments
Description copied from interface:TokenStoreReturns a List of known availablesegmentsfor a givenprocessorName. A segment is considered available if it is not claimed by any other event processor.The segments returned are segments for which a token has been stored previously and have not been claimed by another processor. When the
TokenStoreis empty, an empty list is returned. By default, if this method is not implemented, we will return all segments instead, whether they are available or not.- Specified by:
fetchAvailableSegmentsin interfaceTokenStore- Parameters:
processorName- the processor's name for which to fetch the segments- Returns:
- a List of available segment identifiers for the specified
processorName
-
loadToken
protected TokenEntry loadToken(String processorName, int segment, jakarta.persistence.EntityManager entityManager) Loads an existingTokenEntryor creates a new one using the givenentityManagerfor givenprocessorNameandsegment.- Parameters:
processorName- the name of the event processorsegment- the segment of the event processorentityManager- the entity manager instance to use for the query- Returns:
- the token entry for the given processor name and segment
- Throws:
UnableToClaimTokenException- if there is a token for givenprocessorNameandsegment, but it is claimed by another process.
-
loadToken
protected TokenEntry loadToken(String processorName, Segment segment, jakarta.persistence.EntityManager entityManager) Tries loading an existing token owned by a processor with givenprocessorNameandsegment. If such a token entry exists an attempt will be made to claim the token. If that succeeds the token will be returned. If the token is already owned by another node anUnableToClaimTokenExceptionwill be thrown.If no such token exists yet, a new token entry will be inserted with a
nulltoken, owned by this node, and this method returnsnull.If a token has been claimed, the
segmentwill be validated by checking the database for the split and merge candidate segments. If a concurrent split or merge operation has been detected, the calim will be released and anUnableToClaimTokenExceptionwill be thrown.}- Parameters:
processorName- the name of the processor to load or insert a token entry forsegment- the segment of the processor to load or insert a token entry forentityManager- the entity manager instance to use for the query- Returns:
- the tracking token of the fetched entry or
nullif a new entry was inserted - Throws:
UnableToClaimTokenException- if the token cannot be claimed because another node currently owns the token or if the segment has been split or merged concurrently
-
retrieveStorageIdentifier
Description copied from interface:TokenStoreReturns a unique identifier that uniquely identifies the storage location of the tokens in this store. Two token store implementations that share state, must return the same identifier. Two token store implementations that do not share a location, must return a different identifier (or an empty optional if identifiers are not supported).Note that this method may require the implementation to consult its underlying storage. Therefore, a Transaction should be active when this method is called, similarly to invocations like
TokenStore.fetchToken(String, int),TokenStore.fetchSegments(String), etc. When no Transaction is active, the behavior is undefined.- Specified by:
retrieveStorageIdentifierin interfaceTokenStore- Returns:
- an identifier to uniquely identify the storage location of tokens in this TokenStore.
-
serializer
Returns the serializer used by the Token Store to serialize tokens.- Returns:
- the serializer used by the Token Store to serialize tokens
-