2013-10-08 11:46:02 +02:00
|
|
|
/**
|
2015-03-07 22:58:48 -08:00
|
|
|
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
|
2013-10-08 11:46:02 +02:00
|
|
|
* Copyright (C) 2012-2013 Eligotech BV.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package akka.persistence.snapshot
|
|
|
|
|
|
|
|
|
|
import scala.concurrent.Future
|
|
|
|
|
|
|
|
|
|
import akka.actor._
|
|
|
|
|
import akka.pattern.pipe
|
|
|
|
|
import akka.persistence._
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Abstract snapshot store.
|
|
|
|
|
*/
|
2015-06-03 15:56:00 +02:00
|
|
|
trait SnapshotStore extends Actor with ActorLogging {
|
2013-10-08 11:46:02 +02:00
|
|
|
import SnapshotProtocol._
|
|
|
|
|
import context.dispatcher
|
|
|
|
|
|
2013-11-12 09:02:02 +01:00
|
|
|
private val extension = Persistence(context.system)
|
2014-01-17 06:58:25 +01:00
|
|
|
private val publish = extension.settings.internal.publishPluginCommands
|
2013-11-12 09:02:02 +01:00
|
|
|
|
2015-06-17 01:23:18 +02:00
|
|
|
final def receive = receiveSnapshotStore.orElse[Any, Unit](receivePluginInternal)
|
|
|
|
|
|
|
|
|
|
final val receiveSnapshotStore: Actor.Receive = {
|
2014-06-23 14:33:35 +02:00
|
|
|
case LoadSnapshot(persistenceId, criteria, toSequenceNr) ⇒
|
|
|
|
|
loadAsync(persistenceId, criteria.limit(toSequenceNr)) map {
|
2013-10-08 11:46:02 +02:00
|
|
|
sso ⇒ LoadSnapshotResult(sso, toSequenceNr)
|
|
|
|
|
} recover {
|
|
|
|
|
case e ⇒ LoadSnapshotResult(None, toSequenceNr)
|
2015-06-17 01:23:18 +02:00
|
|
|
} pipeTo senderPersistentActor()
|
2015-06-03 15:56:00 +02:00
|
|
|
|
2013-11-20 13:47:42 +01:00
|
|
|
case SaveSnapshot(metadata, snapshot) ⇒
|
2013-10-08 11:46:02 +02:00
|
|
|
val md = metadata.copy(timestamp = System.currentTimeMillis)
|
|
|
|
|
saveAsync(md, snapshot) map {
|
|
|
|
|
_ ⇒ SaveSnapshotSuccess(md)
|
|
|
|
|
} recover {
|
|
|
|
|
case e ⇒ SaveSnapshotFailure(metadata, e)
|
2015-06-17 01:23:18 +02:00
|
|
|
} to (self, senderPersistentActor())
|
2015-06-03 15:56:00 +02:00
|
|
|
|
2015-06-17 01:23:18 +02:00
|
|
|
case evt: SaveSnapshotSuccess ⇒
|
|
|
|
|
try tryReceivePluginInternal(evt) finally senderPersistentActor ! evt // sender is persistentActor
|
2013-11-20 13:47:42 +01:00
|
|
|
case evt @ SaveSnapshotFailure(metadata, _) ⇒
|
2015-06-17 01:23:18 +02:00
|
|
|
try {
|
|
|
|
|
tryReceivePluginInternal(evt)
|
|
|
|
|
deleteAsync(metadata)
|
|
|
|
|
} finally senderPersistentActor() ! evt // sender is persistentActor
|
2015-06-03 15:56:00 +02:00
|
|
|
|
2013-11-20 13:47:42 +01:00
|
|
|
case d @ DeleteSnapshot(metadata) ⇒
|
2015-06-03 15:56:00 +02:00
|
|
|
deleteAsync(metadata) map {
|
2015-06-17 01:23:18 +02:00
|
|
|
case _ ⇒ DeleteSnapshotSuccess(metadata)
|
2015-06-03 15:56:00 +02:00
|
|
|
} recover {
|
|
|
|
|
case e ⇒ DeleteSnapshotFailure(metadata, e)
|
2015-06-17 01:23:18 +02:00
|
|
|
} to (self, senderPersistentActor())
|
|
|
|
|
if (publish) context.system.eventStream.publish(d)
|
|
|
|
|
|
|
|
|
|
case evt: DeleteSnapshotSuccess ⇒
|
|
|
|
|
try tryReceivePluginInternal(evt) finally senderPersistentActor() ! evt
|
|
|
|
|
case evt: DeleteSnapshotFailure ⇒
|
|
|
|
|
try tryReceivePluginInternal(evt) finally senderPersistentActor() ! evt
|
2015-06-03 15:56:00 +02:00
|
|
|
|
2014-06-27 09:44:21 +02:00
|
|
|
case d @ DeleteSnapshots(persistenceId, criteria) ⇒
|
2015-06-03 15:56:00 +02:00
|
|
|
deleteAsync(persistenceId, criteria) map {
|
|
|
|
|
case _ ⇒ DeleteSnapshotsSuccess(criteria)
|
|
|
|
|
} recover {
|
|
|
|
|
case e ⇒ DeleteSnapshotsFailure(criteria, e)
|
2015-06-17 01:23:18 +02:00
|
|
|
} to (self, senderPersistentActor())
|
|
|
|
|
if (publish) context.system.eventStream.publish(d)
|
|
|
|
|
|
|
|
|
|
case evt: DeleteSnapshotsFailure ⇒
|
|
|
|
|
try tryReceivePluginInternal(evt) finally senderPersistentActor() ! evt // sender is persistentActor
|
|
|
|
|
case evt: DeleteSnapshotsSuccess ⇒
|
|
|
|
|
try tryReceivePluginInternal(evt) finally senderPersistentActor() ! evt
|
2013-10-08 11:46:02 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-17 01:23:18 +02:00
|
|
|
/** Documents intent that the sender() is expected to be the PersistentActor */
|
|
|
|
|
@inline private final def senderPersistentActor(): ActorRef = sender()
|
|
|
|
|
|
|
|
|
|
private def tryReceivePluginInternal(evt: Any): Unit =
|
|
|
|
|
if (receivePluginInternal.isDefinedAt(evt)) receivePluginInternal(evt)
|
|
|
|
|
|
2013-10-08 11:46:02 +02:00
|
|
|
//#snapshot-store-plugin-api
|
2015-06-17 01:23:18 +02:00
|
|
|
|
2013-10-08 11:46:02 +02:00
|
|
|
/**
|
2013-11-07 10:45:02 +01:00
|
|
|
* Plugin API: asynchronously loads a snapshot.
|
2013-10-08 11:46:02 +02:00
|
|
|
*
|
2014-12-08 11:02:14 +01:00
|
|
|
* @param persistenceId id of the persistent actor.
|
2013-10-08 11:46:02 +02:00
|
|
|
* @param criteria selection criteria for loading.
|
|
|
|
|
*/
|
2014-06-23 14:33:35 +02:00
|
|
|
def loadAsync(persistenceId: String, criteria: SnapshotSelectionCriteria): Future[Option[SelectedSnapshot]]
|
2013-10-08 11:46:02 +02:00
|
|
|
|
|
|
|
|
/**
|
2013-11-07 10:45:02 +01:00
|
|
|
* Plugin API: asynchronously saves a snapshot.
|
2013-10-08 11:46:02 +02:00
|
|
|
*
|
|
|
|
|
* @param metadata snapshot metadata.
|
|
|
|
|
* @param snapshot snapshot.
|
|
|
|
|
*/
|
|
|
|
|
def saveAsync(metadata: SnapshotMetadata, snapshot: Any): Future[Unit]
|
|
|
|
|
|
|
|
|
|
/**
|
2013-11-07 10:45:02 +01:00
|
|
|
* Plugin API: deletes the snapshot identified by `metadata`.
|
2013-10-08 11:46:02 +02:00
|
|
|
*
|
|
|
|
|
* @param metadata snapshot metadata.
|
|
|
|
|
*/
|
2013-11-12 09:02:02 +01:00
|
|
|
|
2015-06-03 15:56:00 +02:00
|
|
|
def deleteAsync(metadata: SnapshotMetadata): Future[Unit]
|
2013-11-12 09:02:02 +01:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Plugin API: deletes all snapshots matching `criteria`.
|
|
|
|
|
*
|
2014-12-08 11:02:14 +01:00
|
|
|
* @param persistenceId id of the persistent actor.
|
2013-11-12 09:02:02 +01:00
|
|
|
* @param criteria selection criteria for deleting.
|
|
|
|
|
*/
|
2015-06-03 15:56:00 +02:00
|
|
|
def deleteAsync(persistenceId: String, criteria: SnapshotSelectionCriteria): Future[Unit]
|
2015-06-17 01:23:18 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Plugin API
|
|
|
|
|
* Allows plugin implementers to use `f pipeTo self` and
|
|
|
|
|
* handle additional messages for implementing advanced features
|
|
|
|
|
*/
|
|
|
|
|
def receivePluginInternal: Actor.Receive = Actor.emptyBehavior
|
2013-10-08 11:46:02 +02:00
|
|
|
//#snapshot-store-plugin-api
|
|
|
|
|
}
|