Class SnapshotCapableEventStorageEngine

java.lang.Object
org.axonframework.eventsourcing.eventstore.SnapshotCapableEventStorageEngine
All Implemented Interfaces:
DescribableComponent, EventStorageEngine

@Internal public class SnapshotCapableEventStorageEngine extends Object implements EventStorageEngine
Decorator for an EventStorageEngine that adds support for the SourcingStrategy.Snapshot sourcing strategy for stores that do not support this strategy natively.

When the given SourcingCondition carries a SourcingStrategy.Snapshot strategy, this decorator loads the latest snapshot from the given SnapshotStore and prepends it as a synthetic leading message to the event stream, followed by the events that occurred after the snapshot's position. If no snapshot is found, or if loading fails, it falls back to full event sourcing from the beginning.

All other sourcing strategies, as well as all append and streaming operations, are delegated directly to the wrapped engine.

Since:
5.1.0
Author:
John Hendrikx
  • Field Details

    • DECORATION_ORDER

      public static final int DECORATION_ORDER
      The decoration order used when registering this wrapper as a decorator for EventStorageEngine components.
      See Also:
  • Constructor Details

    • SnapshotCapableEventStorageEngine

      public SnapshotCapableEventStorageEngine(EventStorageEngine delegate, SnapshotStore snapshotStore)
      Constructs a SnapshotCapableEventStorageEngine wrapping the given delegate engine with snapshot loading capability backed by the given snapshotStore.
      Parameters:
      delegate - the EventStorageEngine to delegate non-snapshot operations to, cannot be null
      snapshotStore - the SnapshotStore used to load snapshots, cannot be null
  • Method Details

    • decorate

      public static EventStorageEngine decorate(EventStorageEngine engine, SnapshotStore snapshotStore)
      Returns an EventStorageEngine that supports the SourcingStrategy.Snapshot sourcing strategy, given the engine to source events from and the snapshotStore holding its snapshots.

      The given engine is returned as is when it is the given snapshotStore itself. Such an engine resolves the snapshot within its own source call, serving the snapshot and the events following it in a single round trip. Decorating it would resolve the snapshot separately and pass an absolute strategy inward, disabling that optimization.

      An engine that is already decorated is returned as is too, so composing twice is harmless. It keeps resolving snapshots from the store it was decorated with, and the given snapshotStore is ignored for it. Decorating again would put the given store in front of that one instead of adding anything.

      Any other engine is decorated, resolving the snapshot from the snapshotStore before sourcing the events that follow it.

      Parameters:
      engine - the engine to source events from
      snapshotStore - the store holding the snapshots of the given engine
      Returns:
      an event storage engine supporting the snapshot sourcing strategy
      Throws:
      NullPointerException - if the given engine or snapshotStore is null
      Since:
      5.3.0
    • source

      public MessageStream<EventMessage> source(SourcingCondition condition, @Nullable ProcessingContext context)
      Description copied from interface: EventStorageEngine
      Creates a finite MessageStream of events matching the given condition, carrying along the active ProcessingContext.

      Behaves identically to EventStorageEngine.source(SourcingCondition); the context is passed to decorators (for example snapshot-loading and tracing decorators) that need to correlate the sourcing operation with the surrounding unit of work.

      Specified by:
      source in interface EventStorageEngine
      Parameters:
      condition - the SourcingCondition dictating the stream of events to source
      context - the ProcessingContext active while sourcing; may be null
      Returns:
      a finite MessageStream of events matching the given condition
    • appendEvents

      public CompletableFuture<EventStorageEngine.AppendTransaction<?>> appendEvents(AppendCondition condition, @Nullable ProcessingContext context, List<TaggedEventMessage<?>> events)
      Description copied from interface: EventStorageEngine
      Appends a List of events to the underlying storage solution.

      Events will be appended in the order that they are offered in, validating the given condition before being stored. Note that all events should have a unique event identifier. Tags paired with the events will be stored as well.

      Implementations may be able to detect conflicts during the append stage. In such case, the returned completable future will complete exceptionally, indicating such conflict. Other implementations may delay such checks until the EventStorageEngine.AppendTransaction.commit() is called.

      Called during the PREPARE_COMMIT phase.

      Specified by:
      appendEvents in interface EventStorageEngine
      Parameters:
      condition - The condition describing the transactional requirements for the append transaction
      context - The current ProcessingContext, if any.
      events - The List of events to append to the underlying storage solution.
      Returns:
      A transaction instance that can be committed or rolled back.
    • stream

      public MessageStream<EventMessage> stream(StreamingCondition condition)
      Description copied from interface: EventStorageEngine
      Creates an infinite MessageStream of events matching the given condition.

      The condition may dictate the StreamingCondition.position() to start streaming from, as well as define filter criteria for the returned MessageStream.

      Specified by:
      stream in interface EventStorageEngine
      Parameters:
      condition - The StreamingCondition dictating the StreamingCondition.position() to start streaming from, as well as the filter criteria used for the returned MessageStream.
      Returns:
      An infinite MessageStream of events matching the given condition.
    • firstToken

      public CompletableFuture<TrackingToken> firstToken()
      Description copied from interface: EventStorageEngine
      Creates a TrackingToken that is at the first position of an event stream.

      In other words, a token that tracks events from the beginning of time.

      Specified by:
      firstToken in interface EventStorageEngine
      Returns:
      A CompletableFuture of a TrackingToken at the first position of an event stream.
    • latestToken

      public CompletableFuture<TrackingToken> latestToken()
      Description copied from interface: EventStorageEngine
      Creates a TrackingToken that is at the latest position of an event stream.

      In other words, a token that tracks all new events from this point forward.

      Specified by:
      latestToken in interface EventStorageEngine
      Returns:
      A CompletableFuture of a TrackingToken at the latest position of an event stream.
    • tokenAt

      public CompletableFuture<TrackingToken> tokenAt(Instant at)
      Description copied from interface: EventStorageEngine
      Creates a TrackingToken that tracks all events after the given at.

      If there is an event exactly at the given at, it will be tracked too.

      Specified by:
      tokenAt in interface EventStorageEngine
      Parameters:
      at - The Instant determining how the TrackingToken should be created. A tracking token should point to very first event before this Instant.
      Returns:
      A CompletableFuture of a TrackingToken at the given at, if there aren't events matching this criteria null is returned
    • describeTo

      public void describeTo(ComponentDescriptor descriptor)
      Description copied from interface: DescribableComponent
      Describe the properties of this DescribableComponent with the given descriptor.

      Components should call the appropriate describeProperty methods on the descriptor to register their properties. The descriptor is responsible for determining how these properties are formatted and structured in the final output.

      Best Practices: As a general rule, all relevant fields of a DescribableComponent implementation should be described in this method. However, developers have discretion to include only the fields that make sense in the context. Not every field may be meaningful for description purposes, especially internal implementation details. Furthermore, components might want to expose different information based on their current state. The final decision on what properties to include lies with the person implementing the describeTo method, who should focus on providing information that is useful for understanding the component's configuration and state.

      Example implementation:

       public void describeTo(ComponentDescriptor descriptor) {
           descriptor.describeProperty("name", this.name);
           descriptor.describeProperty("enabled", this.enabled);
           descriptor.describeProperty("configuration", this.configuration); // A nested component
           descriptor.describeProperty("handlers", this.eventHandlers);      // A collection
       }
       
      Specified by:
      describeTo in interface DescribableComponent
      Parameters:
      descriptor - The component descriptor to describe this DescribableComponentn its properties in.