akka.persistence.PersistentActor Scala Examples

The following examples show how to use akka.persistence.PersistentActor. 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
Source File: TestActor.scala    From akka-persistence-couchbase   with Apache License 2.0 5 votes vote down vote up
package akka.persistence.couchbase

import akka.actor.{ActorLogging, ActorRef, Props}
import akka.persistence.{DeleteMessagesSuccess, PersistentActor, RecoveryCompleted}
import akka.persistence.couchbase.TestActor.{GetLastRecoveredEvent, SaveSnapshot}
import akka.persistence.journal.Tagged

import scala.collection.immutable

object TestActor {
  def props(persistenceId: String): Props = props(persistenceId, "couchbase-journal.write")

  def props(persistenceId: String, journalId: String): Props = Props(new TestActor(persistenceId, journalId))

  final case class PersistAll(events: immutable.Seq[String])
  final case class PersistAllAsync(events: immutable.Seq[String])
  final case class DeleteTo(seqNr: Long)
  final case object SaveSnapshot
  final case object GetLastRecoveredEvent
  case object Stop
}

class TestActor(override val persistenceId: String, override val journalPluginId: String)
    extends PersistentActor
    with ActorLogging {
  var lastDelete: ActorRef = _
  var lastRecoveredEvent: String = _

  val receiveRecover: Receive = {
    case evt: String =>
      lastRecoveredEvent = evt

    case RecoveryCompleted =>
      log.debug("Recovery completed, lastRecoveredEvent: {}", lastRecoveredEvent)
  }

  val receiveCommand: Receive = {
    case cmd: String =>
      persist(cmd) { evt =>
        sender() ! evt + "-done"
      }
    case cmd: Tagged =>
      persist(cmd) { evt =>
        val msg = s"${evt.payload}-done"
        sender() ! msg
      }

    case TestActor.PersistAll(events) =>
      val size = events.size
      val handler = {
        var count = 0
        _: String => {
          count += 1
          if (count == size)
            sender() ! "PersistAll-done"
        }
      }
      persistAll(events)(handler)

    case TestActor.PersistAllAsync(events) =>
      val size = events.size
      val handler = {
        var count = 0
        evt: String => {
          count += 1
          if (count == size)
            sender() ! "PersistAllAsync-done"
        }
      }
      persistAllAsync(events)(handler)
      sender() ! "PersistAllAsync-triggered"

    case TestActor.DeleteTo(seqNr) =>
      lastDelete = sender()
      deleteMessages(seqNr)

    case d: DeleteMessagesSuccess =>
      lastDelete ! d

    case SaveSnapshot =>
      saveSnapshot("dumb-snapshot-body")
      sender() ! snapshotSequenceNr

    case GetLastRecoveredEvent =>
      sender() ! lastRecoveredEvent

    case TestActor.Stop =>
      context.stop(self)
  }
} 
Example 2
Source File: CurrentPersistenceIdsQuerySourceTest.scala    From apache-spark-test   with Apache License 2.0 5 votes vote down vote up
package com.github.dnvriend.spark.sstreaming

import java.util.UUID
import java.util.concurrent.atomic.AtomicLong

import akka.actor.{ ActorRef, Props }
import akka.persistence.PersistentActor
import akka.testkit.TestProbe
import com.github.dnvriend.TestSpec
import com.github.dnvriend.spark.datasources.SparkImplicits._
import com.github.dnvriend.spark.datasources.person.Person
import org.apache.spark.sql.streaming.{ OutputMode, ProcessingTime }
import org.scalatest.Ignore

import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
import scala.language.implicitConversions

object PersonActor {
  final case class BlogPost(id: Long, text: String)
}
class PersonActor(val persistenceId: String, schedule: Boolean)(implicit ec: ExecutionContext) extends PersistentActor {
  val counter = new AtomicLong()
  def ping() = context.system.scheduler.scheduleOnce(200.millis, self, "persist")
  def randomId: String = UUID.randomUUID.toString
  override val receiveRecover: Receive = PartialFunction.empty
  override val receiveCommand: Receive = {
    case "persist" =>
      persist(Person(counter.incrementAndGet(), s"foo-$randomId", 20)) { _ =>
        sender() ! "ack"
      }
      if (schedule) ping()
  }
  if (schedule) ping()
}

@Ignore
class CurrentPersistenceIdsQuerySourceTest extends TestSpec {
  def withPersistentActor(pid: String = randomId, schedule: Boolean = false)(f: ActorRef => TestProbe => Unit): Unit = {
    val tp = TestProbe()
    val ref = system.actorOf(Props(new PersonActor(pid, schedule)))
    try f(ref)(tp) finally killActors(ref)
  }

  it should "query read journal" in withSparkSession { spark =>
    withPersistentActor() { ref => tp =>
      tp.send(ref, "persist")
      tp.expectMsg("ack")

      val jdbcReadJournal = spark.readStream
        .currentPersistenceIds("jdbc-read-journal")

      jdbcReadJournal.printSchema()

      println("Is the query streaming: " + jdbcReadJournal.isStreaming)
      println("Are there any streaming queries? " + spark.streams.active.isEmpty)

      val query = jdbcReadJournal
        .writeStream
        .format("console")
        .trigger(ProcessingTime(1.seconds))
        .queryName("consoleStream")
        .outputMode(OutputMode.Append())
        .start()

      query.awaitTermination(10.seconds)
    }
  }
} 
Example 3
Source File: UserRepository.scala    From gabbler   with Apache License 2.0 5 votes vote down vote up
package de.heikoseeberger.gabbler.user

