2015-10-02 1 views
1

J'essaye de tester une nouvelle fonctionnalité de Akka 2.4 - PersistentFSM (http://doc.akka.io/docs/akka/2.4.0/scala/persistence.html#Persistent_FSM) avec l'exemple simple ci-dessous.PersistentFSM ne persiste pas à journal

Cet exemple génère 5 entiers aléatoires et l'affiche dans la séquence. Ce que je voudrais qu'il fasse est de persister les données et à la prochaine exécution de l'application continue d'ajouter à la séquence existante de nombres. La documentation actuelle sur PersistentFSM est un peu rare et il n'y a pas de moyen clair de faire ce travail. Des idées?

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

Pouvez-vous élaborer sur le test que vous faites pour établir si les événements sont persistants ou non? – mattinbits

+0

@mattinbits pour le moment je ne suis même pas sûr de savoir comment le faire fonctionner. Cela semble être une fonctionnalité fusionnée de 'FSM' et' PersistentActor' sans un exemple complet. De la documentation: "PersistentFSM gère les messages entrants d'une manière FSM.L'état interne est persisté comme une séquence de changements, plus tard appelés événements de domaine." - ceci suggère une approche différente de la méthode habituelle 'persist' qui est maintenant même obsolète. – Caballero

Répondre

3

PersistentFSM maintenant implicitement persiste à la fois les changements d'état et les événements de domaine que le produit EFM.

Bien que la documentation que vous lien vers MANQUE, il est possible de voir dans le code que persistAll devient appelé sous le capot à l'endroit approprié: https://github.com/akka/akka/blob/v2.4.0/akka-persistence/src/main/scala/akka/persistence/fsm/PersistentFSM.scala#L110

vous suggère de tester la mise en œuvre que vous avez à voir si elle persiste en effet.

EDIT:

j'ai pu exécuter votre code, sans changement, et voir le répertoire target/journal se créé. J'ai utilisé le suivant 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" 

Et le application.conf suivant:

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" 

Je pense que application.conf est la manière appropriée de préciser l'application spécifique plutôt que conf reference.conf, qui est destiné aux bibliothèques.

+0

Si 'persistAll' est appelé sous le capot alors cela fonctionnerait, n'est-ce pas? Le dossier 'target/journal' n'est même pas créé, ce qui se passe dans un cas classique' PersistentActor' en utilisant la méthode 'persist'. – Caballero

+0

Vous utilisez 'akka.persistence.journal.inmem' qui, comme son nom l'indique, est un journal en mémoire uniquement. C'est pourquoi j'ai demandé ci-dessus ce que vous aviez fait pour tester si la persistance fonctionnait. Essayez d'utiliser 'akka.persistence.journal.plugin =" akka.persistence.journal.leveldb "' – mattinbits

+0

Merci, je n'ai pas remarqué cela. Je l'ai changé en 'akka.persistence.journal.plugin =" akka.persistence.journal.leveldb "' maintenant, mais aucune différence - toujours pas de dossier de journal créé. – Caballero