I
- the type of IDs of projectionsP
- the type of projectionsS
- the type of projection state messagespublic abstract class ProjectionRepository<I,P extends Projection<I,S,?>,S extends io.spine.base.EntityState> extends EventDispatchingRepository<I,P,S>
Projection
s.
Provides an API for the entity catch-up. During this
process, the framework re-builds the states of all or the selected projection instances
by replaying the historical events from the EventStore
of its Bounded Context.
The catch-up process is fully automated and may be scaled across instances.
To start the catch-up, one should call a corresponding method (see below).
TaskViewRepository repository = new TaskViewRepository(); BoundedContextBuilder builder = BoundedContext.singleTenant("Tasks") .add(repository) .build(); // ... //Start the catch-up when needed: Timestamp replayHistorySince = ... repository.catchUp(replayHistorySince, ImmutableSet.of(outdatedTaskId, anotherOne));
All the live events dispatched to the entities-under-catch-up are not lost. They are preserved and dispatched to the projections in a proper historical order.
After the catch-up is completed, the framework automatically switches back to the propagation of the live events.
Constructor and Description |
---|
ProjectionRepository() |
Modifier and Type | Method and Description |
---|---|
boolean |
canDispatch(EventEnvelope event)
Checks if this dispatcher can dispatch the given message.
|
io.spine.server.delivery.CatchUpId |
catchUp(com.google.protobuf.Timestamp since,
@Nullable java.util.Set<I> ids)
Repeats the dispatching of the events from the event log to the requested entities
since the specified time.
|
io.spine.server.delivery.CatchUpId |
catchUpAll(com.google.protobuf.Timestamp since)
Starts the catch-up of all entities in this repository.
|
void |
close()
Closes the repository by closing the underlying storage.
|
P |
create(I id)
Create a new entity instance with its default state.
|
protected ProjectionStorage<I> |
createStorage()
Creates the storage for this repository.
|
protected void |
dispatchTo(I id,
io.spine.core.Event event)
Dispatches the given event to an entity with the given ID.
|
com.google.common.collect.ImmutableSet<EventClass> |
domesticEventClasses()
Obtains classes of domestic events processed by this dispatcher.
|
com.google.common.collect.ImmutableSet<EventClass> |
externalEventClasses()
Obtains classes of external events processed by this dispatcher.
|
protected P |
findOrCreate(I id)
Loads an entity by the passed ID or creates a new one, if the entity was not found.
|
com.google.common.collect.ImmutableSet<EventClass> |
messageClasses()
Obtains a set of message classes that can be processed by this dispatcher.
|
protected RecordStorage<I> |
recordStorage()
Ensures that the repository has the storage.
|
void |
registerWith(BoundedContext context)
Initializes the repository.
|
protected void |
setupEventRouting(EventRouting<I> routing)
A callback for derived repository classes to customize routing schema for events.
|
protected void |
setupStateRouting(StateUpdateRouting<I> routing)
A callback for derived repository classes to customize routing schema for delivering
updated state to subscribed entities, if the default schema does not satisfy
the routing needs.
|
protected Stand |
stand()
Obtains the
Stand from the BoundedContext of this repository. |
void |
store(P entity)
Stores the passed object.
|
dispatch, route
entityFactory, storageConverter
applyMigration, applyMigration, find, find, findActive, iterator, loadAll, loadAll, store, toEntity
checkStorage, context, entityClass, entityStateType, eventFilter, hasContext, idClass, index, isOpen, isRegistered, onRegistered, open, storage, storageAssigned
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
dispatchesEvents, dispatchesExternalEvents, eventClasses
@OverridingMethodsMustInvokeSuper public void registerWith(BoundedContext context) throws java.lang.IllegalStateException
Ensures there is at least one event subscriber method (external or domestic) declared
by the class of the projection. Throws an IllegalStateException
otherwise.
If projections of this repository are subscribed to
entity state updates, a routing for state updates is created and
configured.
If one of the states of entities cannot be routed during the created schema,
IllegalStateException
will be thrown.
Initializes the Inbox
es for the instances of this repository and creates
a RepositoryCache
to optimize the delivery of the event batches.
Creates an instance of the CatchUpProcess
enabling this repository to catch-up its instances.
registerWith
in class EventDispatchingRepository<I,P extends Projection<I,S,?>,S extends io.spine.base.EntityState>
context
- the BoundedContext
of this repositoryjava.lang.IllegalStateException
- if the state routing does not cover one of the entity state types to which
the entities are subscribed@OverridingMethodsMustInvokeSuper protected void setupEventRouting(EventRouting<I> routing)
EventDispatchingRepository
Default routing returns the ID of the entity which produced the event. This allows to “link” different kinds of entities by having the same class of IDs. More complex scenarios (e.g. one-to-many relationships) may require custom routing schemas.
setupEventRouting
in class EventDispatchingRepository<I,P extends Projection<I,S,?>,S extends io.spine.base.EntityState>
routing
- the routing schema to customizeprotected void setupStateRouting(StateUpdateRouting<I> routing)
routing
- the routing to customize@OverridingMethodsMustInvokeSuper public P create(I id)
Repository
create
in class RecordBasedRepository<I,P extends Projection<I,S,?>,S extends io.spine.base.EntityState>
id
- the id of the entityprotected final Stand stand()
Stand
from the BoundedContext
of this repository.protected final RecordStorage<I> recordStorage()
recordStorage
in class RecordBasedRepository<I,P extends Projection<I,S,?>,S extends io.spine.base.EntityState>
java.lang.IllegalStateException
- if the storage is nullprotected final ProjectionStorage<I> createStorage()
Repository
Default implementations use Repository.defaultStorageFactory()
invoking its method
which creates a storage compatible with the repository.
Overwrite this method for creating a custom implementation of Storage
.
createStorage
in class RecordBasedRepository<I,P extends Projection<I,S,?>,S extends io.spine.base.EntityState>
protected final P findOrCreate(I id)
An entity will be loaded whether its active or not.
The new entity is created if and only if there is no record with the corresponding ID.
Overrides to perform finding using the cache.
findOrCreate
in class RecordBasedRepository<I,P extends Projection<I,S,?>,S extends io.spine.base.EntityState>
id
- the ID of the entity to loadpublic final void store(P entity)
Repository
Note: The storage must be assigned before calling this method.
store
in class RecordBasedRepository<I,P extends Projection<I,S,?>,S extends io.spine.base.EntityState>
entity
- an instance to storepublic final com.google.common.collect.ImmutableSet<EventClass> messageClasses()
MessageDispatcher
public final com.google.common.collect.ImmutableSet<EventClass> domesticEventClasses()
EventDispatcher
public final com.google.common.collect.ImmutableSet<EventClass> externalEventClasses()
EventDispatcher
@OverridingMethodsMustInvokeSuper public final boolean canDispatch(EventEnvelope event)
MessageDispatcher
This method does not check that the type of the message is one of the dispatched message classes. Instead, it validates the message upon some custom rules of this dispatcher.
Extend this method to forbid messages from being dispatched to this instance.
event
- the message to checktrue
is the given message can be dispatched by this dispatcher,
false
otherwiseprotected final void dispatchTo(I id, io.spine.core.Event event)
EventDispatchingRepository
dispatchTo
in class EventDispatchingRepository<I,P extends Projection<I,S,?>,S extends io.spine.base.EntityState>
id
- the target entity IDevent
- the event to dispatchpublic io.spine.server.delivery.CatchUpId catchUp(com.google.protobuf.Timestamp since, @Nullable java.util.Set<I> ids) throws CatchUpAlreadyStartedException
At the beginning of the process the state of each of the entities is set to the default.
During this process, the entities receive continuous updates to their state. After the
catch-up is completed, the framework automatically resumes the dispatching of ongoing live
events. When the catch-up is completed, a
CatchUpCompleted
event is emitted.
One may use the identifier of the catch-up process and subscribe to the events of this type
to understand whether the operation is done.
The subscriptions to the entity state updates (i.e.
EntityStateChanged
) events are not
supported in the catch-up.
since
- point in the past, since which the catch-up should be performedids
- identifiers of the entities to catch up, null
means that all entities should
be caught upCatchUpAlreadyStartedException
- if another catch-up for the same entity type and overlapping targets is already in
progresson a shortcut method which starts the catch-up for all
entities in this repository
public io.spine.server.delivery.CatchUpId catchUpAll(com.google.protobuf.Timestamp since) throws CatchUpAlreadyStartedException
This is a shortcut method for catchUp(since, null)
.
since
- point in the past, since which the catch-up should be performedCatchUpAlreadyStartedException
- if another catch-up for the same entity type is already in progressProjectionRepository.catchUp(Timestamp, Set)
@OverridingMethodsMustInvokeSuper public void close()
Repository
The reference to the storage becomes null after this call.
close
in interface java.lang.AutoCloseable
close
in class Repository<I,P extends Projection<I,S,?>>