import akka.NotUsed
import akka.actor.{ ActorLogging, Props }
import akka.persistence.PersistentActor
import akka.persistence.query.EventEnvelope
import akka.persistence.query.scaladsl.EventsByPersistenceIdQuery
import akka.stream.scaladsl.Source

object UserRepository {

  sealed trait UserEvent

  final case object GetUsers
  final case class Users(users: Set[User])

  final case class AddUser(username: String, nickname: String, email: String)
  final case class UserAdded(user: User) extends UserEvent
  final case class UsernameTaken(username: String)

  final case class RemoveUser(id: Long)
  final case class UserRemoved(user: User) extends UserEvent
  final case class IdUnknown(id: Long)

  final case class GetUserEvents(fromSeqNo: Long)
  final case class UserEvents(userEvents: Source[(Long, UserEvent), NotUsed])

  final case class User(id: Long, username: String, nickname: String, email: String)

  final val Name = "user-repository"

  def apply(readJournal: EventsByPersistenceIdQuery): Props =
    Props(new UserRepository(readJournal))
}

final class UserRepository(readJournal: EventsByPersistenceIdQuery)
    extends PersistentActor
    with ActorLogging {
  import UserRepository._

  override val persistenceId = Name

  private var users = Map.empty[String, User]

  override def receiveCommand = {
    case GetUsers                           => sender() ! Users(users.valuesIterator.to[Set])
    case AddUser(username, nickname, email) => handleAddUser(username, nickname, email)
    case RemoveUser(id)                     => handleRemoveUser(id)
    case GetUserEvents(fromSeqNo)           => handleGetUserEvents(fromSeqNo)
  }

  override def receiveRecover = {
    case UserAdded(user)   => users += user.username -> user
    case UserRemoved(user) => users -= user.username
  }

  private def handleAddUser(username: String, nickname: String, email: String) = {
    def add() =
      persist(UserAdded(User(lastSequenceNr, username, nickname, email))) { userAdded =>
        receiveRecover(userAdded)
        log.info("Added user with username {}", username)
        sender() ! userAdded
      }
    if (!users.contains(username)) add() else sender() ! UsernameTaken(username)
  }

  private def handleRemoveUser(id: Long) = {
    def remove(user: User) =
      persist(UserRemoved(user)) { userRemoved =>
        receiveRecover(userRemoved)
        log.info("Removed user with id {} and username {}", id, user.username)
        sender() ! userRemoved
      }
    users.valuesIterator.find(_.id == id) match {
      case Some(user) => remove(user)
      case None       => sender() ! IdUnknown(id)
    }
  }

  private def handleGetUserEvents(fromSeqNo: Long) = {
    val userEvents =
      readJournal
        .eventsByPersistenceId(Name, fromSeqNo, Long.MaxValue)
        .collect { case EventEnvelope(_, _, seqNo, event: UserEvent) => seqNo -> event }
    sender() ! UserEvents(userEvents)
  }
} 
Example 4
Source File: UserRepository.scala    From gabbler   with Apache License 2.0 5 votes vote down vote up
package de.heikoseeberger.gabbler.chat

import akka.actor.{ ActorLogging, Props }
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.Uri
import akka.persistence.{ PersistentActor, RecoveryCompleted }
import akka.stream.ActorMaterializer
import akka.stream.alpakka.sse.scaladsl.EventSource
import de.heikoseeberger.akkasse.ServerSentEvent
import io.circe.parser.decode

object UserRepository {

  private sealed trait UserEvent

  final case class FindUserByUsername(username: String)
  final case class UsernameUnknown(username: String)

  private final case class AddUser(id: Long, username: String, nickname: String)
  private final case class UserAdded(eventId: String, user: User)

  private final case class RemoveUser(id: Long)
  private final case class UserRemoved(eventId: String, user: User)

  final case class User(id: Long, username: String, nickname: String)

  final val Name = "user-repository"

  def apply(userEventsEndpoint: Uri): Props =
    Props(new UserRepository(userEventsEndpoint))
}

final class UserRepository(userEventsEndpoint: Uri) extends PersistentActor with ActorLogging {
  import UserRepository._
  import io.circe.generic.auto._

  override val persistenceId = Name

  private implicit val mat = ActorMaterializer()

  private var users = Map.empty[String, User]

  private var lastEventId = Option.empty[String]

  override def receiveCommand = {
    case FindUserByUsername(n)               => handleFindUserByUsername(n)
    case (eventId: String, AddUser(i, u, n)) => handleAddUser(eventId, i, u, n)
    case (eventId: String, RemoveUser(i))    => handleRemoveUser(eventId, i)
  }

  override def receiveRecover = {
    case RecoveryCompleted =>
      userEvents(lastEventId).runForeach(self ! _)

    case UserAdded(eventId, user) =>
      lastEventId = Some(eventId)
      users += user.username -> user
      log.info("Added user with username {}", user.username)

    case UserRemoved(eventId, user) =>
      lastEventId = Some(eventId)
      users -= user.username
      log.info("Removed user with username {}", user.username)
  }

  private def handleFindUserByUsername(username: String) =
    users.get(username) match {
      case Some(user) => sender() ! user
      case None       => sender() ! UsernameUnknown(username)
    }

