2016-03-30 5 views
1

Вот код:Почему этот настойчивый актер не работает

import akka.persistence._ 
import akka.actor.{Actor, ActorRef, ActorSystem, Props, ActorLogging} 


class Counter extends PersistentActor with ActorLogging { 

    import Counter._ 

    var state: State = new State(0) 

    override def receiveRecover: Receive = { 
    case RecoveryCompleted => println("Recovery completed.") 
    case SnapshotOffer(_, snapshot: State) => state = snapshot 
    case op: Operation => updateState(op) 
    } 


    override def persistenceId: String = "counter-persistent" 

    override def receiveCommand: Receive = { 
    case op: Operation => 
     println(s"Counter receive ${op}") 
     persist(op) { 
     op => updateState(op) 
     } 
    case "print" => println(s"The current state of couter is ${state}") 
    case SaveSnapshotFailure(_, reason) => println(s"save snapshot failed, reason: ${reason}") 
    case SaveSnapshotSuccess(_) => println(s"snapshot saved") 
    } 

    def updateState(op: Operation): Unit = op match { 
    case Increment(n) => 
     state = state.inc(n) 
     takeSnapshot 
    case Decrement(n) => 
     state = state.dec(n) 
     takeSnapshot 
    } 

    def takeSnapshot: Unit = { 
    // if (state % 5 == 0) saveSnapshot() 
    saveSnapshot() 
    } 
} 


object Counter { 

    sealed trait Operation { 
    val count: Int 
    } 

    case class Increment(override val count: Int) extends Operation 

    case class Decrement(override val count: Int) extends Operation 

    final case class State(n: Int) { 
    def inc(x: Int) = State(n + x) 

    def dec(x: Int) = State(n - x) 
    } 

} 







object Persistent extends App { 

    import Counter._ 

    val system = ActorSystem("persistent-actors") 

    val counter = system.actorOf(Props[Counter]) 

    counter ! Increment(3) 
    counter ! Increment(5) 
    counter ! Decrement(3) 
    counter ! "print" 

    Thread.sleep(1000) 

    system.terminate() 

} 

Configuration (application.conf):

akka { 
    persistence { 
    journal { 
     plugin = "akka.persistence.journal.leveldb", 
     leveldb { 
     dir = "target/example/journal", 
     native = false 
     } 
    }, 
    snapshot-store { 
     plugin = "akka.persistence.snapshot-store.local", 
     local { 
     dir = "target/example/snapshots" 
     } 
    } 
    } 
} 

Запуск приложения дважды показывает, что состояние не является постоянным на всех:

Recovery completed. 
Counter receive Increment(3) 
Counter receive Increment(5) 
Counter receive Decrement(3) 
The current state of couter is State(5) 
snapshot saved 
snapshot saved 
snapshot saved 

Recovery completed. 
Counter receive Increment(3) 
Counter receive Increment(5) 
Counter receive Decrement(3) 
The current state of couter is State(5) 
snapshot saved 
snapshot saved 
snapshot saved 

Почему?

+0

Вы настроили плагин persistence? Какой журнал вы используете? – manub

+0

В чем проблема, с которой вы сталкиваетесь, что не работает. Пожалуйста, предоставьте дополнительную информацию об этом. – curious

+0

Конфигурация @manub теперь отправлена. – qed

ответ

3

Проблема заключается в том, что вы делаете снимок после каждого операционного сообщения, которое получает актер, но при съемке моментального снимка вы не сохраняете его состояние. Если вы внимательно посмотрите на вас takeSnapshot код:

def takeSnapshot: Unit = { 
    // if (state % 5 == 0) saveSnapshot() 
    saveSnapshot() 
    } 

вызов saveSnapshot() не принимает снимок вашего состояния, поскольку нет ни одного аргумента ей передается.

вам нужно изменить вам takeSnapshot метод немного напоминает это:

def takeSnapshot: Unit = { 
    // if (state % 5 == 0) saveSnapshot() 
    saveSnapshot(state) // Pass the states you need to store while taking a snapshot. 
    } 

Это будет работать.