akka.persistence.SnapshotOffer Scala Examples

The following examples show how to use akka.persistence.SnapshotOffer. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
package no.nextgentel.oss.akkatools.aggregate.aggregateTest_usingAggregateStateBase

import java.util.UUID

import akka.actor.{ActorPath, ActorSystem, Props}
import akka.persistence.{DeleteMessagesFailure, DeleteMessagesSuccess, SaveSnapshotFailure, SaveSnapshotSuccess, SnapshotMetadata, SnapshotOffer}
import akka.testkit.{TestKit, TestProbe}
import com.typesafe.config.ConfigFactory
import no.nextgentel.oss.akkatools.aggregate._
import no.nextgentel.oss.akkatools.testing.AggregateTesting
import org.scalatest.{BeforeAndAfter, BeforeAndAfterAll, FunSuiteLike, Matchers}
import org.slf4j.LoggerFactory



  override def onSnapshotOffer(offer: SnapshotOffer): Unit = {
    state = offer.snapshot.asInstanceOf[StringState]
  }

  override def acceptSnapshotRequest(req: SaveSnapshotOfCurrentState): Boolean = {
    if (state == StringState("WAT")) {
      state = StringState("SAVED")
      true
    }
    else {
      state = StringState("WAT") //So it works second time
      false
    }
  }

  override def onSnapshotSuccess(success: SaveSnapshotSuccess): Unit = {
    state = StringState("SUCCESS_SNAP")
  }

  override def onSnapshotFailure(failure: SaveSnapshotFailure): Unit = {
    state = StringState("FAIL_SNAP")
  }

  override def onDeleteMessagesSuccess(success: DeleteMessagesSuccess): Unit = {
    state = StringState("SUCCESS_MSG")
  }

  override def onDeleteMessagesFailure(failure: DeleteMessagesFailure): Unit = {
    state = StringState("FAIL_MSG")
  }

  // Used as prefix/base when constructing the persistenceId to use - the unique ID is extracted runtime from actorPath which is construced by Sharding-coordinator
  override def persistenceIdBase(): String = "/x/"
}

case class StringEv(data: String)

case class StringState(data:String) extends AggregateStateBase[StringEv, StringState] {
  override def transitionState(event: StringEv): StateTransition[StringEv, StringState] =
    StateTransition(StringState(event.data))
} 
Example 2
Source File: ReliableFSM.scala    From reliable-http-client   with Apache License 2.0 5 votes vote down vote up
package rhttpc.akkapersistence

import akka.actor.FSM._
import akka.actor._
import akka.persistence.{AkkaPersistentSnapshotter, SnapshotOffer}
import rhttpc.akkapersistence.impl._
import rhttpc.client.subscription.SubscriptionOnResponse

trait ReliableFSM[S, D] extends AkkaPersistentSnapshotter with AbstractReliableFSM[S, D]

trait AbstractReliableFSM[S, D]
  extends PersistentFSM[S, D]
  with SubscriptionsHolder[S, D] { self: AbstractSnapshotter =>

  override def receive: Receive =
    handleNotifyAboutRecoveryCompleted orElse
      handleSubscriptionMessages orElse
      handleSnapshotEvents orElse
      super.receive
}

trait PersistentFSM[S, D]
  extends PersistentActorWithNotifications
  with FSM[S, D]
  with FSMAfterAllListenerHolder[S, D]
  with FSMStateTransitionRegistrar[S, D]
  with NotifierAboutRecoveryCompleted { self: AbstractSnapshotter with StateTransitionHandler[S, D]  =>

  private var ownLastSequenceNr = 0L
  
  override protected def incOwnLastSequenceNr(): Long = {
    ownLastSequenceNr += 1
    ownLastSequenceNr
  }

  override def receiveRecover: Receive =
    handleSnapshotOffer orElse
      handleRecoveryCompleted

  private val handleSnapshotOffer: Receive = {
    case SnapshotOffer(metadata, snapshot) =>
      log.info(s"Recovering: $metadata from snapshot: $snapshot")
      ownLastSequenceNr = metadata.sequenceNr
      val casted = snapshot.asInstanceOf[FSMState[S, D]]
      onSubscriptionsOffered(casted.subscriptions)
      startWith(casted.state, casted.data)
  }

  override protected def onFinishedJobAfterTransition(afterAllData: FinishedJobAfterTransitionData[S, D]): Unit = {
    saveSnapshotNotifying(FSMState(afterAllData), afterAllData.sequenceNumber, afterAllData.afterAllListener)
  }

  onTermination {
    case StopEvent(Normal, _, _) =>
      deleteSnapshotsLogging()
    case StopEvent(Failure(_), _, _) =>
      deleteSnapshotsLogging()
  }

}

case class FSMState[S, D](state: S, data: D, subscriptions: Set[SubscriptionOnResponse])