  private def handleAddUser(eventId: String, id: Long, username: String, nickname: String) =
    persist(UserAdded(eventId, User(id, username, nickname)))(receiveRecover)

  private def handleRemoveUser(eventId: String, id: Long) =
    users.values.find(_.id == id) match {
      case Some(user) => persist(UserRemoved(eventId, user))(receiveRecover)
      case None       => log.warning("User with id {} does not exist!", id)
    }

  private def userEvents(lastEventId: Option[String]) =
    EventSource(userEventsEndpoint, Http(context.system).singleRequest(_), lastEventId)
      .collect {
        case ServerSentEvent(Some(data), Some("user-added"), Some(eventId), _) =>
          eventId -> decode[AddUser](data)
        case ServerSentEvent(Some(data), Some("user-removed"), Some(eventId), _) =>
          eventId -> decode[RemoveUser](data)
      }
      .collect { case (eventId, Right(userEvent)) => eventId -> userEvent }
} 
Example 5
Source File: AtLeastOnce.scala    From reactive-application-development-scala   with Apache License 2.0 5 votes vote down vote up
import akka.actor.{ Actor, ActorSelection }
import akka.persistence.{ AtLeastOnceDelivery, PersistentActor }

sealed trait Cmd
case class SayHello(deliveryId: Long, s: String) extends Cmd
case class ReceiveHello(deliveryId: Long) extends Cmd

sealed trait Evt
case class HelloSaid(s: String) extends Evt
case class HelloReceived(deliveryId: Long) extends Evt


class SendActor(destination: ActorSelection)
    extends PersistentActor with AtLeastOnceDelivery {


  override def persistenceId: String = "persistence-id"


  override def receiveCommand: Receive = {
    case s: String =>
      persist(HelloSaid(s))(updateState)
    case ReceiveHello(deliveryId) =>
      persist(HelloReceived(deliveryId))(updateState)
  }


  override def receiveRecover: Receive = {
    case evt: Evt => updateState(evt)
  }

  def updateState(evt: Evt): Unit = evt match {
    case HelloSaid(s) =>
      deliver(destination)(deliveryId => SayHello(deliveryId, s))

    case HelloReceived(deliveryId) =>
      confirmDelivery(deliveryId)
  }
}

class ReceiveActor extends Actor {
  def receive = {
    case SayHello(deliveryId, s) =>
      // ... do something with s
      sender() ! ReceiveHello(deliveryId)
  }
} 
Example 6
Source File: DeduplicationInterceptor.scala    From akka-cqrs   with Apache License 2.0 5 votes vote down vote up
package com.productfoundry.akka.cqrs.process

import akka.persistence.PersistentActor
import akka.productfoundry.contrib.pattern.ReceivePipeline
import akka.productfoundry.contrib.pattern.ReceivePipeline.{HandledCompletely, Inner}
import com.productfoundry.akka.cqrs.AggregateEventRecord

trait DeduplicationInterceptor {
  this: PersistentActor with ReceivePipeline =>

  private var deduplicationIds: Set[String] = Set.empty

  pipelineInner {
    case eventRecord: AggregateEventRecord =>

      val deduplicationId = eventRecord.tag.value

      if (deduplicationIds.contains(deduplicationId)) {
        HandledCompletely
      } else {
        persist(DeduplicationEntry(deduplicationId))( _ => handled(deduplicationId))
        Inner(eventRecord)
      }
  }

  override def receiveRecover: Receive = {
    case DeduplicationEntry(deduplicationId) => handled(deduplicationId)
  }

  protected def handled(deduplicationId: String): Unit = {
    deduplicationIds += deduplicationId
  }
} 
Example 7
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")
   }
} 
Example 8
Source File: UserHandler.scala    From reactive-microservices   with MIT License 5 votes vote down vote up
import akka.actor.{ActorLogging, ActorRef, PoisonPill, Props}
import akka.persistence.PersistentActor
import akka.routing.{RemoveRoutee, ActorRefRoutee, AddRoutee}
import btc.common.UserHandlerMessages._
import btc.common.WebSocketHandlerMessages.{OperationSuccessful, Alarm, AllSubscriptions}
import scala.collection.mutable
import scala.concurrent.duration._
import UserHandler._

object UserHandler {
  case object KeepAlive

  case class Ticker(max: BigDecimal, min: BigDecimal, last: BigDecimal, bid: BigDecimal, ask: BigDecimal, vwap: BigDecimal, average: BigDecimal, volume: BigDecimal)

  def props(userId: Long, wsActor: ActorRef, broadcaster: ActorRef, keepAliveTimeout: FiniteDuration) = {
    Props(new UserHandler(userId, wsActor, broadcaster, keepAliveTimeout))
  }
}

class UserHandler(userId: Long, wsActor: ActorRef, broadcaster: ActorRef, keepAliveTimeout: FiniteDuration) extends PersistentActor with ActorLogging {
  override val persistenceId: String = userId.toString

  override def preStart(): Unit = {
    super.preStart()
    broadcaster ! AddRoutee(ActorRefRoutee(self))
  }

  override def postStop(): Unit = {
    super.postStop()
    broadcaster ! RemoveRoutee(ActorRefRoutee(self))
  }

  override def receiveRecover: Receive = {
    case subscribe: Subscribe => updateState(subscribe)
    case unsubscribe: Unsubscribe => updateState(unsubscribe)
  }

