2015-10-02 3 views
1

Я пытаюсь протестировать новую функцию Akka 2.4 - PersistentFSM (http://doc.akka.io/docs/akka/2.4.0/scala/persistence.html#Persistent_FSM) с помощью простого примера ниже.PersistentFSM не сохраняется в журнале

В этом примере генерируется 5 случайных целых чисел и объявляется в последовательности. Мне бы хотелось, чтобы это продолжалось, и при следующем запуске приложения продолжайте добавлять существующую последовательность чисел. Текущая документация на PersistentFSM немного скудна, и нет четкого способа сделать эту работу. Есть идеи?

TestFSM.scala:

import akka.actor.{Actor, ActorSystem, Props} 
import akka.persistence.fsm.PersistentFSM 
import akka.persistence.fsm.PersistentFSM.FSMState 
import scala.reflect._ 
import scala.util.Random 

final case class SetNumber(num: Integer) 

sealed trait State extends FSMState 
case object Idle extends State { 
    override def identifier: String = "Idle" 
} 
case object Active extends State { 
    override def identifier: String = "Active" 
} 

sealed trait Data { 
    def add(number: Integer): Data 
} 
case object Empty extends Data { 
    def add(number: Integer) = Numbers(Vector(number)) 
} 
final case class Numbers(queue: Seq[Integer]) extends Data { 
    def add(number: Integer) = Numbers(queue :+ number) 
} 

sealed trait DomainEvt 
case class SetNumberEvt(num: Integer) extends DomainEvt 

class Generator extends Actor with PersistentFSM[State, Data, DomainEvt] { 

    override def applyEvent(domainEvent: DomainEvt, currentData: Data): Data = { 
     domainEvent match { 
      case SetNumberEvt(num) => currentData.add(num) 
     } 
    } 

    override def persistenceId: String = "generator" 

    override def domainEventClassTag: ClassTag[DomainEvt] = classTag[DomainEvt] 

    startWith(Idle, Empty) 

    when(Idle) { 
     case Event(SetNumber(num), Empty) => 
      goto(Active) applying SetNumberEvt(num) 
    } 

    when(Active) { 
     case Event(SetNumber(num), numbers: Data) => 
      println(numbers) 
      stay applying SetNumberEvt(num) 
    } 

    initialize() 

} 

object TestFSM extends App { 

    val system = ActorSystem() 

    val actor = system.actorOf(Props[Generator]) 

    actor ! SetNumber(Random.nextInt()) 
    actor ! SetNumber(Random.nextInt()) 
    actor ! SetNumber(Random.nextInt()) 
    actor ! SetNumber(Random.nextInt()) 
    actor ! SetNumber(Random.nextInt()) 

    Thread.sleep(1000) 
    system.terminate() 

} 

reference.conf:

akka.persistence.journal.plugin = "akka.persistence.journal.inmem" 
akka.persistence.snapshot-store.plugin = "akka.persistence.snapshot-store.local" 
akka.persistence.journal.leveldb.dir = "target/journal" 
akka.persistence.snapshot-store.local.dir = "target/snapshots" 
+0

Можете ли вы уточнить, какой тест вы проводите, чтобы установить, сохраняются ли события? – mattinbits

+0

@mattinbits на данный момент я даже не уверен, как заставить его работать. Это, кажется, объединенная функциональность 'FSM' и' PersistentActor' без полного примера. Из документации: «PersistentFSM обрабатывает входящие сообщения в формате FSM, а его внутреннее состояние сохраняется как последовательность изменений, которые позже называются событиями домена». - это предполагает другой подход от обычного метода 'persist', который теперь даже устарел. – Caballero

ответ

3

PersistentFSM Теперь неявно сохраняется как государственные изменения и события домена как доходы FSM.

Хотя документация связывании отсутствует, то можно увидеть из кода, который persistAll становится называются под капотом в соответствующей точке: https://github.com/akka/akka/blob/v2.4.0/akka-persistence/src/main/scala/akka/persistence/fsm/PersistentFSM.scala#L110

предлагает вам протестировать реализацию, как вы его увидеть действительно ли это сохраняется.

EDIT:

Я был в состоянии выполнить свой код, без изменений, и посмотреть каталог target/journal получить создан. Я использовал следующие build.sbt:

name := "Scratch" 

version := "1.0" 

scalaVersion := "2.11.7" 

sbtVersion := "0.13.7" 

mainClass := Some("TestFSM") 

fork := true 

libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.4.0" 

libraryDependencies += "com.typesafe.akka" %% "akka-persistence" % "2.4.0" 

libraryDependencies += "org.iq80.leveldb"   % "leveldb"   % "0.7" 

libraryDependencies += "org.fusesource.leveldbjni" % "leveldbjni-all" % "1.8" 

И следующий application.conf:

akka.persistence.journal.plugin = "akka.persistence.journal.leveldb" 
akka.persistence.snapshot-store.plugin = "akka.persistence.snapshot-store.local" 
akka.persistence.journal.leveldb.dir = "target/journal" 
akka.persistence.snapshot-store.local.dir = "target/snapshots" 

Я думаю application.conf является подходящим способом указать для конкретного применения, а не конф reference.conf, который предназначен для библиотек.

+0

Если 'persistAll' вызывается под капотом, тогда это будет работать, не так ли? Папка 'target/journal' даже не создана, что происходит в классическом случае' PersistentActor', используя метод 'persist'. – Caballero

+0

Вы используете 'akka.persistence.journal.inmem', который, как следует из названия, является журналом только в памяти. Вот почему я спросил выше, что вы сделали, чтобы проверить, работает ли упорство. Попробуйте использовать 'akka.persistence.journal.plugin =" akka.persistence.journal.leveldb "' – mattinbits

+0

Спасибо, я этого не заметил. Я изменил его на 'akka.persistence.journal.plugin =" akka.persistence.journal.leveldb "' сейчас, но никакой разницы - все еще не создана папка журнала. – Caballero