How to remove/clean-up state of EventSourcedBehavior when task done?

I have some persistent actors (implementing EventSourcedBehavior) that manage certain jobs/tasks. When a job is completed the EventSourceBehavior that was managing it can be stopped and its state (events/snapshot) is not needed anymore. I would like to be able to remove the state when stopping the actor. Something like an Effect().deleteStateAndStop().

Is there a concept for this already? Or any other approach to avoid orphaned events/snapshots piling up?

Hi Peter,

There’s nothing to do what you ask for out of the box, at least to my knowledge. You’ll have to “manually” delete the event records you no longer need from the database.

Thank you, @chmodas. The old PersistentActor at least had one deleteSnapshots method that we were using:

deleteSnapshots(SnapshotSelectionCriteria.latest());

I don’t really like to dig into the implementation details of the journal and snapshot plug-in implementations to avoid piling up orphaned event and snapshot data. But I will consider this now or maybe use a different approach than persistent actor in the first place. Will think about this…

Hey Peter,

You can still delete events by the snapshot. And you could delete the snapshot (same documentation).

Perhaps a combination of the two would be sufficient for your case? You can end up leaving a tombstone of sorts.

Hi @chmodas, yes, this is great. I was using the RetentionCriteria already with .withDeleteEventsOnSnapshot(). And I could use a tombstone event to trigger a snapshot at the end. But this would still leave behind the last snapshot. I think this is the only part I could not figure out myself: How to delete that last snapshot?

Hey Peter,

You are right, it will leave the last snapshot. The Effect API does not provide you with any means to erase all snapshots. However, you can still achieve what you desire using the Journal and Snapshot plugin APIs, if you don’t want to touch the data directly.

Perhaps you might have an actor tasked with deleting those entities’ entries using the def asyncDeleteMessagesTo(persistenceId: String, toSequenceNr: Long) and def deleteAsync(persistenceId: String, criteria: SnapshotSelectionCriteria) to remove the events and snapshots, respectively? Something along those lines.

Borislav

Hi Peter,

I am looking for something similar, were you able to solve this ? I created a persistence event sourced actor to make sure its fail safe, but it needs to behave like a normal actor once the task is done.

Hi @Dexter, unfortunately not. I have left this code unchanged so far (it still uses classic API), which is bothering me a little bit. But I had started thinking if I am even using a too powerful weapon here. I don’t really need event sourcing in the original means in order to recover state from all events. I only need to persist state in order to recover. But the actors are pretty short living and when they are done, the state can go as well. I don’t want to risk a huge amount of orphaned state objects hanging around without a solid life cycle handling. Still the EventSourcedBehavior is really close to what I need. I was thinking whether I should write my own Behavior that does something similar or my own journal / snapshot plug-in. But I did not come to conclusion, yet (because I had just avoided to topic until now).

I have found one way to delete all snapshots, but it looks quite hacky. I could do this:

ActorPath path = _context.getSelf().path().root().child("system").child("akka.persistence.snapshot-store.local");
ActorSelection actorSelection = _context.classicActorContext().actorSelection(path);
actorSelection.tell(new SnapshotProtocol.DeleteSnapshots(persistenceId().id(), SnapshotSelectionCriteria.latest()),
        Adapter.toClassic(_context.getSelf()));
  }

But I would be curious to know if there is a better way to lookup the local snapshot actor. (side node: Using a local snapshot might look weird for a clustered environment, but it actually writes to a distributed filesystem with read-after-write consistency level.)

good afternoon, colleagues.

I also faced the need to delete the states and events of actors that will never be loaded again.

My answer is this:

If you store the events in cassandra, then its plugin has a method for deleting all events for persistId.

  /**
   * Delete everything related to one single `persistenceId`. All events,  tagged events, and
   * snapshots are deleted.
   */
  def deleteAll(persistenceId: String, neverUsePersistenceIdAgain: Boolean): Future[Done] = {

I’m sure there is something similar for other implementations of Jurnal Plugin as well.