  override def receiveCommand: Receive = {
    case KeepAlive if System.currentTimeMillis() - lastHeartBeatTime > keepAliveTimeout.toMillis =>
      log.info(s"Timeout while waiting for heartbeat for user $userId, stopping")
      self ! PoisonPill
    case Heartbeat =>
      log.debug(s"Got heartbeat for user $userId")
      lastHeartBeatTime = System.currentTimeMillis()
      sender() ! Heartbeat
    case QuerySubscriptions =>
      log.info(s"Got request for subscriptions for user $userId")
      wsActor ! AllSubscriptions(subscriptions.values.toList)
    case ticker: Ticker =>
      val alarms = getAlarmsForTicker(ticker)
      log.debug(s"Got ticker and sending alarms $alarms for user $userId")
      alarms.foreach(wsActor ! _)
    case subscribe: Subscribe =>
      log.debug(s"Got subscribe request $subscribe for user $userId")
      persist(subscribe) { e =>
        updateState(e)
        wsActor ! OperationSuccessful(e.id)
      }
    case unsubscribe: Unsubscribe =>
      log.debug(s"Got unsubscribe request $unsubscribe for user $userId")
      persist(unsubscribe) { e =>
        updateState(e)
        wsActor ! OperationSuccessful(e.id)
      }
  }

  private def updateState(subscribe: Subscribe) = subscriptions.put(subscribe.id, subscribe)

  private def updateState(unsubscribe: Unsubscribe) = subscriptions.remove(unsubscribe.id)

  private def getAlarmsForTicker(ticker: Ticker): List[Alarm] = {
    subscriptions.values.map {
      case SubscribeRateChange(id) => Option(Alarm(id, ticker.average))
      case SubscribeBidOver(id, threshold) => if (ticker.bid > threshold) Option(Alarm(id, ticker.bid)) else None
      case SubscribeAskBelow(id, threshold) => if (ticker.ask < threshold) Option(Alarm(id, ticker.ask)) else None
      case SubscribeVolumeOver(id, threshold) => if (ticker.volume > threshold) Option(Alarm(id, ticker.volume)) else None
      case SubscribeVolumeBelow(id, threshold) => if (ticker.volume < threshold) Option(Alarm(id, ticker.volume)) else None
    }.toList.flatten
  }

  private val subscriptions = mutable.Map.empty[Long, Subscribe]
  private var lastHeartBeatTime = System.currentTimeMillis()
} 
Example 9
Source File: ClusterShardingQuickTerminationSpec.scala    From akka-persistence-cassandra   with Apache License 2.0 5 votes vote down vote up
package akka.persistence.cassandra.sharding

import akka.actor.{ ActorLogging, ActorRef, Props, ReceiveTimeout }
import akka.cluster.{ Cluster, MemberStatus }
import akka.cluster.sharding.{ ClusterSharding, ClusterShardingSettings, ShardRegion }
import akka.persistence.PersistentActor
import akka.persistence.cassandra.CassandraSpec
import akka.testkit.TestProbe

import scala.concurrent.duration._

object ClusterShardingQuickTerminationSpec {

  case object Increment
  case object Decrement
  final case class Get(counterId: Long)
  final case class EntityEnvelope(id: Long, payload: Any)
  case object Ack

  case object Stop
  final case class CounterChanged(delta: Int)

  class Counter extends PersistentActor with ActorLogging {
    import ShardRegion.Passivate

    context.setReceiveTimeout(5.seconds)

    // self.path.name is the entity identifier (utf-8 URL-encoded)
    override def persistenceId: String = "Counter-" + self.path.name

    var count = 0

    def updateState(event: CounterChanged): Unit =
      count += event.delta

    override def receiveRecover: Receive = {
      case evt: CounterChanged => updateState(evt)
      case other               => log.debug("Other: {}", other)
    }

    override def receiveCommand: Receive = {
      case Increment      => persist(CounterChanged(+1))(updateState)
      case Decrement      => persist(CounterChanged(-1))(updateState)
      case Get(_)         => sender() ! count
      case ReceiveTimeout => context.parent ! Passivate(stopMessage = Stop)
      case Stop =>
        sender() ! Ack
        context.stop(self)
    }
  }
  val extractEntityId: ShardRegion.ExtractEntityId = {
    case EntityEnvelope(id, payload) => (id.toString, payload)
    case msg @ Get(id)               => (id.toString, msg)
  }

  val numberOfShards = 100

  val extractShardId: ShardRegion.ExtractShardId = {
    case EntityEnvelope(id, _) => (id % numberOfShards).toString
    case Get(id)               => (id % numberOfShards).toString
  }

}

class ClusterShardingQuickTerminationSpec extends CassandraSpec("""
    akka.actor.provider = cluster
  """.stripMargin) {

  import ClusterShardingQuickTerminationSpec._

  "Cassandra Plugin with Cluster Sharding" must {
    "clear state if persistent actor shuts down" in {
      Cluster(system).join(Cluster(system).selfMember.address)
      awaitAssert {
        Cluster(system).selfMember.status shouldEqual MemberStatus.Up
      }
      ClusterSharding(system).start(
        typeName = "tagging",
        entityProps = Props[Counter],
        settings = ClusterShardingSettings(system),
        extractEntityId = extractEntityId,
        extractShardId = extractShardId)

      (0 to 100).foreach { i =>
        val counterRegion: ActorRef = ClusterSharding(system).shardRegion("tagging")
        awaitAssert {
          val sender = TestProbe()
          counterRegion.tell(Get(123), sender.ref)
          sender.expectMsg(500.millis, i)
        }

        counterRegion ! EntityEnvelope(123, Increment)
        counterRegion ! Get(123)
        expectMsg(i + 1)

        counterRegion ! EntityEnvelope(123, Stop)
        expectMsg(Ack)
      }
    }
  }
} 
Example 10
Source File: TestActor.scala    From akka-persistence-cassandra   with Apache License 2.0 5 votes vote down vote up
package akka.persistence.cassandra.query