object FSMState {
  def apply[S, D](data: FinishedJobAfterTransitionData[S, D]): FSMState[S, D] = FSMState(data.state, data.data, data.subscriptions)
}

case object StateSaved 
Example 3
Source File: HttpRequestRecorder.scala    From rokku   with Apache License 2.0 5 votes vote down vote up
package com.ing.wbaa.rokku.proxy.persistence

import akka.http.scaladsl.model.{ HttpRequest, RemoteAddress }
import akka.persistence.{ PersistentActor, RecoveryCompleted, SaveSnapshotFailure, SaveSnapshotSuccess, SnapshotOffer }
import com.ing.wbaa.rokku.proxy.data.User
import com.ing.wbaa.rokku.proxy.persistence.HttpRequestRecorder.{ ExecutedRequestCmd, LatestRequests, LatestRequestsResult, Shutdown }
import com.typesafe.config.ConfigFactory
import com.typesafe.scalalogging.LazyLogging

sealed trait Evt
case class ExecutedRequestEvt(httpRequest: HttpRequest, userSTS: User, clientIPAddress: RemoteAddress) extends Evt

object HttpRequestRecorder {
  case class ExecutedRequestCmd(httpRequest: HttpRequest, userSTS: User, clientIPAddress: RemoteAddress)
  case class LatestRequests(amount: Int)
  case class LatestRequestsResult(requests: List[ExecutedRequestEvt])
  case object Shutdown
}

case class CurrentRequestsState(requests: List[ExecutedRequestEvt] = Nil) {
  def add(e: ExecutedRequestEvt): CurrentRequestsState = {
    if (size > 200) { copy(requests.reverse.drop(100)) }
    copy(e :: requests)
  }
  def getRequests(n: Int = 100): List[ExecutedRequestEvt] = this.requests.reverse.take(n)
  def size: Int = requests.size
}

class HttpRequestRecorder extends PersistentActor with LazyLogging {
  var state: CurrentRequestsState = CurrentRequestsState()
  val snapShotInterval = ConfigFactory.load().getInt("rokku.requestPersistence.snapshotInterval")

  private def updateState(e: ExecutedRequestEvt) = state = state.add(e)

  override def persistenceId: String = ConfigFactory.load().getString("rokku.requestPersistence.persistenceId")

  override def receiveRecover: Receive = {
    case e: ExecutedRequestEvt => {
      logger.debug("No snapshot, replying event sequence {}", lastSequenceNr)
      updateState(e)
    }
    case SnapshotOffer(metadata, snapshot: CurrentRequestsState) => {
      logger.debug("Received snapshot offer, timestamp: {} for persistenceId: {} ", metadata.timestamp, metadata.persistenceId)
      state = snapshot
    }
    case RecoveryCompleted => logger.debug("Actor State recovery completed!")
  }

  override def receiveCommand: Receive = {
    case SaveSnapshotSuccess(metadata)  => logger.debug("Snapshot saved successfully, seq: {}", metadata.sequenceNr)

    case SaveSnapshotFailure(_, reason) => logger.error("Failed to save snapshot, reason: {}", reason.getMessage)

    case rc: ExecutedRequestCmd =>
      persist(ExecutedRequestEvt(rc.httpRequest, rc.userSTS, rc.clientIPAddress)) { e =>
        logger.debug("Received event for event sourcing {} from user: {}", e.httpRequest.uri, e.userSTS.userName)
        updateState(e)
        if (lastSequenceNr % snapShotInterval == 0 && lastSequenceNr != 0)
          saveSnapshot(state)
      }

    case get: LatestRequests => sender() ! LatestRequestsResult(state.getRequests(get.amount))

    case Shutdown            => context.stop(self)

    case _                   => logger.debug(s"{} Got unsupported message type", HttpRequestRecorder.getClass.getName)
  }

} 
Example 4
Source File: PersistenceExample.scala    From typed-actors   with Apache License 2.0 5 votes vote down vote up
package org.example

import akka.actor.{ ActorLogging, ActorSystem }
import akka.persistence.{ SnapshotOffer, PersistentActor }
import de.knutwalker.akka.typed._

import scala.concurrent.duration._

object PersistenceExample extends App {

  case class Ping(replyTo: ActorRef[Pong])
  case class Pong(replyTo: ActorRef[Ping])

  case class Evt(data: String)

  case class ExampleState(events: List[String] = Nil) {
    def updated(evt: Evt): ExampleState = copy(evt.data :: events)
    def size: Int = events.length
    override def toString: String = events.reverse.toString
  }

  class TypedPersistentPingActor extends TypedActor with PersistentActor with ActorLogging {
    type Message = Ping

    def persistenceId: String = "typed-persistent-ping-id"

    var state = ExampleState()

    def updateState(event: Evt): Unit =
      state = state.updated(event)

