2013-10-15 09:01:07 +02:00
/* *
2014-02-02 19:05:45 -06:00
* Copyright ( C ) 2009 - 2014 Typesafe Inc . < http : //www.typesafe.com>
2013-10-15 09:01:07 +02:00
*/
package akka.persistence
import java.lang. { Iterable ⇒ JIterable }
2014-06-26 13:56:01 +02:00
import akka.actor. { AbstractActor , UntypedActor }
2013-10-15 09:01:07 +02:00
import akka.japi. { Procedure , Util }
import akka.persistence.JournalProtocol._
2014-06-24 16:57:33 +02:00
import scala.collection.immutable
2013-10-15 09:01:07 +02:00
/* *
* INTERNAL API .
*
* Event sourcing mixin for a [ [ Processor ] ] .
*/
2014-06-26 13:56:01 +02:00
private [ persistence ] trait Eventsourced extends ProcessorImpl {
2014-05-21 01:35:21 +02:00
// TODO consolidate these traits as PersistentActor #15230
2013-10-27 08:01:14 +01:00
/* *
* Processor recovery state . Waits for recovery completion and then changes to
* `processingCommands`
*/
private val recovering : State = new State {
2014-03-19 11:59:16 +01:00
// cache the recoveryBehavior since it's a def for binary compatibility in 2.3.x
private val _recoveryBehavior : Receive = recoveryBehavior
2013-11-20 13:47:42 +01:00
override def toString : String = "recovering"
2013-10-27 08:01:14 +01:00
def aroundReceive ( receive : Receive , message : Any ) {
2014-03-19 11:59:16 +01:00
// Since we are recovering we can ignore the receive behavior from the stack
Eventsourced . super . aroundReceive ( _recoveryBehavior , message )
2013-10-27 08:01:14 +01:00
message match {
2014-01-17 06:58:25 +01:00
case _ : ReadHighestSequenceNrSuccess | _ : ReadHighestSequenceNrFailure ⇒
currentState = processingCommands
case _ ⇒
2013-10-27 08:01:14 +01:00
}
}
}
2013-10-15 09:01:07 +02:00
/* *
* Command processing state . If event persistence is pending after processing a
* command , event persistence is triggered and state changes to `persistingEvents` .
2013-10-27 08:01:14 +01:00
*
* There 's no need to loop commands though the journal any more i . e . they can now be
* directly offered as `LoopSuccess` to the state machine implemented by `Processor` .
2013-10-15 09:01:07 +02:00
*/
private val processingCommands : State = new State {
2013-11-20 13:47:42 +01:00
override def toString : String = "processing commands"
2014-04-03 11:29:01 +02:00
def aroundReceive ( receive : Receive , message : Any ) = message match {
case _ : ConfirmablePersistent ⇒
doAroundReceive ( receive , message )
case PersistentBatch ( b ) ⇒
throw new UnsupportedOperationException ( "Persistent command batches not supported" )
case _ : PersistentRepr ⇒
throw new UnsupportedOperationException ( "Persistent commands not supported" )
2014-06-03 16:40:44 +02:00
case WriteMessageSuccess ( r ) ⇒
r match {
case p : PersistentRepr ⇒
withCurrentPersistent ( p ) ( p ⇒ pendingInvocations . peek ( ) . handler ( p . payload ) )
case _ ⇒ pendingInvocations . peek ( ) . handler ( r . payload )
}
onWriteComplete ( )
case LoopMessageSuccess ( l ) ⇒
pendingInvocations . peek ( ) . handler ( l )
2014-05-21 01:35:21 +02:00
onWriteComplete ( )
case s @ WriteMessagesSuccessful ⇒ Eventsourced . super . aroundReceive ( receive , s )
case f : WriteMessagesFailed ⇒ Eventsourced . super . aroundReceive ( receive , f )
2014-04-03 11:29:01 +02:00
case _ ⇒
doAroundReceive ( receive , message )
}
private def doAroundReceive ( receive : Receive , message : Any ) : Unit = {
2014-01-17 06:58:25 +01:00
Eventsourced . super . aroundReceive ( receive , LoopMessageSuccess ( message ) )
2014-05-21 01:35:21 +02:00
if ( pendingStashingPersistInvocations > 0 ) {
2013-10-27 08:01:14 +01:00
currentState = persistingEvents
2014-05-21 01:35:21 +02:00
}
2014-06-03 16:40:44 +02:00
if ( resequenceableEventBatch . nonEmpty ) flushBatch ( )
else processorStash . unstash ( )
2013-10-15 09:01:07 +02:00
}
2014-04-03 11:29:01 +02:00
2014-05-21 01:35:21 +02:00
private def onWriteComplete ( ) : Unit = {
2014-06-03 16:40:44 +02:00
pendingInvocations . pop ( )
2014-05-21 01:35:21 +02:00
}
2013-10-15 09:01:07 +02:00
}
/* *
* Event persisting state . Remains until pending events are persisted and then changes
* state to `processingCommands` . Only events to be persisted are processed . All other
* messages are stashed internally .
*/
private val persistingEvents : State = new State {
2013-11-20 13:47:42 +01:00
override def toString : String = "persisting events"
2014-06-03 16:40:44 +02:00
def aroundReceive ( receive : Receive , message : Any ) : Unit = message match {
2014-04-03 11:29:01 +02:00
case _ : ConfirmablePersistent ⇒
2014-03-24 11:21:21 +01:00
processorStash . stash ( )
2013-11-20 13:47:42 +01:00
case PersistentBatch ( b ) ⇒
2014-06-03 16:40:44 +02:00
b foreach {
case p : PersistentRepr ⇒ deleteMessage ( p . sequenceNr , permanent = true )
case r ⇒ // ignore, nothing to delete (was not a persistent message)
}
2013-10-27 08:01:14 +01:00
throw new UnsupportedOperationException ( "Persistent command batches not supported" )
2013-11-20 13:47:42 +01:00
case p : PersistentRepr ⇒
2014-05-21 01:35:21 +02:00
deleteMessage ( p . sequenceNr , permanent = true )
2013-10-27 08:01:14 +01:00
throw new UnsupportedOperationException ( "Persistent commands not supported" )
2014-06-03 16:40:44 +02:00
case WriteMessageSuccess ( m ) ⇒
m match {
case p : PersistentRepr ⇒ withCurrentPersistent ( p ) ( p ⇒ pendingInvocations . peek ( ) . handler ( p . payload ) )
case _ ⇒ pendingInvocations . peek ( ) . handler ( m . payload )
}
onWriteComplete ( )
2014-01-17 06:58:25 +01:00
case e @ WriteMessageFailure ( p , _ ) ⇒
2013-10-15 09:01:07 +02:00
Eventsourced . super . aroundReceive ( receive , message ) // stops actor by default
2014-06-03 16:40:44 +02:00
onWriteComplete ( )
case LoopMessageSuccess ( l ) ⇒
pendingInvocations . peek ( ) . handler ( l )
onWriteComplete ( )
2014-05-21 01:35:21 +02:00
case s @ WriteMessagesSuccessful ⇒ Eventsourced . super . aroundReceive ( receive , s )
case f : WriteMessagesFailed ⇒ Eventsourced . super . aroundReceive ( receive , f )
case other ⇒ processorStash . stash ( )
2013-10-15 09:01:07 +02:00
}
2014-06-03 16:40:44 +02:00
private def onWriteComplete ( ) : Unit = {
pendingInvocations . pop ( ) match {
case _ : StashingHandlerInvocation ⇒
// enables an early return to `processingCommands`, because if this counter hits `0`,
// we know the remaining pendingInvocations are all `persistAsync` created, which
// means we can go back to processing commands also - and these callbacks will be called as soon as possible
pendingStashingPersistInvocations -= 1
case _ ⇒ // do nothing
2014-05-21 01:35:21 +02:00
}
2014-06-03 16:40:44 +02:00
if ( pendingStashingPersistInvocations == 0 ) {
2013-10-15 09:01:07 +02:00
currentState = processingCommands
2013-10-27 08:01:14 +01:00
processorStash . unstash ( )
2013-10-15 09:01:07 +02:00
}
}
2014-05-21 01:35:21 +02:00
2013-10-15 09:01:07 +02:00
}
2014-03-19 11:59:16 +01:00
/* *
* INTERNAL API .
*
* This is a def and not a val because of binary compatibility in 2.3 . x .
* It is cached where it is used .
*/
private def recoveryBehavior : Receive = {
case Persistent ( payload , _ ) if recoveryRunning && receiveRecover . isDefinedAt ( payload ) ⇒
receiveRecover ( payload )
case s : SnapshotOffer if receiveRecover . isDefinedAt ( s ) ⇒
receiveRecover ( s )
case f : RecoveryFailure if receiveRecover . isDefinedAt ( f ) ⇒
receiveRecover ( f )
2014-06-05 14:07:17 +02:00
case RecoveryCompleted if receiveRecover . isDefinedAt ( RecoveryCompleted ) ⇒
receiveRecover ( RecoveryCompleted )
2014-03-19 11:59:16 +01:00
}
2014-06-03 16:40:44 +02:00
sealed trait PendingHandlerInvocation {
def evt : Any
2014-05-21 01:35:21 +02:00
def handler : Any ⇒ Unit
}
/* * forces processor to stash incoming commands untill all these invocations are handled */
2014-06-03 16:40:44 +02:00
final case class StashingHandlerInvocation ( evt : Any , handler : Any ⇒ Unit ) extends PendingHandlerInvocation
/* * does not force the processor to stash commands; Originates from either `persistAsync` or `defer` calls */
final case class AsyncHandlerInvocation ( evt : Any , handler : Any ⇒ Unit ) extends PendingHandlerInvocation
2014-05-21 01:35:21 +02:00
2014-06-03 16:40:44 +02:00
/* * Used instead of iterating `pendingInvocations` in order to check if safe to revert to processing commands */
2014-05-21 01:35:21 +02:00
private var pendingStashingPersistInvocations : Long = 0
/* * Holds user-supplied callbacks for persist / persistAsync calls */
2014-06-03 16:40:44 +02:00
private val pendingInvocations = new java . util . LinkedList [ PendingHandlerInvocation ] ( ) // we only append / isEmpty / get(0) on it
private var resequenceableEventBatch : List [ Resequenceable ] = Nil
2013-10-15 09:01:07 +02:00
2013-10-27 08:01:14 +01:00
private var currentState : State = recovering
2013-11-07 10:45:02 +01:00
private val processorStash = createStash ( )
2013-10-15 09:01:07 +02:00
2014-06-03 16:40:44 +02:00
private def flushBatch ( ) {
Eventsourced . super . aroundReceive ( receive , PersistentBatch ( resequenceableEventBatch . reverse ) )
resequenceableEventBatch = Nil
}
2013-10-15 09:01:07 +02:00
/* *
* Asynchronously persists `event` . On successful persistence , `handler` is called with the
* persisted event . It is guaranteed that no new commands will be received by a processor
* between a call to `persist` and the execution of its `handler` . This also holds for
* multiple `persist` calls per received command . Internally , this is achieved by stashing new
* commands and unstashing them when the `event` has been persisted and handled . The stash used
* for that is an internal stash which doesn 't interfere with the user stash inherited from
* [ [ Processor ] ] .
*
* An event `handler` may close over processor state and modify it . The `sender` of a persisted
* event is the sender of the corresponding command . This means that one can reply to a command
* sender within an event `handler` .
*
* Within an event handler , applications usually update processor state using persisted event
* data , notify listeners and reply to command senders .
*
* If persistence of an event fails , the processor will be stopped . This can be customized by
* handling [ [ PersistenceFailure ] ] in [ [ receiveCommand ] ] .
*
2014-05-21 01:35:21 +02:00
* @param event event to be persisted
2013-10-15 09:01:07 +02:00
* @param handler handler for each persisted `event`
*/
final def persist [ A ] ( event : A ) ( handler : A ⇒ Unit ) : Unit = {
2014-05-21 01:35:21 +02:00
pendingStashingPersistInvocations += 1
2014-06-03 16:40:44 +02:00
pendingInvocations addLast StashingHandlerInvocation ( event , handler . asInstanceOf [ Any ⇒ Unit ] )
resequenceableEventBatch = PersistentRepr ( event ) : : resequenceableEventBatch
2013-10-15 09:01:07 +02:00
}
/* *
* Asynchronously persists `events` in specified order . This is equivalent to calling
2013-11-07 10:45:02 +01:00
* `persist[A](event: A)(handler: A => Unit)` multiple times with the same `handler` ,
* except that `events` are persisted atomically with this method .
2013-10-15 09:01:07 +02:00
*
2014-05-21 01:35:21 +02:00
* @param events events to be persisted
2013-10-15 09:01:07 +02:00
* @param handler handler for each persisted `events`
*/
final def persist [ A ] ( events : immutable.Seq [ A ] ) ( handler : A ⇒ Unit ) : Unit =
events . foreach ( persist ( _ ) ( handler ) )
2014-05-21 01:35:21 +02:00
/* *
* Asynchronously persists `event` . On successful persistence , `handler` is called with the
* persisted event .
*
* Unlike `persist` the processor will continue to receive incomming commands between the
* call to `persist` and executing it 's `handler` . This asynchronous , non - stashing , version of
* of persist should be used when you favor throughput over the " command - 2 only processed after
* command - 1 effects ' have been applied " guarantee , which is provided by the plain [ [ persist ] ] method .
*
* An event `handler` may close over processor state and modify it . The `sender` of a persisted
* event is the sender of the corresponding command . This means that one can reply to a command
* sender within an event `handler` .
*
* If persistence of an event fails , the processor will be stopped . This can be customized by
* handling [ [ PersistenceFailure ] ] in [ [ receiveCommand ] ] .
*
* @param event event to be persisted
* @param handler handler for each persisted `event`
*/
final def persistAsync [ A ] ( event : A ) ( handler : A ⇒ Unit ) : Unit = {
2014-06-03 16:40:44 +02:00
pendingInvocations addLast AsyncHandlerInvocation ( event , handler . asInstanceOf [ Any ⇒ Unit ] )
resequenceableEventBatch = PersistentRepr ( event ) : : resequenceableEventBatch
2014-05-21 01:35:21 +02:00
}
/* *
* Asynchronously persists `events` in specified order . This is equivalent to calling
* `persistAsync[A](event: A)(handler: A => Unit)` multiple times with the same `handler` ,
* except that `events` are persisted atomically with this method .
*
* @param events events to be persisted
* @param handler handler for each persisted `events`
*/
final def persistAsync [ A ] ( events : immutable.Seq [ A ] ) ( handler : A ⇒ Unit ) : Unit =
events . foreach ( persistAsync ( _ ) ( handler ) )
2014-06-03 16:40:44 +02:00
/* *
* Defer the handler execution until all pending handlers have been executed .
* Allows to define logic within the actor , which will respect the invocation - order - guarantee
* in respect to `persistAsync` calls . That is , if `persistAsync` was invoked before defer ,
* the corresponding handlers will be invoked in the same order as they were registered in .
*
* This call will NOT result in `event` being persisted , please use `persist` or `persistAsync` ,
* if the given event should possible to replay .
*
* If there are no pending persist handler calls , the handler will be called immediatly .
*
* In the event of persistence failures ( indicated by [ [ PersistenceFailure ] ] messages being sent to the
* [ [ PersistentActor ] ] , you can handle these messages , which in turn will enable the deferred handlers to run afterwards .
* If persistence failure messages are left `unhandled` , the default behavior is to stop the Actor , thus the handlers
* will not be run .
*
* @param event event to be handled in the future , when preceeding persist operations have been processes
* @param handler handler for the given `event`
*/
final def defer [ A ] ( event : A ) ( handler : A ⇒ Unit ) : Unit = {
if ( pendingInvocations . isEmpty ) {
handler ( event )
} else {
pendingInvocations addLast AsyncHandlerInvocation ( event , handler . asInstanceOf [ Any ⇒ Unit ] )
resequenceableEventBatch = NonPersistentRepr ( event , sender ( ) ) : : resequenceableEventBatch
}
}
/* *
* Defer the handler execution until all pending handlers have been executed .
* Allows to define logic within the actor , which will respect the invocation - order - guarantee
* in respect to `persistAsync` calls . That is , if `persistAsync` was invoked before defer ,
* the corresponding handlers will be invoked in the same order as they were registered in .
*
* This call will NOT result in `event` being persisted , please use `persist` or `persistAsync` ,
* if the given event should possible to replay .
*
* If there are no pending persist handler calls , the handler will be called immediatly .
*
* In the event of persistence failures ( indicated by [ [ PersistenceFailure ] ] messages being sent to the
* [ [ PersistentActor ] ] , you can handle these messages , which in turn will enable the deferred handlers to run afterwards .
* If persistence failure messages are left `unhandled` , the default behavior is to stop the Actor , thus the handlers
* will not be run .
*
* @param events event to be handled in the future , when preceeding persist operations have been processes
* @param handler handler for each `event`
*/
final def defer [ A ] ( events : immutable.Seq [ A ] ) ( handler : A ⇒ Unit ) : Unit =
events . foreach ( defer ( _ ) ( handler ) )
2013-10-15 09:01:07 +02:00
/* *
2014-01-19 17:46:32 +01:00
* Recovery handler that receives persisted events during recovery . If a state snapshot
2013-10-15 09:01:07 +02:00
* has been captured and saved , this handler will receive a [ [ SnapshotOffer ] ] message
* followed by events that are younger than the offered snapshot .
*
* This handler must not have side - effects other than changing processor state i . e . it
* should not perform actions that may fail , such as interacting with external services ,
* for example .
*
2014-06-05 14:07:17 +02:00
* If recovery fails , the actor will be stopped . This can be customized by
* handling [ [ RecoveryFailure ] ] .
*
2013-10-15 09:01:07 +02:00
* @see [ [ Recover ] ]
*/
2014-01-19 17:46:32 +01:00
def receiveRecover : Receive
2013-10-15 09:01:07 +02:00
/* *
* Command handler . Typically validates commands against current state ( and / or by
* communication with other actors ) . On successful validation , one or more events are
* derived from a command and these events are then persisted by calling `persist` .
* Commands sent to event sourced processors should not be [ [ Persistent ] ] messages .
*/
def receiveCommand : Receive
2013-10-27 08:01:14 +01:00
override def unstashAll ( ) {
// Internally, all messages are processed by unstashing them from
// the internal stash one-by-one. Hence, an unstashAll() from the
// user stash must be prepended to the internal stash.
processorStash . prepend ( clearStash ( ) )
}
2013-10-15 09:01:07 +02:00
/* *
* INTERNAL API .
*/
final override protected [ akka ] def aroundReceive ( receive : Receive , message : Any ) {
currentState . aroundReceive ( receive , message )
}
2013-10-27 08:01:14 +01:00
/* *
* Calls `super.preRestart` then unstashes all messages from the internal stash .
*/
override def preRestart ( reason : Throwable , message : Option [ Any ] ) {
processorStash . unstashAll ( )
2013-11-20 13:47:42 +01:00
super . preRestart ( reason , message )
2013-10-27 08:01:14 +01:00
}
/* *
* Calls `super.postStop` then unstashes all messages from the internal stash .
*/
override def postStop ( ) {
processorStash . unstashAll ( )
2013-11-20 13:47:42 +01:00
super . postStop ( )
2013-10-27 08:01:14 +01:00
}
2013-10-15 09:01:07 +02:00
/* *
* INTERNAL API .
2014-03-19 11:59:16 +01:00
*
* Only here for binary compatibility in 2.3 . x .
2013-10-15 09:01:07 +02:00
*/
2014-03-19 11:59:16 +01:00
protected [ persistence ] val initialBehavior : Receive = recoveryBehavior orElse {
2013-10-15 09:01:07 +02:00
case msg if receiveCommand . isDefinedAt ( msg ) ⇒
receiveCommand ( msg )
}
}
/* *
* An event sourced processor .
*/
2014-05-21 01:35:21 +02:00
@deprecated ( "EventsourcedProcessor will be removed in 2.4.x, instead extend the API equivalent `akka.persistence.PersistentProcessor`" , since = "2.3.4" )
2013-10-15 09:01:07 +02:00
trait EventsourcedProcessor extends Processor with Eventsourced {
2014-05-21 01:35:21 +02:00
// TODO remove Processor #15230
2014-03-20 12:05:32 +01:00
def receive = receiveCommand
2013-10-15 09:01:07 +02:00
}
2014-05-21 01:35:21 +02:00
/* *
* An persistent Actor - can be used to implement command or event sourcing .
*/
2014-06-26 13:56:01 +02:00
trait PersistentActor extends ProcessorImpl with Eventsourced {
def receive = receiveCommand
}
2014-05-21 01:35:21 +02:00
/* *
* Java API : an persistent actor - can be used to implement command or event sourcing .
*/
2014-06-26 13:56:01 +02:00
abstract class UntypedPersistentActor extends UntypedActor with ProcessorImpl with Eventsourced {
2014-05-21 01:35:21 +02:00
2014-03-19 11:59:16 +01:00
final def onReceive ( message : Any ) = onReceiveCommand ( message )
2013-10-15 09:01:07 +02:00
2014-01-19 17:46:32 +01:00
final def receiveRecover : Receive = {
case msg ⇒ onReceiveRecover ( msg )
2013-10-15 09:01:07 +02:00
}
final def receiveCommand : Receive = {
case msg ⇒ onReceiveCommand ( msg )
}
/* *
2013-11-07 10:45:02 +01:00
* Java API : asynchronously persists `event` . On successful persistence , `handler` is called with the
2013-10-15 09:01:07 +02:00
* persisted event . It is guaranteed that no new commands will be received by a processor
* between a call to `persist` and the execution of its `handler` . This also holds for
* multiple `persist` calls per received command . Internally , this is achieved by stashing new
* commands and unstashing them when the `event` has been persisted and handled . The stash used
* for that is an internal stash which doesn 't interfere with the user stash inherited from
* [ [ UntypedProcessor ] ] .
*
* An event `handler` may close over processor state and modify it . The `getSender()` of a persisted
* event is the sender of the corresponding command . This means that one can reply to a command
* sender within an event `handler` .
*
* Within an event handler , applications usually update processor state using persisted event
* data , notify listeners and reply to command senders .
*
* If persistence of an event fails , the processor will be stopped . This can be customized by
* handling [ [ PersistenceFailure ] ] in [ [ onReceiveCommand ] ] .
*
* @param event event to be persisted .
* @param handler handler for each persisted `event`
*/
final def persist [ A ] ( event : A , handler : Procedure [ A ] ) : Unit =
persist ( event ) ( event ⇒ handler ( event ) )
/* *
2013-11-07 10:45:02 +01:00
* Java API : asynchronously persists `events` in specified order . This is equivalent to calling
* `persist[A](event: A, handler: Procedure[A])` multiple times with the same `handler` ,
* except that `events` are persisted atomically with this method .
2013-10-15 09:01:07 +02:00
*
* @param events events to be persisted .
* @param handler handler for each persisted `events`
*/
final def persist [ A ] ( events : JIterable [ A ] , handler : Procedure [ A ] ) : Unit =
persist ( Util . immutableSeq ( events ) ) ( event ⇒ handler ( event ) )
2014-05-21 01:35:21 +02:00
/* *
* JAVA API : asynchronously persists `event` . On successful persistence , `handler` is called with the
* persisted event .
*
* Unlike `persist` the processor will continue to receive incomming commands between the
* call to `persist` and executing it 's `handler` . This asynchronous , non - stashing , version of
* of persist should be used when you favor throughput over the " command - 2 only processed after
* command - 1 effects ' have been applied " guarantee , which is provided by the plain [ [ persist ] ] method .
*
* An event `handler` may close over processor state and modify it . The `sender` of a persisted
* event is the sender of the corresponding command . This means that one can reply to a command
* sender within an event `handler` .
*
* If persistence of an event fails , the processor will be stopped . This can be customized by
* handling [ [ PersistenceFailure ] ] in [ [ receiveCommand ] ] .
*
* @param event event to be persisted
* @param handler handler for each persisted `event`
*/
final def persistAsync [ A ] ( event : A ) ( handler : Procedure [ A ] ) : Unit =
super [ Eventsourced ] . persistAsync ( event ) ( event ⇒ handler ( event ) )
/* *
* JAVA API : asynchronously persists `events` in specified order . This is equivalent to calling
* `persistAsync[A](event: A)(handler: A => Unit)` multiple times with the same `handler` ,
* except that `events` are persisted atomically with this method .
*
* @param events events to be persisted
* @param handler handler for each persisted `events`
*/
final def persistAsync [ A ] ( events : JIterable [ A ] ) ( handler : A ⇒ Unit ) : Unit =
super [ Eventsourced ] . persistAsync ( Util . immutableSeq ( events ) ) ( event ⇒ handler ( event ) )
2014-06-03 16:40:44 +02:00
/* *
* Defer the handler execution until all pending handlers have been executed .
* Allows to define logic within the actor , which will respect the invocation - order - guarantee
* in respect to `persistAsync` calls . That is , if `persistAsync` was invoked before defer ,
* the corresponding handlers will be invoked in the same order as they were registered in .
*
* This call will NOT result in `event` being persisted , please use `persist` or `persistAsync` ,
* if the given event should possible to replay .
*
* If there are no pending persist handler calls , the handler will be called immediatly .
*
* In the event of persistence failures ( indicated by [ [ PersistenceFailure ] ] messages being sent to the
* [ [ PersistentActor ] ] , you can handle these messages , which in turn will enable the deferred handlers to run afterwards .
* If persistence failure messages are left `unhandled` , the default behavior is to stop the Actor , thus the handlers
* will not be run .
*
* @param event event to be handled in the future , when preceeding persist operations have been processes
* @param handler handler for the given `event`
*/
final def defer [ A ] ( event : A ) ( handler : Procedure [ A ] ) : Unit =
super [ Eventsourced ] . defer ( event ) ( event ⇒ handler ( event ) )
/* *
* Defer the handler execution until all pending handlers have been executed .
* Allows to define logic within the actor , which will respect the invocation - order - guarantee
* in respect to `persistAsync` calls . That is , if `persistAsync` was invoked before defer ,
* the corresponding handlers will be invoked in the same order as they were registered in .
*
* This call will NOT result in `event` being persisted , please use `persist` or `persistAsync` ,
* if the given event should possible to replay .
*
* If there are no pending persist handler calls , the handler will be called immediatly .
*
* In the event of persistence failures ( indicated by [ [ PersistenceFailure ] ] messages being sent to the
* [ [ PersistentActor ] ] , you can handle these messages , which in turn will enable the deferred handlers to run afterwards .
* If persistence failure messages are left `unhandled` , the default behavior is to stop the Actor , thus the handlers
* will not be run .
*
* @param events event to be handled in the future , when preceeding persist operations have been processes
* @param handler handler for each `event`
*/
final def defer [ A ] ( events : JIterable [ A ] ) ( handler : Procedure [ A ] ) : Unit =
super [ Eventsourced ] . defer ( Util . immutableSeq ( events ) ) ( event ⇒ handler ( event ) )
2013-10-15 09:01:07 +02:00
/* *
2014-01-19 17:46:32 +01:00
* Java API : recovery handler that receives persisted events during recovery . If a state snapshot
2013-10-15 09:01:07 +02:00
* has been captured and saved , this handler will receive a [ [ SnapshotOffer ] ] message
* followed by events that are younger than the offered snapshot .
*
* This handler must not have side - effects other than changing processor state i . e . it
* should not perform actions that may fail , such as interacting with external services ,
* for example .
*
2014-06-05 14:07:17 +02:00
* If recovery fails , the actor will be stopped . This can be customized by
* handling [ [ RecoveryFailure ] ] .
*
2013-10-15 09:01:07 +02:00
* @see [ [ Recover ] ]
*/
2014-06-25 12:51:21 +02:00
@throws ( classOf [ Exception ] )
2014-01-19 17:46:32 +01:00
def onReceiveRecover ( msg : Any ) : Unit
2013-10-15 09:01:07 +02:00
/* *
2013-11-07 10:45:02 +01:00
* Java API : command handler . Typically validates commands against current state ( and / or by
2013-10-15 09:01:07 +02:00
* communication with other actors ) . On successful validation , one or more events are
* derived from a command and these events are then persisted by calling `persist` .
2013-10-27 08:01:14 +01:00
* Commands sent to event sourced processors must not be [ [ Persistent ] ] or
2014-06-24 16:57:33 +02:00
* [ [ PersistentBatch ] ] messages . In this case an `UnsupportedOperationException` is
2013-10-27 08:01:14 +01:00
* thrown by the processor .
2013-10-15 09:01:07 +02:00
*/
2014-06-25 12:51:21 +02:00
@throws ( classOf [ Exception ] )
2013-10-15 09:01:07 +02:00
def onReceiveCommand ( msg : Any ) : Unit
2013-11-07 10:45:02 +01:00
}
2014-02-15 23:44:00 -05:00
/* *
2014-06-26 13:56:01 +02:00
* Java API : an persistent actor - can be used to implement command or event sourcing .
2014-02-15 23:44:00 -05:00
*/
2014-06-26 13:56:01 +02:00
abstract class AbstractPersistentActor extends AbstractActor with PersistentActor with Eventsourced {
2014-02-15 23:44:00 -05:00
/* *
* Java API : asynchronously persists `event` . On successful persistence , `handler` is called with the
* persisted event . It is guaranteed that no new commands will be received by a processor
* between a call to `persist` and the execution of its `handler` . This also holds for
* multiple `persist` calls per received command . Internally , this is achieved by stashing new
* commands and unstashing them when the `event` has been persisted and handled . The stash used
* for that is an internal stash which doesn 't interfere with the user stash inherited from
* [ [ UntypedProcessor ] ] .
*
* An event `handler` may close over processor state and modify it . The `getSender()` of a persisted
* event is the sender of the corresponding command . This means that one can reply to a command
* sender within an event `handler` .
*
* Within an event handler , applications usually update processor state using persisted event
* data , notify listeners and reply to command senders .
*
* If persistence of an event fails , the processor will be stopped . This can be customized by
* handling [ [ PersistenceFailure ] ] in [ [ receiveCommand ] ] .
*
* @param event event to be persisted .
* @param handler handler for each persisted `event`
*/
final def persist [ A ] ( event : A , handler : Procedure [ A ] ) : Unit =
persist ( event ) ( event ⇒ handler ( event ) )
/* *
* Java API : asynchronously persists `events` in specified order . This is equivalent to calling
* `persist[A](event: A, handler: Procedure[A])` multiple times with the same `handler` ,
* except that `events` are persisted atomically with this method .
*
* @param events events to be persisted .
* @param handler handler for each persisted `events`
*/
final def persist [ A ] ( events : JIterable [ A ] , handler : Procedure [ A ] ) : Unit =
persist ( Util . immutableSeq ( events ) ) ( event ⇒ handler ( event ) )
2014-03-20 12:05:32 +01:00
2014-05-21 01:35:21 +02:00
/* *
* Java API : asynchronously persists `event` . On successful persistence , `handler` is called with the
* persisted event .
*
* Unlike `persist` the processor will continue to receive incomming commands between the
* call to `persistAsync` and executing it 's `handler` . This asynchronous , non - stashing , version of
* of persist should be used when you favor throughput over the strict ordering guarantees that `persist` guarantees .
*
* If persistence of an event fails , the processor will be stopped . This can be customized by
* handling [ [ PersistenceFailure ] ] in [ [ receiveCommand ] ] .
*
* @param event event to be persisted
* @param handler handler for each persisted `event`
*/
final def persistAsync [ A ] ( event : A , handler : Procedure [ A ] ) : Unit =
persistAsync ( event ) ( event ⇒ handler ( event ) )
2014-06-03 16:40:44 +02:00
/* *
* Defer the handler execution until all pending handlers have been executed .
* Allows to define logic within the actor , which will respect the invocation - order - guarantee
* in respect to `persistAsync` calls . That is , if `persistAsync` was invoked before defer ,
* the corresponding handlers will be invoked in the same order as they were registered in .
*
* This call will NOT result in `event` being persisted , please use `persist` or `persistAsync` ,
* if the given event should possible to replay .
*
* If there are no pending persist handler calls , the handler will be called immediatly .
*
* In the event of persistence failures ( indicated by [ [ PersistenceFailure ] ] messages being sent to the
* [ [ PersistentActor ] ] , you can handle these messages , which in turn will enable the deferred handlers to run afterwards .
* If persistence failure messages are left `unhandled` , the default behavior is to stop the Actor , thus the handlers
* will not be run .
*
* @param event event to be handled in the future , when preceeding persist operations have been processes
* @param handler handler for the given `event`
*/
final def defer [ A ] ( event : A ) ( handler : Procedure [ A ] ) : Unit =
super . defer ( event ) ( event ⇒ handler ( event ) )
/* *
* Defer the handler execution until all pending handlers have been executed .
* Allows to define logic within the actor , which will respect the invocation - order - guarantee
* in respect to `persistAsync` calls . That is , if `persistAsync` was invoked before defer ,
* the corresponding handlers will be invoked in the same order as they were registered in .
*
* This call will NOT result in `event` being persisted , please use `persist` or `persistAsync` ,
* if the given event should possible to replay .
*
* If there are no pending persist handler calls , the handler will be called immediatly .
*
* In the event of persistence failures ( indicated by [ [ PersistenceFailure ] ] messages being sent to the
* [ [ PersistentActor ] ] , you can handle these messages , which in turn will enable the deferred handlers to run afterwards .
* If persistence failure messages are left `unhandled` , the default behavior is to stop the Actor , thus the handlers
* will not be run .
*
* @param events event to be handled in the future , when preceeding persist operations have been processes
* @param handler handler for each `event`
*/
final def defer [ A ] ( events : JIterable [ A ] ) ( handler : Procedure [ A ] ) : Unit =
super . defer ( Util . immutableSeq ( events ) ) ( event ⇒ handler ( event ) )
2014-05-21 01:35:21 +02:00
/* *
* Java API : asynchronously persists `events` in specified order . This is equivalent to calling
* `persistAsync[A](event: A)(handler: A => Unit)` multiple times with the same `handler` ,
* except that `events` are persisted atomically with this method .
*
* @param events events to be persisted
* @param handler handler for each persisted `events`
*/
final def persistAsync [ A ] ( events : JIterable [ A ] , handler : Procedure [ A ] ) : Unit =
persistAsync ( Util . immutableSeq ( events ) ) ( event ⇒ handler ( event ) )
2014-06-26 13:56:01 +02:00
override def receive = super [ PersistentActor ] . receive
2014-03-20 12:05:32 +01:00
2014-05-21 01:35:21 +02:00
}
2014-06-26 13:56:01 +02:00
/* *
* Java API : an event sourced processor .
*/
@deprecated ( "UntypedEventsourcedProcessor will be removed in 2.4.x, instead extend the API equivalent `akka.persistence.PersistentProcessor`" , since = "2.3.4" )
abstract class UntypedEventsourcedProcessor extends UntypedPersistentActor {
override def persistenceId : String = processorId
}
/* *
* Java API : compatible with lambda expressions ( to be used with [ [ akka . japi . pf . ReceiveBuilder ] ] ) :
* command handler . Typically validates commands against current state ( and / or by
* communication with other actors ) . On successful validation , one or more events are
* derived from a command and these events are then persisted by calling `persist` .
* Commands sent to event sourced processors must not be [ [ Persistent ] ] or
* [ [ PersistentBatch ] ] messages . In this case an `UnsupportedOperationException` is
* thrown by the processor .
*/
@deprecated ( "AbstractEventsourcedProcessor will be removed in 2.4.x, instead extend the API equivalent `akka.persistence.PersistentProcessor`" , since = "2.3.4" )
abstract class AbstractEventsourcedProcessor extends AbstractPersistentActor {
override def persistenceId : String = processorId
}