import scala.collection.immutable
import akka.actor.Props
import akka.persistence.PersistentActor
import akka.actor.ActorRef
import akka.persistence.DeleteMessagesSuccess
import akka.persistence.cassandra.EventWithMetaData
import akka.persistence.journal.Tagged

object TestActor {
  def props(persistenceId: String, journalId: String = "akka.persistence.cassandra.journal"): Props =
    Props(new TestActor(persistenceId, journalId))

  final case class PersistAll(events: immutable.Seq[String])
  final case class DeleteTo(seqNr: Long)
}

class TestActor(override val persistenceId: String, override val journalPluginId: String) extends PersistentActor {

  var lastDelete: ActorRef = _

  val receiveRecover: Receive = {
    case evt: String =>
  }

  val receiveCommand: Receive = {
    case cmd: String =>
      persist(cmd) { evt =>
        sender() ! evt + "-done"
      }
    case cmd: EventWithMetaData =>
      persist(cmd) { evt =>
        sender() ! s"$evt-done"
      }
    case cmd: Tagged =>
      persist(cmd) { evt =>
        val msg = s"${evt.payload}-done"
        sender() ! msg
      }

    case TestActor.PersistAll(events) =>
      val size = events.size
      val handler = {
        var count = 0
        evt: String => {
          count += 1
          if (count == size)
            sender() ! "PersistAll-done"
        }
      }
      persistAll(events)(handler)

    case TestActor.DeleteTo(seqNr) =>
      lastDelete = sender()
      deleteMessages(seqNr)

    case d: DeleteMessagesSuccess =>
      lastDelete ! d
  }
} 
Example 11
Source File: TestTaggingActor.scala    From akka-persistence-cassandra   with Apache License 2.0 5 votes vote down vote up
package akka.persistence.cassandra

import akka.actor.{ ActorLogging, ActorRef, Props }
import akka.persistence.cassandra.journal.TagWriterSpec.TestEx
import akka.persistence.{ PersistentActor, RecoveryCompleted, SaveSnapshotSuccess }
import akka.persistence.journal.Tagged

object TestTaggingActor {
  case object Ack
  case object Crash
  case object DoASnapshotPlease
  case object SnapShotAck
  case object Stop

  def props(pId: String, tags: Set[String] = Set(), probe: Option[ActorRef] = None): Props =
    Props(new TestTaggingActor(pId, tags, probe))
}

class TestTaggingActor(val persistenceId: String, tags: Set[String], probe: Option[ActorRef])
    extends PersistentActor
    with ActorLogging {
  import TestTaggingActor._

  def receiveRecover: Receive = {
    case RecoveryCompleted =>
      probe.foreach(_ ! RecoveryCompleted)
    case _ =>
  }

  def receiveCommand: Receive = normal

  def normal: Receive = {
    case event: String =>
      log.debug("Persisting {}", event)
      persist(Tagged(event, tags)) { e =>
        processEvent(e)
        sender() ! Ack
      }
    case Crash =>
      throw TestEx("oh dear")
    case DoASnapshotPlease =>
      saveSnapshot("i don't have any state :-/")
      context.become(waitingForSnapshot(sender()))
    case Stop =>
      context.stop(self)

  }

  def waitingForSnapshot(who: ActorRef): Receive = {
    case SaveSnapshotSuccess(_) =>
      who ! SnapShotAck
      context.become(normal)
  }

  def processEvent: Receive = {
    case _ =>
  }
} 
Example 12
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 13
Source File: HasPersistence.scala    From ForestFlow   with Apache License 2.0 5 votes vote down vote up
package ai.forestflow.serving.cluster

import akka.actor.{Actor, ActorLogging}
import akka.persistence.PersistentActor

trait HasPersistence extends ActorLogging {
  this: PersistentActor =>

  def persistencePrefix: String

  override def persistenceId: String = {
    /*log.info(s"Getting persistenceId: akka.serialization.Serialization.serializedActorPath(self) = ${akka.serialization.Serialization.serializedActorPath(self)}")
    log.info(s"self.path.address = ${self.path.address}")
    log.info(s"self.path.elements.toList.mkString('-') = ${self.path.elements.toList.mkString("-")}")
    log.info(s"self.path.elements.toString() = ${self.path.elements.toString()}")
    log.info(s"self.path.toStringWithAddress(self.path.address) = ${self.path.toStringWithAddress(self.path.address)}")
    log.info(s"self.path.toString = ${self.path.toString}")*/
    s"$persistencePrefix-${context.parent.path.name}-${self.path.name}"
  }
} 
Example 14
Source File: Person.scala    From akka-serialization-test   with Apache License 2.0 5 votes vote down vote up
package com.github.dnvriend.domain

import akka.actor.ActorLogging
import akka.event.LoggingReceive
import akka.persistence.{ PersistentActor, RecoveryCompleted }

