Search Results for

    Show / Hide Table of Contents

    Snapshots

    Snapshots can dramatically reduce recovery times of persistent actors and views. The following discusses snapshots in context of persistent actors but this is also applicable to persistent views.

    Persistent actors can save snapshots of internal state by calling the SaveSnapshot method. If saving of a snapshot succeeds, the persistent actor receives a SaveSnapshotSuccess message, otherwise a SaveSnapshotFailure message.

    public static class Snapshots
    {
        public class MyPersistentActor : UntypedPersistentActor
        {
            public override string PersistenceId => "my-stable-persistence-id";
            private const int SnapShotInterval = 1000;
            private object state = new();
    
            protected override void OnRecover(object message)
            {
                // handle recovery here
            }
    
            protected override void OnCommand(object message)
            {
                if (message is SaveSnapshotSuccess s)
                {
                    // ...
                }
                else if (message is SaveSnapshotFailure f)
                {
                    // ...
                }
                else if (message is string cmd)
                {
                    Persist($"evt-{cmd}", e =>
                    {
                        UpdateState(e);
                        if (LastSequenceNr % SnapShotInterval == 0 && LastSequenceNr != 0)
                        {
                            SaveSnapshot(state);
                        }
                    });
                }
            }
    
            private void UpdateState(string e)
            {
    
            }
        }
    }
    

    During recovery, the persistent actor is offered a previously saved snapshot via a SnapshotOffer message from which it can initialize internal state.

    if (message is SnapshotOffer offeredSnapshot)
    {
        state = offeredSnapshot.Snapshot;
    }
    else if (message is RecoveryCompleted)
    {
        // ..
    }
    else
    {
        // event
    }
    

    The replayed messages that follow the SnapshotOffer message, if any, are younger than the offered snapshot. They finally recover the persistent actor to its current (i.e. latest) state.

    In general, a persistent actor is only offered a snapshot if that persistent actor has previously saved one or more snapshots and at least one of these snapshots matches the SnapshotSelectionCriteria that can be specified for recovery.

    public override Recovery Recovery => new Recovery(fromSnapshot: new SnapshotSelectionCriteria(maxSequenceNr: 457L, maxTimeStamp: DateTime.UtcNow));
    

    If not specified, they default to SnapshotSelectionCriteria.Latest which selects the latest (= youngest) snapshot. To disable snapshot-based recovery, applications should use SnapshotSelectionCriteria.None. A recovery where no saved snapshot matches the specified SnapshotSelectionCriteria will replay all journaled messages.

    Note

    In order to use snapshots, a default snapshot-store (akka.persistence.snapshot-store.plugin) must be configured, or the UntypedPersistentActor can pick a snapshot store explicitly by overriding SnapshotPluginId. Since it is acceptable for some applications to not use any snap-shotting, it is legal to not configure a snapshot store. However, Akka will log a warning message when this situation is detected and then continue to operate until an actor tries to store a snapshot, at which point the operation will fail (by replying with an SaveSnapshotFailure for example). Note that Cluster Sharding is using snapshots, so if you use Cluster Sharding you need to define a snapshot store plugin.

    Snapshot Deletion

    A persistent actor can delete individual snapshots by calling the DeleteSnapshot method with the sequence number of when the snapshot was taken.

    To bulk-delete a range of snapshots matching SnapshotSelectionCriteria, persistent actors should use the deleteSnapshots method. Depending on the journal used this might be inefficient. It is best practice to do specific deletes with deleteSnapshot or to include a minSequenceNr as well as a maxSequenceNr for the SnapshotSelectionCriteria.

    Optional Snapshots

    By default, the persistent actor will unconditionally be stopped if the snapshot can't be loaded in the recovery. It is possible to make snapshot loading optional. This can be useful when it is alright to ignore snapshot in case of for example deserialization errors. When snapshot loading fails it will instead recover by replaying all events.

    Enable this feature by setting snapshot-is-optional = true in the snapshot store configuration.

    Warning

    Don't set snapshot-is-optional = true if events have been deleted because that would result in wrong recovered state if snapshot load fails.

    Snapshot Status Handling

    Saving or deleting snapshots can either succeed or fail – this information is reported back to the persistent actor via status messages as illustrated in the following table.

    Method Success Failure message
    SaveSnapshot SaveSnapshotSuccess SaveSnapshotFailure
    DeleteSnapshot DeleteSnapshotSuccess DeleteSnapshotFailure
    DeleteSnapshots DeleteSnapshotsSuccess DeleteSnapshotsFailure

    If failure messages are left unhandled by the actor, a default warning log message will be logged for each incoming failure message. No default action is performed on the success messages, however you're free to handle them e.g. in order to delete an in memory representation of the snapshot, or in the case of failure to attempt save the snapshot again.

    In this article
    • githubEdit this page
    Back to top
    Contribute
    • Project Chat
    • Discussion Forum
    • Source Code
    Support
    • Akka.NET Support Plans
    • Akka.NET Observability Tools
    • Akka.NET Training & Consulting
    Maintained By
    • Petabridge - The Akka.NET Company
    • Learn Akka.NET