    def numEvents =
      state.size

    val receiveRecover: Receive = {
      case evt: Evt                                 => updateState(evt)
      case SnapshotOffer(_, snapshot: ExampleState) => state = snapshot
    }

    val typedReceive: TypedReceive = {
      case Ping(replyTo) ⇒
        persist(Evt(s"$numEvents"))(updateState)
        persist(Evt(s"${numEvents + 1}")) { event =>
          updateState(event)
          replyTo ! Pong(typedSelf)
        }
    }

    val receiveCommand: Receive =
      untypedFromTyped(typedReceive).orElse {
        case "snap"  => saveSnapshot(state)
        case "print" => println(state)
      }

    override def receive: Receive =
      receiveCommand

    override def postStop(): Unit = {
      log.info(s"state = $state")
      super.postStop()
    }
  }

  class TypedPongActor extends TypedActor.Of[Pong] with ActorLogging {
    private[this] var count = 0
    val typedReceive: TypedReceive = {
      case Pong(replyTo) ⇒
        count += 1
        replyTo ! Ping(typedSelf)
    }

    override def postStop(): Unit = {
      log.info(s"pings: $count")
      super.postStop()
    }

    override def preStart(): Unit = {
      import context.dispatcher
      super.preStart()
      context.system.scheduler.scheduleOnce(600.millis)(Shutdown(system))
      ()
    }
  }



  implicit val system = ActorSystem()
  val ping = ActorOf(PropsFor[TypedPersistentPingActor], "ping")
  val pong = ActorOf(PropsFor[TypedPongActor], "pong")

  ping ! Ping(pong)
} 
Example 5
Source File: InventoryActor.scala    From Learn-Scala-Programming   with MIT License 5 votes vote down vote up
package ch14

import akka.actor.{Actor, ActorLogging, Props}
import akka.persistence.{PersistentActor, RecoveryCompleted, SnapshotOffer}
import ch14.Commands.{GetArticle, GetInventory}

object InventoryActor {
  def props: Props = Props[InventoryActor]
  val persistenceId = "Inventory"
}

class InventoryActor extends PersistentActor with Actor with ActorLogging {

  override def persistenceId: String = InventoryActor.persistenceId

  private var inventory: Inventory = Inventory(Map.empty)

  override def receiveRecover: Receive = {
    case event: Event                          => inventory = inventory.update(event)
    case SnapshotOffer(_, snapshot: Inventory) => inventory = snapshot
    case RecoveryCompleted                     => saveSnapshot(inventory)
  }

  override def receiveCommand: Receive = {
    case GetInventory =>
      sender() ! inventory

    case GetArticle(name) =>
      sender() ! Inventory(inventory.state.filter(_._1 == name))

    case cmd: Command =>
      inventory.canUpdate(cmd) match {
        case None =>
          sender() ! None
        case Some(event) =>
          persistAsync(event) { ev =>
            inventory = inventory.update(ev)
            sender() ! Some(ev)
          }
      }

  }
} 
Example 6
Source File: SamplePersistenceActor.scala    From Akka-Cookbook   with MIT License 5 votes vote down vote up
package com.packt.chapter6

import akka.persistence.{PersistentActor, SnapshotOffer}

class SamplePersistenceActor extends PersistentActor {
  override val persistenceId = "unique-id-1"

  var state = ActiveUsers()
  def updateState(event: Event) = state = state.update(event)

  val receiveRecover: Receive = {
    case evt: Event => updateState(evt)
    case SnapshotOffer(_, snapshot: ActiveUsers) => state = snapshot
  }

  val receiveCommand: Receive = {
    case UserUpdate(userId, Add) => persist(AddUserEvent(userId))(updateState)
    case UserUpdate(userId, Remove) => persist(RemoveUserEvent(userId))(updateState)
    case "snap"  => saveSnapshot(state)
    case "print" => println(state)
    case ShutdownPersistentActor => context.stop(self)
  }

  override def postStop() = println(s"Stopping [${self.path}]")
} 
Example 7
Source File: FriendActor.scala    From Akka-Cookbook   with MIT License 5 votes vote down vote up
package com.packt.chapter6

import akka.actor.{ActorLogging, Props}
import akka.persistence.{PersistentActor, Recovery, RecoveryCompleted, SnapshotOffer}

object FriendActor {
  def props(friendId: String, recoveryStrategy: Recovery) = Props(new FriendActor(friendId, recoveryStrategy))
}

class FriendActor(friendId: String, r: Recovery) extends PersistentActor with ActorLogging {
  override val persistenceId = friendId
  override val recovery = r

  var state = FriendState()
  def updateState(event: FriendEvent) = state = state.update(event)