object Person {
  sealed trait PersonEvent
  final case class NameRegisteredEvent(name: String, surname: String) extends PersonEvent
  final case class NameChangedEvent(name: String) extends PersonEvent
  final case class SurnameChangedEvent(surname: String) extends PersonEvent

  sealed trait PersonCommand
  final case class RegisterNameCommand(name: String, surname: String) extends PersonCommand
  final case class ChangeNameCommand(name: String) extends PersonCommand
  final case class ChangeSurnameCommand(surname: String) extends PersonCommand
}

class Person(val persistenceId: String) extends PersistentActor with ActorLogging {
  import Person._
  var name: String = _
  var surname: String = _

  override def receiveRecover: Receive = LoggingReceive {
    case e: NameRegisteredEvent ⇒

      handleEvent(e)
    case e: NameChangedEvent    ⇒ handleEvent(e)
    case e: SurnameChangedEvent ⇒ handleEvent(e)
    case RecoveryCompleted      ⇒ println("==> Recovery completed")
    case e                      ⇒ println("Dropping event: " + e.getClass.getName)
  }

  def handleEvent(event: NameRegisteredEvent): Unit = {
    this.name = event.name
    this.surname = event.surname
    log.debug(s"[NameRegistered]: Person $persistenceId => name: $name, surname: $surname")
  }

  def handleEvent(event: NameChangedEvent): Unit = {
    this.name = event.name
    log.debug(s"[NameChanged]: Person $persistenceId => name: $name, surname: $surname")
  }

  def handleEvent(event: SurnameChangedEvent): Unit = {
    this.surname = event.surname
    log.debug(s"[SurnameChanged]: Person $persistenceId => name: $name, surname: $surname")
  }

  override def receiveCommand: Receive = LoggingReceive {
    case RegisterNameCommand(name, surname) ⇒
      persist(NameRegisteredEvent(name, surname)) { e ⇒
        handleEvent(e)
        sender() ! akka.actor.Status.Success("")
      }
    case ChangeNameCommand(newName) ⇒
      persist(NameChangedEvent(newName)) { e ⇒
        handleEvent(e)
        sender() ! akka.actor.Status.Success("")
      }
    case ChangeSurnameCommand(newSurname) ⇒
      persist(SurnameChangedEvent(newSurname)) { e ⇒
        handleEvent(e)
        sender() ! akka.actor.Status.Success("")
      }
  }

  override def postStop(): Unit = {
    log.debug(s"Stopped $persistenceId")
    super.postStop()
  }
} 
Example 15
Source File: AbstractEmbeddedPersistentActorSpec.scala    From akka-persistence-couchbase   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.scaladsl.persistence.testkit

import akka.actor.{ ActorRef, Props, actorRef2Scala }
import akka.persistence.PersistentActor
import com.lightbend.lagom.persistence.ActorSystemSpec

import scala.concurrent.duration._

object AbstractEmbeddedPersistentActorSpec {

  final case class Cmd(data: String)
  final case class Evt(data: String)
  case object Get
  final case class State(data: Vector[String] = Vector.empty) {
    def apply(evt: Evt): State = {
      copy(data :+ evt.data)
    }
  }

  def props(persistenceId: String): Props =
    Props(new Persistent(persistenceId))

  class Persistent(override val persistenceId: String) extends PersistentActor {
    var state = State()

    override def receiveRecover = {
      case evt: Evt => state = state(evt)
    }

    override def receiveCommand = {
      case Cmd(data) =>
        persist(Evt(data.toUpperCase)) { evt =>
          state = state(evt)
        }
      case Get => sender() ! state
    }
  }

}

trait AbstractEmbeddedPersistentActorSpec { spec: ActorSystemSpec =>
  import AbstractEmbeddedPersistentActorSpec._

  "A persistent actor" must {
    "store events in the embedded journal" in within(15.seconds) {
      val p = system.actorOf(props("p1"))
      println(implicitly[ActorRef])

      p ! Get
      expectMsg(State())
      p ! Cmd("a")
      p ! Cmd("b")
      p ! Cmd("c")
      p ! Get
      expectMsg(State(Vector("A", "B", "C")))

      // start another with same persistenceId should recover state
      val p2 = system.actorOf(props("p1"))
      p2 ! Get
      expectMsg(State(Vector("A", "B", "C")))
    }

  }

} 
Example 16
Source File: AbstractEmbeddedPersistentActorSpec.scala    From akka-persistence-couchbase   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.javadsl.persistence.testkit

import akka.actor.{ ActorRef, Props, actorRef2Scala }
import akka.persistence.PersistentActor
import com.lightbend.lagom.persistence.ActorSystemSpec

import scala.concurrent.duration._

object AbstractEmbeddedPersistentActorSpec {

  final case class Cmd(data: String)
  final case class Evt(data: String)
  case object Get
  final case class State(data: Vector[String] = Vector.empty) {
    def apply(evt: Evt): State = {
      copy(data :+ evt.data)
    }
  }

  def props(persistenceId: String): Props =
    Props(new Persistent(persistenceId))

  class Persistent(override val persistenceId: String) extends PersistentActor {
    var state = State()

    override def receiveRecover = {
      case evt: Evt => state = state(evt)
    }

    override def receiveCommand = {
      case Cmd(data) =>
        persist(Evt(data.toUpperCase)) { evt =>
          state = state(evt)
        }
      case Get => sender() ! state
    }
  }

}

trait AbstractEmbeddedPersistentActorSpec { spec: ActorSystemSpec =>
  import AbstractEmbeddedPersistentActorSpec._

