=per #15937 Allow PersistentActor to be used as a stackable modification

* PersistentActor correctly calls `super.around*` and allows to be mixed into e.g. ActorSubscriber
 * Tests have been added on PersistentActor and Processor to verify the stackable behavior of `around*` and `pre*` methods
 * Delegation in Processor has been simplified
This commit is contained in:
Michał Węgrzyn 2014-10-22 22:12:22 +02:00
parent ad35be7de1
commit 4f52158b0a
4 changed files with 246 additions and 28 deletions

View file

@ -13,6 +13,7 @@ import akka.testkit.EventFilter
import akka.testkit.TestProbe
import java.util.concurrent.atomic.AtomicInteger
import scala.util.Random
import scala.util.control.NoStackTrace
object PersistentActorSpec {
final case class Cmd(data: Any)
@ -403,6 +404,95 @@ object PersistentActorSpec {
}
}
class StackableTestPersistentActor(val probe: ActorRef) extends StackableTestPersistentActor.BaseActor with PersistentActor with StackableTestPersistentActor.MixinActor {
override def persistenceId: String = "StackableTestPersistentActor"
def receiveCommand = {
case "restart" throw new Exception("triggering restart") with NoStackTrace { override def toString = "Boom!" }
}
def receiveRecover = {
case _ ()
}
override def preStart(): Unit = {
probe ! "preStart"
super.preStart()
}
override def postStop(): Unit = {
probe ! "postStop"
super.postStop()
}
override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
probe ! "preRestart"
super.preRestart(reason, message)
}
override def postRestart(reason: Throwable): Unit = {
probe ! "postRestart"
super.postRestart(reason)
}
}
object StackableTestPersistentActor {
trait BaseActor extends Actor { this: StackableTestPersistentActor
override protected[akka] def aroundPreStart() = {
probe ! "base aroundPreStart"
super.aroundPreStart()
}
override protected[akka] def aroundPostStop() = {
probe ! "base aroundPostStop"
super.aroundPostStop()
}
override protected[akka] def aroundPreRestart(reason: Throwable, message: Option[Any]) = {
probe ! "base aroundPreRestart"
super.aroundPreRestart(reason, message)
}
override protected[akka] def aroundPostRestart(reason: Throwable) = {
probe ! "base aroundPostRestart"
super.aroundPostRestart(reason)
}
override protected[akka] def aroundReceive(receive: Receive, message: Any) = {
probe ! "base aroundReceive"
super.aroundReceive(receive, message)
}
}
trait MixinActor extends Actor { this: StackableTestPersistentActor
override protected[akka] def aroundPreStart() = {
probe ! "mixin aroundPreStart"
super.aroundPreStart()
}
override protected[akka] def aroundPostStop() = {
probe ! "mixin aroundPostStop"
super.aroundPostStop()
}
override protected[akka] def aroundPreRestart(reason: Throwable, message: Option[Any]) = {
probe ! "mixin aroundPreRestart"
super.aroundPreRestart(reason, message)
}
override protected[akka] def aroundPostRestart(reason: Throwable) = {
probe ! "mixin aroundPostRestart"
super.aroundPostRestart(reason)
}
override protected[akka] def aroundReceive(receive: Receive, message: Any) = {
if (message == "restart" && recoveryFinished) { probe ! "mixin aroundReceive" }
super.aroundReceive(receive, message)
}
}
}
}
abstract class PersistentActorSpec(config: Config) extends AkkaSpec(config) with PersistenceSpec with ImplicitSender {
@ -770,7 +860,35 @@ abstract class PersistentActorSpec(config: Config) extends AkkaSpec(config) with
processor2 ! GetState
expectMsg(List("a-1", "a-2", "b-41", "b-42", "c-41", "c-42", RecoveryCompleted))
}
"be used as a stackable modification" in {
val persistentActor = system.actorOf(Props(classOf[StackableTestPersistentActor], testActor))
expectMsg("mixin aroundPreStart")
expectMsg("base aroundPreStart")
expectMsg("preStart")
persistentActor ! "restart"
expectMsg("mixin aroundReceive")
expectMsg("base aroundReceive")
expectMsg("mixin aroundPreRestart")
expectMsg("base aroundPreRestart")
expectMsg("preRestart")
expectMsg("postStop")
expectMsg("mixin aroundPostRestart")
expectMsg("base aroundPostRestart")
expectMsg("postRestart")
expectMsg("preStart")
persistentActor ! PoisonPill
expectMsg("mixin aroundPostStop")
expectMsg("base aroundPostStop")
expectMsg("postStop")
expectNoMsg(100.millis)
}
}
}
class LeveldbPersistentActorSpec extends PersistentActorSpec(PersistenceSpec.config("leveldb", "LeveldbPersistentActorSpec"))