  val receiveRecover: Receive = {
    case evt: FriendEvent =>
      log.info(s"Replaying event: $evt")
      updateState(evt)
    case SnapshotOffer(_, recoveredState : FriendState) =>
      log.info(s"Snapshot offered: $recoveredState")
      state = recoveredState
    case RecoveryCompleted => log.info(s"Recovery completed. Current state: $state")
  }

  val receiveCommand: Receive = {
    case AddFriend(friend) => persist(FriendAdded(friend))(updateState)
    case RemoveFriend(friend) => persist(FriendRemoved(friend))(updateState)
    case "snap" => saveSnapshot(state)
    case "print" => log.info(s"Current state: $state")
  }
} 
Example 8
Source File: BlogEntity.scala    From akka-blog-example   with Apache License 2.0 5 votes vote down vote up
package com.spr.blog

import akka.actor.Props
import akka.pattern.pipe
import akka.persistence.{PersistentActor, SnapshotOffer}

import scala.concurrent.{Future, Promise}


class BlogEntity extends PersistentActor {

  import BlogEntity._
  import context._

  private var state = BlogState()

  // in order to really match the Lagom example properly, we'd create an actor for every blog post, though that
  // sounds a bit overkill to me. then our persistenceId would be something like s"blog-$id".
  override def persistenceId: String = "blog"

  override def receiveCommand: Receive = {
    case GetPost(id) =>
      sender() ! state(id)
    case AddPost(content) =>
      handleEvent(PostAdded(PostId(), content)) pipeTo sender()
      ()
    case UpdatePost(id, content) =>
      state(id) match {
        case response @ Left(_) => sender() ! response
        case Right(_) =>
          handleEvent(PostUpdated(id, content)) pipeTo sender()
          ()
      }
  }

  private def handleEvent[E <: BlogEvent](e: => E): Future[E] = {
    val p = Promise[E]
    persist(e) { event =>
      p.success(event)
      state += event
      system.eventStream.publish(event)
      if (lastSequenceNr != 0 && lastSequenceNr % 1000 == 0) saveSnapshot(state)
    }
    p.future
  }

  override def receiveRecover: Receive = {
    case event: BlogEvent =>
      state += event
    case SnapshotOffer(_, snapshot: BlogState) =>
      state = snapshot
  }

}

object BlogEntity {
  def props = Props(new BlogEntity)

  sealed trait BlogCommand

  final case class GetPost(id: PostId) extends BlogCommand

  final case class AddPost(content: PostContent) extends BlogCommand

  final case class UpdatePost(id: PostId, content: PostContent) extends BlogCommand

  sealed trait BlogEvent {
    val id: PostId
    val content: PostContent
  }

  final case class PostAdded(id: PostId, content: PostContent) extends BlogEvent

  final case class PostUpdated(id: PostId, content: PostContent) extends BlogEvent

  final case class PostNotFound(id: PostId) extends RuntimeException(s"Blog post not found with id $id")

  type MaybePost[+A] = Either[PostNotFound, A]

  final case class BlogState(posts: Map[PostId, PostContent]) {
    def apply(id: PostId): MaybePost[PostContent] = posts.get(id).toRight(PostNotFound(id))

    def +(event: BlogEvent): BlogState = BlogState(posts.updated(event.id, event.content))
  }

  object BlogState {
    def apply(): BlogState = BlogState(Map.empty)
  }

} 
Example 9
Source File: WFActor.scala    From Scala-Reactive-Programming   with MIT License 5 votes vote down vote up
package com.packt.publishing.cassandra.actor

import akka.actor.{ActorLogging, Props}
import akka.persistence.{PersistentActor, Recovery, RecoveryCompleted, SnapshotOffer}
import com.packt.publishing.cassandra.commands.{AddWF, PrintWF, RemoveWF, SnapshotWF}
import com.packt.publishing.cassandra.events.{WFAdded, WFEvent, WFRemoved}
import com.packt.publishing.cassandra.state.WFState

object WFActor {
  def props(id: String, recovery: Recovery) = Props(new WFActor(id, recovery))
}

class WFActor(id: String, rec: Recovery) extends PersistentActor with ActorLogging {

  override val persistenceId = id
  override val recovery = rec

  var state = WFState()

  def updateState(event: WFEvent) = state = state.update(event)

   val receiveRecover: Receive = {
    case evt: WFEvent =>  log.info(s"Replaying event: $evt")
                              updateState(evt)
    case SnapshotOffer(_, recoveredState : WFState) =>
                              log.info(s"Snapshot offered: $recoveredState")
                              state = recoveredState
    case RecoveryCompleted => log.info(s"Recovery completed. Current state: $state")
   }

   val receiveCommand: Receive = {
      case AddWF(wf) => persist(WFAdded(wf))(updateState)
      case RemoveWF(wf) => persist(WFRemoved(wf))(updateState)
      case SnapshotWF =>  saveSnapshot(state)
      case PrintWF => log.info(s"Current state: $state")
   }
}