  "A persistent actor" must {
    "store events in the embedded journal" in within(15.seconds) {
      val p = system.actorOf(props("p1"))
      println(implicitly[ActorRef])

      p ! Get
      expectMsg(State())
      p ! Cmd("a")
      p ! Cmd("b")
      p ! Cmd("c")
      p ! Get
      expectMsg(State(Vector("A", "B", "C")))

      // start another with same persistenceId should recover state
      val p2 = system.actorOf(props("p1"))
      p2 ! Get
      expectMsg(State(Vector("A", "B", "C")))
    }

  }

} 
Example 17
Source File: AwaitPersistenceInit.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.persistence.testkit

import java.util.concurrent.TimeUnit

import akka.actor.ActorSystem
import akka.actor.Props
import akka.persistence.PersistentActor
import akka.testkit.TestProbe
import org.slf4j.LoggerFactory

import scala.concurrent.duration._

// A copy of akka.persistence.cassandra.CassandraLifecycle's awaitPersistenceInit.
private[lagom] object AwaitPersistenceInit {
  def awaitPersistenceInit(system: ActorSystem): Unit = {
    val probe = TestProbe()(system)
    val log   = LoggerFactory.getLogger(getClass)
    val t0    = System.nanoTime()
    var n     = 0
    probe.within(45.seconds) {
      probe.awaitAssert {
        n += 1
        system.actorOf(Props[AwaitPersistenceInit], "persistenceInit" + n).tell("hello", probe.ref)
        probe.expectMsg(15.seconds, "hello")
        log.debug(
          "awaitPersistenceInit took {} ms {}",
          TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t0),
          system.name
        )
      }
    }
  }
}

private[lagom] class AwaitPersistenceInit extends PersistentActor {
  def persistenceId: String = self.path.name

  def receiveRecover: Receive = {
    case _ =>
  }

  def receiveCommand: Receive = {
    case msg =>
      persist(msg) { _ =>
        sender() ! msg
        context.stop(self)
      }
  }
} 
Example 18
Source File: AbstractEmbeddedPersistentActorSpec.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.scaladsl.persistence.testkit

import akka.actor.ActorRef
import akka.actor.ActorSystem
import akka.actor.Props
import akka.actor.actorRef2Scala
import akka.persistence.PersistentActor
import akka.testkit.ImplicitSender
import akka.testkit.TestKitBase
import com.lightbend.lagom.persistence.ActorSystemSpec
import com.lightbend.lagom.persistence.PersistenceSpec

import scala.collection.immutable
import com.lightbend.lagom.scaladsl.playjson.JsonSerializerRegistry
import com.lightbend.lagom.scaladsl.playjson.JsonSerializer
import scala.concurrent.duration._

object AbstractEmbeddedPersistentActorSpec {
  final case class Cmd(data: String)
  final case class Evt(data: String)
  case object Get
  final case class State(data: Vector[String] = Vector.empty) {
    def apply(evt: Evt): State = {
      copy(data :+ evt.data)
    }
  }

  def props(persistenceId: String): Props =
    Props(new Persistent(persistenceId))

  class Persistent(override val persistenceId: String) extends PersistentActor {
    var state = State()

    override def receiveRecover = {
      case evt: Evt => state = state(evt)
    }

    override def receiveCommand = {
      case Cmd(data) =>
        persist(Evt(data.toUpperCase)) { evt =>
          state = state(evt)
        }
      case Get => sender() ! state
    }
  }

  object EmbeddedPersistentActorSerializers extends JsonSerializerRegistry {
    override def serializers: immutable.Seq[JsonSerializer[_]] = {
      import play.api.libs.json._
      import JsonSerializer.emptySingletonFormat

      Vector(
        JsonSerializer(Json.format[Cmd]),
        JsonSerializer(Json.format[Evt]),
        JsonSerializer(emptySingletonFormat(Get)),
        JsonSerializer(Json.format[State])
      )
    }
  }
}

trait AbstractEmbeddedPersistentActorSpec { spec: ActorSystemSpec =>
  import AbstractEmbeddedPersistentActorSpec._

  "A persistent actor" must {
    "store events in the embedded journal" in within(15.seconds) {
      val p = system.actorOf(props("p1"))
      println(implicitly[ActorRef])

      p ! Get
      expectMsg(State())
      p ! Cmd("a")
      p ! Cmd("b")
      p ! Cmd("c")
      p ! Get
      expectMsg(State(Vector("A", "B", "C")))

      // start another with same persistenceId should recover state
      val p2 = system.actorOf(props("p1"))
      p2 ! Get
      expectMsg(State(Vector("A", "B", "C")))
    }
  }
} 
Example 19
Source File: AbstractEmbeddedPersistentActorSpec.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.javadsl.persistence.testkit

import akka.actor.ActorRef
import akka.actor.Props
import akka.actor.actorRef2Scala
import akka.persistence.PersistentActor
import com.lightbend.lagom.persistence.ActorSystemSpec
import com.lightbend.lagom.serialization.Jsonable

import scala.concurrent.duration._

object AbstractEmbeddedPersistentActorSpec {
  // All commands and events extending Jsonable so that the
  // tests will use Jackson serialization instead of Java's.
  case object Get                    extends Jsonable
  final case class Cmd(data: String) extends Jsonable
  final case class Evt(data: String) extends Jsonable
  final case class State(data: Vector[String] = Vector.empty) extends Jsonable {
    def apply(evt: Evt): State = {
      copy(data :+ evt.data)
    }
  }

