2013-10-09 13:11:53 +02:00
|
|
|
/**
|
2014-02-02 19:05:45 -06:00
|
|
|
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
2013-10-09 13:11:53 +02:00
|
|
|
*/
|
|
|
|
|
|
2013-09-14 14:19:18 +02:00
|
|
|
package docs.persistence
|
|
|
|
|
|
2014-08-29 11:17:33 +02:00
|
|
|
import akka.actor.{ Actor, ActorSystem, Props }
|
2014-06-24 16:57:33 +02:00
|
|
|
import akka.persistence._
|
2014-07-08 18:30:15 +02:00
|
|
|
import com.typesafe.config.ConfigFactory
|
2014-06-24 16:57:33 +02:00
|
|
|
|
2013-12-06 12:48:44 +01:00
|
|
|
import scala.concurrent.duration._
|
|
|
|
|
import scala.language.postfixOps
|
2013-09-14 14:19:18 +02:00
|
|
|
trait PersistenceDocSpec {
|
2014-01-17 06:58:25 +01:00
|
|
|
val config =
|
|
|
|
|
"""
|
|
|
|
|
//#auto-update-interval
|
|
|
|
|
akka.persistence.view.auto-update-interval = 5s
|
|
|
|
|
//#auto-update-interval
|
|
|
|
|
//#auto-update
|
|
|
|
|
akka.persistence.view.auto-update = off
|
|
|
|
|
//#auto-update
|
|
|
|
|
"""
|
|
|
|
|
|
2014-06-05 14:07:17 +02:00
|
|
|
trait SomeOtherMessage
|
|
|
|
|
|
2014-06-03 16:40:44 +02:00
|
|
|
implicit val system: ActorSystem
|
2013-09-14 14:19:18 +02:00
|
|
|
|
|
|
|
|
import system._
|
|
|
|
|
|
|
|
|
|
new AnyRef {
|
2014-12-08 11:02:14 +01:00
|
|
|
trait MyPersistentActor1 extends PersistentActor {
|
2013-09-14 14:19:18 +02:00
|
|
|
//#recover-on-start-disabled
|
2013-09-15 09:04:05 +02:00
|
|
|
override def preStart() = ()
|
2013-09-14 14:19:18 +02:00
|
|
|
//#recover-on-start-disabled
|
|
|
|
|
//#recover-on-restart-disabled
|
2013-09-15 09:04:05 +02:00
|
|
|
override def preRestart(reason: Throwable, message: Option[Any]) = ()
|
2013-09-14 14:19:18 +02:00
|
|
|
//#recover-on-restart-disabled
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
trait MyPersistentActor2 extends PersistentActor {
|
2013-09-14 14:19:18 +02:00
|
|
|
//#recover-on-start-custom
|
2013-09-15 09:04:05 +02:00
|
|
|
override def preStart() {
|
2013-09-14 14:19:18 +02:00
|
|
|
self ! Recover(toSequenceNr = 457L)
|
|
|
|
|
}
|
|
|
|
|
//#recover-on-start-custom
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
val persistentActor = system.deadLetters
|
|
|
|
|
//#recover-explicit
|
|
|
|
|
persistentActor ! Recover()
|
|
|
|
|
//#recover-explicit
|
2014-04-09 11:40:31 +02:00
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
class MyPersistentActor4 extends PersistentActor {
|
2014-06-26 13:56:01 +02:00
|
|
|
override def persistenceId = "my-stable-persistence-id"
|
|
|
|
|
|
2014-03-24 15:35:54 +01:00
|
|
|
//#recovery-completed
|
2014-04-09 11:40:31 +02:00
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
override def receiveRecover: Receive = {
|
|
|
|
|
case RecoveryCompleted =>
|
|
|
|
|
// perform init after recovery, before any other messages
|
|
|
|
|
//...
|
2014-07-08 18:30:15 +02:00
|
|
|
case evt => //...
|
2014-06-25 12:51:21 +02:00
|
|
|
}
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
override def receiveCommand: Receive = {
|
2014-07-08 18:30:15 +02:00
|
|
|
case msg => //...
|
2014-03-24 15:35:54 +01:00
|
|
|
}
|
|
|
|
|
//#recovery-completed
|
|
|
|
|
}
|
2013-09-14 14:19:18 +02:00
|
|
|
}
|
|
|
|
|
|
2014-11-21 16:59:21 +01:00
|
|
|
new AnyRef {
|
2014-12-08 11:02:14 +01:00
|
|
|
trait MyPersistentActor1 extends PersistentActor {
|
|
|
|
|
//#recover-fully-disabled
|
|
|
|
|
override def preStart() = self ! Recover(toSequenceNr = 0L)
|
|
|
|
|
//#recover-fully-disabled
|
|
|
|
|
}
|
2014-11-21 16:59:21 +01:00
|
|
|
}
|
|
|
|
|
|
2013-09-14 14:19:18 +02:00
|
|
|
new AnyRef {
|
2014-12-08 11:02:14 +01:00
|
|
|
trait PersistentActorMethods {
|
2014-06-23 14:33:35 +02:00
|
|
|
//#persistence-id
|
|
|
|
|
def persistenceId: String
|
|
|
|
|
//#persistence-id
|
2013-09-14 14:19:18 +02:00
|
|
|
//#recovery-status
|
|
|
|
|
def recoveryRunning: Boolean
|
|
|
|
|
def recoveryFinished: Boolean
|
|
|
|
|
//#recovery-status
|
|
|
|
|
}
|
2014-12-08 11:02:14 +01:00
|
|
|
class MyPersistentActor1 extends PersistentActor with PersistentActorMethods {
|
2014-06-23 14:33:35 +02:00
|
|
|
//#persistence-id-override
|
|
|
|
|
override def persistenceId = "my-stable-persistence-id"
|
|
|
|
|
//#persistence-id-override
|
2014-12-08 11:02:14 +01:00
|
|
|
|
|
|
|
|
override def receiveRecover: Receive = {
|
|
|
|
|
case _ =>
|
|
|
|
|
}
|
|
|
|
|
override def receiveCommand: Receive = {
|
2013-12-03 16:34:26 +01:00
|
|
|
case _ =>
|
2013-09-14 14:19:18 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-03 15:10:56 +02:00
|
|
|
new AnyRef {
|
|
|
|
|
//#at-least-once-example
|
2014-08-29 11:17:33 +02:00
|
|
|
import akka.actor.{ Actor, ActorPath }
|
2014-06-03 15:10:56 +02:00
|
|
|
import akka.persistence.AtLeastOnceDelivery
|
|
|
|
|
|
|
|
|
|
case class Msg(deliveryId: Long, s: String)
|
|
|
|
|
case class Confirm(deliveryId: Long)
|
|
|
|
|
|
|
|
|
|
sealed trait Evt
|
|
|
|
|
case class MsgSent(s: String) extends Evt
|
|
|
|
|
case class MsgConfirmed(deliveryId: Long) extends Evt
|
|
|
|
|
|
|
|
|
|
class MyPersistentActor(destination: ActorPath)
|
|
|
|
|
extends PersistentActor with AtLeastOnceDelivery {
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
override def persistenceId: String = "persistence-id"
|
|
|
|
|
|
|
|
|
|
override def receiveCommand: Receive = {
|
2014-06-03 15:10:56 +02:00
|
|
|
case s: String => persist(MsgSent(s))(updateState)
|
|
|
|
|
case Confirm(deliveryId) => persist(MsgConfirmed(deliveryId))(updateState)
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
override def receiveRecover: Receive = {
|
2014-06-03 15:10:56 +02:00
|
|
|
case evt: Evt => updateState(evt)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def updateState(evt: Evt): Unit = evt match {
|
|
|
|
|
case MsgSent(s) =>
|
|
|
|
|
deliver(destination, deliveryId => Msg(deliveryId, s))
|
|
|
|
|
|
|
|
|
|
case MsgConfirmed(deliveryId) => confirmDelivery(deliveryId)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MyDestination extends Actor {
|
|
|
|
|
def receive = {
|
|
|
|
|
case Msg(deliveryId, s) =>
|
|
|
|
|
// ...
|
|
|
|
|
sender() ! Confirm(deliveryId)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//#at-least-once-example
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-14 14:19:18 +02:00
|
|
|
new AnyRef {
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
class MyPersistentActor extends PersistentActor {
|
|
|
|
|
override def persistenceId = "my-stable-persistence-id"
|
2013-09-26 09:14:43 +02:00
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
//#save-snapshot
|
2013-09-26 09:14:43 +02:00
|
|
|
var state: Any = _
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
override def receiveCommand: Receive = {
|
2013-12-03 16:34:26 +01:00
|
|
|
case "snap" => saveSnapshot(state)
|
|
|
|
|
case SaveSnapshotSuccess(metadata) => // ...
|
|
|
|
|
case SaveSnapshotFailure(metadata, reason) => // ...
|
2013-09-26 09:14:43 +02:00
|
|
|
}
|
2014-12-08 11:02:14 +01:00
|
|
|
//#save-snapshot
|
|
|
|
|
|
|
|
|
|
override def receiveRecover: Receive = ???
|
2013-09-26 09:14:43 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
new AnyRef {
|
2014-12-08 11:02:14 +01:00
|
|
|
class MyPersistentActor extends PersistentActor {
|
|
|
|
|
override def persistenceId = "my-stable-persistence-id"
|
|
|
|
|
|
|
|
|
|
//#snapshot-offer
|
2013-09-26 09:14:43 +02:00
|
|
|
var state: Any = _
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
override def receiveRecover: Receive = {
|
2013-12-03 16:34:26 +01:00
|
|
|
case SnapshotOffer(metadata, offeredSnapshot) => state = offeredSnapshot
|
2014-12-08 11:02:14 +01:00
|
|
|
case RecoveryCompleted =>
|
|
|
|
|
case event => // ...
|
2013-09-26 09:14:43 +02:00
|
|
|
}
|
2014-12-08 11:02:14 +01:00
|
|
|
//#snapshot-offer
|
|
|
|
|
|
|
|
|
|
override def receiveCommand: Receive = ???
|
2013-09-26 09:14:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
import akka.actor.Props
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
val persistentActor = system.actorOf(Props[MyPersistentActor])
|
2013-09-26 09:14:43 +02:00
|
|
|
|
|
|
|
|
//#snapshot-criteria
|
2014-12-08 11:02:14 +01:00
|
|
|
persistentActor ! Recover(fromSnapshot = SnapshotSelectionCriteria(
|
2013-09-26 09:14:43 +02:00
|
|
|
maxSequenceNr = 457L,
|
|
|
|
|
maxTimestamp = System.currentTimeMillis))
|
|
|
|
|
//#snapshot-criteria
|
|
|
|
|
}
|
2013-10-27 08:01:14 +01:00
|
|
|
|
2014-05-21 01:35:21 +02:00
|
|
|
new AnyRef {
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
val persistentActor = system.actorOf(Props[MyPersistentActor]())
|
2014-05-21 01:35:21 +02:00
|
|
|
|
|
|
|
|
//#persist-async
|
|
|
|
|
class MyPersistentActor extends PersistentActor {
|
|
|
|
|
|
2014-06-26 13:56:01 +02:00
|
|
|
override def persistenceId = "my-stable-persistence-id"
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
override def receiveRecover: Receive = {
|
2014-05-21 01:35:21 +02:00
|
|
|
case _ => // handle recovery here
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
override def receiveCommand: Receive = {
|
2014-05-21 01:35:21 +02:00
|
|
|
case c: String => {
|
|
|
|
|
sender() ! c
|
|
|
|
|
persistAsync(s"evt-$c-1") { e => sender() ! e }
|
|
|
|
|
persistAsync(s"evt-$c-2") { e => sender() ! e }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// usage
|
2014-12-08 11:02:14 +01:00
|
|
|
persistentActor ! "a"
|
|
|
|
|
persistentActor ! "b"
|
2014-05-21 01:35:21 +02:00
|
|
|
|
|
|
|
|
// possible order of received messages:
|
|
|
|
|
// a
|
|
|
|
|
// b
|
|
|
|
|
// evt-a-1
|
|
|
|
|
// evt-a-2
|
|
|
|
|
// evt-b-1
|
|
|
|
|
// evt-b-2
|
|
|
|
|
|
|
|
|
|
//#persist-async
|
|
|
|
|
}
|
2014-06-03 16:40:44 +02:00
|
|
|
new AnyRef {
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
val persistentActor = system.actorOf(Props[MyPersistentActor]())
|
2014-06-03 16:40:44 +02:00
|
|
|
|
|
|
|
|
//#defer
|
|
|
|
|
class MyPersistentActor extends PersistentActor {
|
|
|
|
|
|
2014-06-26 13:56:01 +02:00
|
|
|
override def persistenceId = "my-stable-persistence-id"
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
override def receiveRecover: Receive = {
|
2014-06-03 16:40:44 +02:00
|
|
|
case _ => // handle recovery here
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
override def receiveCommand: Receive = {
|
2014-06-03 16:40:44 +02:00
|
|
|
case c: String => {
|
|
|
|
|
sender() ! c
|
|
|
|
|
persistAsync(s"evt-$c-1") { e => sender() ! e }
|
|
|
|
|
persistAsync(s"evt-$c-2") { e => sender() ! e }
|
|
|
|
|
defer(s"evt-$c-3") { e => sender() ! e }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//#defer
|
|
|
|
|
|
|
|
|
|
//#defer-caller
|
2014-12-08 11:02:14 +01:00
|
|
|
persistentActor ! "a"
|
|
|
|
|
persistentActor ! "b"
|
2014-06-03 16:40:44 +02:00
|
|
|
|
|
|
|
|
// order of received messages:
|
|
|
|
|
// a
|
|
|
|
|
// b
|
|
|
|
|
// evt-a-1
|
|
|
|
|
// evt-a-2
|
|
|
|
|
// evt-a-3
|
|
|
|
|
// evt-b-1
|
|
|
|
|
// evt-b-2
|
|
|
|
|
// evt-b-3
|
|
|
|
|
|
|
|
|
|
//#defer-caller
|
|
|
|
|
}
|
2014-01-17 06:58:25 +01:00
|
|
|
new AnyRef {
|
|
|
|
|
import akka.actor.Props
|
|
|
|
|
|
|
|
|
|
//#view
|
2014-06-24 16:57:33 +02:00
|
|
|
class MyView extends PersistentView {
|
2014-06-23 14:33:35 +02:00
|
|
|
override def persistenceId: String = "some-persistence-id"
|
2014-06-24 16:57:33 +02:00
|
|
|
override def viewId: String = "some-persistence-id-view"
|
2014-01-17 06:58:25 +01:00
|
|
|
|
2014-12-08 11:02:14 +01:00
|
|
|
def receive: Receive = {
|
2014-06-24 16:57:33 +02:00
|
|
|
case payload if isPersistent =>
|
|
|
|
|
// handle message from journal...
|
|
|
|
|
case payload =>
|
|
|
|
|
// handle message from user-land...
|
2014-01-17 06:58:25 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//#view
|
|
|
|
|
|
|
|
|
|
//#view-update
|
|
|
|
|
val view = system.actorOf(Props[MyView])
|
|
|
|
|
view ! Update(await = true)
|
|
|
|
|
//#view-update
|
|
|
|
|
}
|
2014-06-03 16:40:44 +02:00
|
|
|
|
2013-09-14 14:19:18 +02:00
|
|
|
}
|