akka.actor.FSM Scala Examples

The following examples show how to use akka.actor.FSM. 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: FSMAfterAllListenerHolder.scala    From reliable-http-client   with Apache License 2.0 5 votes vote down vote up
package rhttpc.akkapersistence.impl

import akka.actor.FSM
import rhttpc.akkapersistence.StateSaved

private[akkapersistence] trait FSMAfterAllListenerHolder[S, D] { this: FSM[S, D] =>
  private var currentAfterAllListener: Option[RecipientWithMsg] = None

  implicit class StateExt(state: this.State) {
    def acknowledgingAfterSave() = {
      replyingAfterSave()
    }

    def replyingAfterSave(msg: Any = StateSaved) = {
      currentAfterAllListener = Some(new RecipientWithMsg(sender(), msg))
      state
    }
  }

  protected def useCurrentAfterAllListener(): Option[RecipientWithMsg] = {
    val tmp = currentAfterAllListener
    currentAfterAllListener = None
    tmp
  }
} 
Example 2
Source File: ReliableFSMSpec.scala    From reliable-http-client   with Apache License 2.0 5 votes vote down vote up
package rhttpc.akkapersistence

import akka.actor.{ActorSystem, FSM, PoisonPill}
import akka.persistence._
import akka.testkit._
import org.scalatest._
import rhttpc.akkapersistence.impl._
import rhttpc.client.ReliableClientBaseSpec

import scala.concurrent.Await
import scala.concurrent.duration._

class ReliableFSMSpec
  extends TestKit(ActorSystem("ReliableFSMSpec"))
  with ReliableClientBaseSpec with ImplicitSender with Matchers {

  it should "save snapshot after message publication and reply with StateSaved" in { fixture =>
    createAndSendFoo(fixture, "12")
  }

  it should "recover in correct state not saving snapshot one more time" in { fixture =>
    val id = "123"
    val actor = createAndSendFoo(fixture, id)
    val snapshot = actor.underlyingActor.savedSnapshots.head

    watch(actor)
    actor ! PoisonPill
    expectTerminated(actor)

    val recovered = TestActorRef[FooBarActor](FooBarActor.props(id, fixture.client))
    recovered ! NotifyAboutRecoveryCompleted
    recovered.underlyingActor.recover(snapshot)
    expectMsg(RecoveryCompleted)

    Thread.sleep(500)
    recovered.underlyingActor.savedSnapshots shouldBe empty

    fixture.transport.replySubscriptionPromise.success("foo")
    awaitCond(recovered.underlyingActor.savedSnapshots.size == 1)
    Await.result(fixture.transport.ackOnReplySubscriptionFuture, 3 seconds)

    recovered ! CurrentState
    expectMsg(FooState)
  }

  def createAndSendFoo(fixture: FixtureParam, id: String): TestActorRef[FooBarActor] = {
    val actor = TestActorRef[FooBarActor](FooBarActor.props(id, fixture.client))
    actor ! SendMsg("foo")
    Thread.sleep(500)
    actor.underlyingActor.savedSnapshots shouldBe empty
    fixture.transport.publicationPromise.success(Unit)
    awaitCond(actor.underlyingActor.savedSnapshots.size == 1)
    expectMsg(StateSaved)
    actor
  }
}

trait MockReliableFSM[S, D] extends AbstractReliableFSM[S, D] with MockSnapshotter[S, D]

trait MockSnapshotter[S, D] extends AbstractSnapshotter { this: FSM[S, D] =>
  @volatile var savedSnapshots: List[SnapshotWithSeqNr] = List.empty

  override def saveSnapshotWithSeqNr(snapshot: Any, seqNr: Long): Unit = {
    savedSnapshots = SnapshotWithSeqNr(snapshot, seqNr) :: savedSnapshots
    self ! SaveSnapshotSuccess(SnapshotMetadata(persistenceId, seqNr))
  }

  def recover(snap: SnapshotWithSeqNr) = {
    self ! SnapshotOffer(SnapshotMetadata(persistenceId, snap.seqNr), snap.snapshot)
  }

  protected def handleRecover: Receive = {
    val handleOfferAndThanSendCompleted: Receive = {
      case offer: SnapshotOffer =>
        receiveRecover(offer)
        self ! RecoveryCompleted
    }
    handleOfferAndThanSendCompleted orElse receiveRecover
  }

  whenUnhandled {
    case Event(event, _) if handleRecover.isDefinedAt(event) =>
      handleRecover(event)
      stay()
  }

  override def deleteSnapshots(criteria: SnapshotSelectionCriteria): Unit = {}
}

case class SnapshotWithSeqNr(snapshot: Any, seqNr: Long) 
Example 3
Source File: TrafficLightFSM.scala    From Akka-Cookbook   with MIT License 5 votes vote down vote up
package com.packt.chapter10

import java.util.Date

import akka.actor.{Actor, ActorLogging, ActorRef, FSM}
import TrafficLightFSM._
import scala.concurrent.duration._

object TrafficLightFSM {
  sealed trait TrafficLightState
  case object Green extends TrafficLightState
  case object Yellow extends TrafficLightState
  case object Red extends TrafficLightState

  sealed trait Data
  case class Countdown(i: Int) extends Data

  //Events
  case object Tick
  case class ReportChange(to: TrafficLightState, date: Date)
}

class TrafficLightFSM(changesSubscriber: ActorRef) extends Actor with ActorLogging with FSM[TrafficLightState, Data]{
  import context.dispatcher

  trafficLightState(Green, Yellow, 2)
  trafficLightState(Yellow, Red, 4)
  trafficLightState(Red, Green, 8)
  startWith(Green, Countdown(8))

  initialize()
  scheduleTick()

  onTransition {
    case Green -> Yellow => changesSubscriber ! ReportChange(Yellow, new Date())
    case Yellow -> Red => changesSubscriber ! ReportChange(Red, new Date())
    case Red -> Green => changesSubscriber ! ReportChange(Green, new Date())
  }

  private def scheduleTick() = {
    context.system.scheduler.scheduleOnce(1 second, self, Tick)
  }

  private def trafficLightState(
                                 trafficLightState: TrafficLightState,
                                 nextTrafficLightState: TrafficLightState,
                                 totalSecondsNextState: Int) = {
    when(trafficLightState) {
      case Event(Tick, Countdown(i)) if i != 0 =>
        scheduleTick()
        log.info(s"Current state [$trafficLightState]. Countdown: [$i].")
        stay using Countdown(i - 1)
      case Event(Tick, Countdown(i)) if i == 0 =>
        scheduleTick()
        log.info(s"Changing from $trafficLightState to $nextTrafficLightState.")
        goto(nextTrafficLightState) using Countdown(totalSecondsNextState)
    }
  }
}