  def props(persistenceId: String): Props =
    Props(new Persistent(persistenceId))

  class Persistent(override val persistenceId: String) extends PersistentActor {
    var state = State()

    override def receiveRecover = {
      case evt: Evt => state = state(evt)
    }

    override def receiveCommand = {
      case Cmd(data) =>
        persist(Evt(data.toUpperCase)) { evt =>
          state = state(evt)
        }
      case Get => sender() ! state
    }
  }
}

trait AbstractEmbeddedPersistentActorSpec { spec: ActorSystemSpec =>
  import AbstractEmbeddedPersistentActorSpec._

  "A persistent actor" must {
    "store events in the embedded journal" in within(15.seconds) {
      val p = system.actorOf(props("p1"))
      println(implicitly[ActorRef])

      p ! Get
      expectMsg(State())
      p ! Cmd("a")
      p ! Cmd("b")
      p ! Cmd("c")
      p ! Get
      expectMsg(State(Vector("A", "B", "C")))

      // start another with same persistenceId should recover state
      val p2 = system.actorOf(props("p1"))
      p2 ! Get
      expectMsg(State(Vector("A", "B", "C")))
    }
  }
} 
Example 20
Source File: StockPersistenceActor.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, RecoveryCompleted}

object StockPersistenceActor {
  def props(stockId: String) = Props(new StockPersistenceActor(stockId))
}

class StockPersistenceActor(stockId: String) extends PersistentActor with ActorLogging {
  override val persistenceId = stockId

  var state = StockHistory()
  def updateState(event: ValueAppended) = state = state.update(event)

  val receiveRecover: Receive = {
    case evt: ValueAppended => updateState(evt)
    case RecoveryCompleted => log.info(s"Recovery completed. Current state: $state")
  }

  val receiveCommand: Receive = {
    case ValueUpdate(value) => persist(ValueAppended(StockValue(value)))(updateState)
    case "print" => log.info(s"Current state: $state")
  }

  override def postStop() = log.info(s"Stopping [${self.path}]")
} 
Example 21
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 22
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 23
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 24
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 25
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 26
Source File: Music.scala    From akka-serialization-test   with Apache License 2.0 5 votes vote down vote up
package com.github.dnvriend.domain

import java.time.Duration

import akka.actor.ActorLogging
import akka.event.LoggingReceive
import akka.persistence.PersistentActor

object Music {

  type Title = String
  type Year = Int

  final case class Song(title: Title, duration: Duration)

  sealed trait AlbumEvent

  final case class TitleChanged(title: Title) extends AlbumEvent

  final case class YearChanged(year: Year) extends AlbumEvent

  final case class SongAdded(song: Song) extends AlbumEvent

  final case class SongRemoved(song: Song) extends AlbumEvent

  sealed trait AlbumCommand

  final case class ChangeAlbumTitle(title: Title) extends AlbumCommand

  final case class ChangeAlbumYear(year: Year) extends AlbumCommand

  final case class AddSong(song: Song) extends AlbumCommand

  final case class RemoveSong(song: Song) extends AlbumCommand

}

class Album(val persistenceId: String) extends PersistentActor with ActorLogging {

  import Music._

  var title: Title = _
  var year: Year = _
  var songs: Set[Song] = Set[Song]()

  override def receiveRecover: Receive = LoggingReceive {
    case e: TitleChanged ⇒ handleEvent(e)
    case e: YearChanged  ⇒ handleEvent(e)
    case e: SongAdded    ⇒ handleEvent(e)
    case e: SongRemoved  ⇒ handleEvent(e)
  }

  def handleEvent(event: TitleChanged): Unit = {
    this.title = event.title
    log.debug(s"[TitleChanged]: Album $persistenceId => title: $title, year: $year songs: $songs")
  }

  def handleEvent(event: YearChanged): Unit = {
    this.year = event.year
    log.debug(s"[YearChanged]: Album $persistenceId => title: $title, year: $year songs: $songs")
  }

  def handleEvent(event: SongAdded): Unit = {
    this.songs = this.songs + event.song
    log.debug(s"[SongAdded]: Album $persistenceId => title: $title, year: $year songs: $songs")
  }

  def handleEvent(event: SongRemoved): Unit = {
    this.songs = this.songs - event.song
    log.debug(s"[SongRemoved]: Album $persistenceId => title: $title, year: $year songs: $songs")
  }

  override def receiveCommand: Receive = LoggingReceive {
    case ChangeAlbumTitle(newTitle) ⇒
      persistAll(List(TitleChanged(newTitle))) { e ⇒
        handleEvent(e)
        sender() ! akka.actor.Status.Success("")
      }
    case ChangeAlbumYear(newYear) ⇒
      persistAll(List(YearChanged(newYear))) { e ⇒
        handleEvent(e)
        sender() ! akka.actor.Status.Success("")
      }
    case AddSong(newSong) ⇒
      persistAll(List(SongAdded(newSong))) { e ⇒
        handleEvent(e)
        sender() ! akka.actor.Status.Success("")
      }
    case RemoveSong(oldSong) ⇒
      persistAll(List(SongRemoved(oldSong))) { e ⇒
        handleEvent(e)
        sender() ! akka.actor.Status.Success("")
      }
  }

  override def postStop(): Unit = {
    log.debug(s"Stopped $persistenceId")
    super.postStop()
  }
}