per #15423 Remove deprecated features from akka-persistence

* remove channels
* remove View
* remove Processor
* collapse the complicated internal state management
  that was spread out between Processor, Eventsourced and Recovery
* remove Recovery trait, this caused some duplication between Eventsourced
  and PersistentView, but but the enhanced PersistentView will not be based
  on recovery infrastructure, and therefore PersistentView code will be replaced anyway
* remove PersistentBatch
* remove LoopMessage
* remove deleteMessages of individual messages
* remove Persistent, PersistentRepr and PersistentImpl are kept
* remove processorId
* update doc sample code
* note in migration guide about persistenceId
* rename Resequencable to PersistentEnvelope
This commit is contained in:
Patrik Nordwall 2014-12-08 11:02:14 +01:00
parent 86a5b3d9d7
commit c566d5a106
84 changed files with 2162 additions and 9560 deletions

View file

@ -16,90 +16,45 @@ object PerformanceSpec {
// accurate throughput measurements
val config =
"""
akka.persistence.performance.cycles.warmup = 300
akka.persistence.performance.cycles.load = 1000
"""
case object StartMeasure
case object StopMeasure
final case class FailAt(sequenceNr: Long)
trait Measure extends { this: Actor
val NanoToSecond = 1000.0 * 1000 * 1000
class Measure(numberOfMessages: Int) {
private val NanoToSecond = 1000.0 * 1000 * 1000
var startTime: Long = 0L
var stopTime: Long = 0L
var startSequenceNr = 0L
var stopSequenceNr = 0L
private var startTime: Long = 0L
private var stopTime: Long = 0L
def startMeasure(): Unit = {
startSequenceNr = lastSequenceNr
startTime = System.nanoTime
}
def stopMeasure(): Unit = {
stopSequenceNr = lastSequenceNr
def stopMeasure(): Double = {
stopTime = System.nanoTime
sender() ! (NanoToSecond * (stopSequenceNr - startSequenceNr) / (stopTime - startTime))
}
def lastSequenceNr: Long
}
class PerformanceTestDestination extends Actor with Measure {
var lastSequenceNr = 0L
val confirm: PartialFunction[Any, Any] = {
case cp @ ConfirmablePersistent(payload, sequenceNr, _)
lastSequenceNr = sequenceNr
cp.confirm()
payload
}
def receive = confirm andThen {
case StartMeasure startMeasure()
case StopMeasure stopMeasure()
case m if (lastSequenceNr % 1000 == 0) print(".")
(NanoToSecond * numberOfMessages / (stopTime - startTime))
}
}
abstract class PerformanceTestProcessor(name: String) extends NamedProcessor(name) with Measure {
abstract class PerformanceTestPersistentActor(name: String) extends NamedPersistentActor(name) {
var failAt: Long = -1
val controlBehavior: Receive = {
case StartMeasure startMeasure()
case StopMeasure stopMeasure()
case FailAt(sequenceNr) failAt = sequenceNr
}
override def postRestart(reason: Throwable) {
super.postRestart(reason)
receive(StartMeasure)
}
}
class CommandsourcedTestProcessor(name: String) extends PerformanceTestProcessor(name) {
def receive = controlBehavior orElse {
case p: Persistent
if (lastSequenceNr % 1000 == 0) if (recoveryRunning) print("r") else print(".")
if (lastSequenceNr == failAt) throw new TestException("boom")
}
}
class CommandsourcedTestPersistentActor(name: String) extends PerformanceTestProcessor(name) with PersistentActor {
override val controlBehavior: Receive = {
case StartMeasure startMeasure()
case StopMeasure defer(StopMeasure)(_ stopMeasure())
case FailAt(sequenceNr) failAt = sequenceNr
}
val receiveRecover: Receive = {
override val receiveRecover: Receive = {
case _ if (lastSequenceNr % 1000 == 0) print("r")
}
val receiveCommand: Receive = controlBehavior orElse {
val controlBehavior: Receive = {
case StopMeasure defer(StopMeasure)(_ sender() ! StopMeasure)
case FailAt(sequenceNr) failAt = sequenceNr
}
}
class CommandsourcedTestPersistentActor(name: String) extends PerformanceTestPersistentActor(name) {
override val receiveCommand: Receive = controlBehavior orElse {
case cmd persistAsync(cmd) { _
if (lastSequenceNr % 1000 == 0) print(".")
if (lastSequenceNr == failAt) throw new TestException("boom")
@ -107,12 +62,9 @@ object PerformanceSpec {
}
}
class EventsourcedTestProcessor(name: String) extends PerformanceTestProcessor(name) with PersistentActor {
val receiveRecover: Receive = {
case _ if (lastSequenceNr % 1000 == 0) print("r")
}
class EventsourcedTestPersistentActor(name: String) extends PerformanceTestPersistentActor(name) {
val receiveCommand: Receive = controlBehavior orElse {
override val receiveCommand: Receive = controlBehavior orElse {
case cmd persist(cmd) { _
if (lastSequenceNr % 1000 == 0) print(".")
if (lastSequenceNr == failAt) throw new TestException("boom")
@ -120,11 +72,27 @@ object PerformanceSpec {
}
}
class StashingEventsourcedTestProcessor(name: String) extends PerformanceTestProcessor(name) with PersistentActor {
val receiveRecover: Receive = {
case _ if (lastSequenceNr % 1000 == 0) print("r")
/**
* `persist` every 10th message, otherwise `persistAsync`
*/
class MixedTestPersistentActor(name: String) extends PerformanceTestPersistentActor(name) {
var counter = 0
val handler: Any Unit = { evt
if (lastSequenceNr % 1000 == 0) print(".")
if (lastSequenceNr == failAt) throw new TestException("boom")
}
val receiveCommand: Receive = controlBehavior orElse {
case cmd
counter += 1
if (counter % 10 == 0) persist(cmd)(handler)
else persistAsync(cmd)(handler)
}
}
class StashingEventsourcedTestPersistentActor(name: String) extends PerformanceTestPersistentActor(name) {
val printProgress: PartialFunction[Any, Any] = {
case m if (lastSequenceNr % 1000 == 0) print("."); m
}
@ -146,82 +114,50 @@ object PerformanceSpec {
class PerformanceSpec extends AkkaSpec(PersistenceSpec.config("leveldb", "PerformanceSpec", serialization = "off").withFallback(ConfigFactory.parseString(PerformanceSpec.config))) with PersistenceSpec with ImplicitSender {
import PerformanceSpec._
val warmupCycles = system.settings.config.getInt("akka.persistence.performance.cycles.warmup")
val loadCycles = system.settings.config.getInt("akka.persistence.performance.cycles.load")
def stressCommandsourcedProcessor(failAt: Option[Long]): Unit = {
val processor = namedProcessor[CommandsourcedTestProcessor]
failAt foreach { processor ! FailAt(_) }
1 to warmupCycles foreach { i processor ! Persistent(s"msg${i}") }
processor ! StartMeasure
1 to loadCycles foreach { i processor ! Persistent(s"msg${i}") }
processor ! StopMeasure
expectMsgPF(100 seconds) {
case throughput: Double println(f"\nthroughput = $throughput%.2f persistent processor commands per second")
}
def stressPersistentActor(persistentActor: ActorRef, failAt: Option[Long], description: String): Unit = {
failAt foreach { persistentActor ! FailAt(_) }
val m = new Measure(loadCycles)
m.startMeasure()
1 to loadCycles foreach { i persistentActor ! s"msg${i}" }
persistentActor ! StopMeasure
expectMsg(100.seconds, StopMeasure)
println(f"\nthroughput = ${m.stopMeasure()}%.2f $description per second")
}
def stressCommandsourcedPersistentActor(failAt: Option[Long]): Unit = {
val processor = namedProcessor[CommandsourcedTestPersistentActor]
failAt foreach { processor ! FailAt(_) }
1 to warmupCycles foreach { i processor ! s"msg${i}" }
processor ! StartMeasure
1 to loadCycles foreach { i processor ! s"msg${i}" }
processor ! StopMeasure
expectMsgPF(100 seconds) {
case throughput: Double println(f"\nthroughput = $throughput%.2f persistent actor commands per second")
}
val persistentActor = namedPersistentActor[CommandsourcedTestPersistentActor]
stressPersistentActor(persistentActor, failAt, "persistent commands")
}
def stressPersistentActor(failAt: Option[Long]): Unit = {
val processor = namedProcessor[EventsourcedTestProcessor]
failAt foreach { processor ! FailAt(_) }
1 to warmupCycles foreach { i processor ! s"msg${i}" }
processor ! StartMeasure
1 to loadCycles foreach { i processor ! s"msg${i}" }
processor ! StopMeasure
expectMsgPF(100 seconds) {
case throughput: Double println(f"\nthroughput = $throughput%.2f persistent events per second")
}
def stressEventSourcedPersistentActor(failAt: Option[Long]): Unit = {
val persistentActor = namedPersistentActor[EventsourcedTestPersistentActor]
stressPersistentActor(persistentActor, failAt, "persistent events")
}
def stressMixedPersistentActor(failAt: Option[Long]): Unit = {
val persistentActor = namedPersistentActor[MixedTestPersistentActor]
stressPersistentActor(persistentActor, failAt, "persistent events & commands")
}
def stressStashingPersistentActor(): Unit = {
val processor = namedProcessor[StashingEventsourcedTestProcessor]
1 to warmupCycles foreach { i processor ! "b" }
processor ! StartMeasure
val persistentActor = namedPersistentActor[StashingEventsourcedTestPersistentActor]
val m = new Measure(loadCycles)
m.startMeasure()
val cmds = 1 to (loadCycles / 3) flatMap (_ List("a", "b", "c"))
processor ! StartMeasure
cmds foreach (processor ! _)
processor ! StopMeasure
expectMsgPF(100 seconds) {
case throughput: Double println(f"\nthroughput = $throughput%.2f persistent events per second")
}
cmds foreach (persistentActor ! _)
persistentActor ! StopMeasure
expectMsg(100.seconds, StopMeasure)
println(f"\nthroughput = ${m.stopMeasure()}%.2f persistent events per second")
}
def stressPersistentChannel(): Unit = {
val channel = system.actorOf(PersistentChannel.props())
val destination = system.actorOf(Props[PerformanceTestDestination])
1 to warmupCycles foreach { i channel ! Deliver(PersistentRepr(s"msg${i}", persistenceId = "test"), destination.path) }
channel ! Deliver(Persistent(StartMeasure), destination.path)
1 to loadCycles foreach { i channel ! Deliver(PersistentRepr(s"msg${i}", persistenceId = "test"), destination.path) }
channel ! Deliver(Persistent(StopMeasure), destination.path)
expectMsgPF(100 seconds) {
case throughput: Double println(f"\nthroughput = $throughput%.2f persistent messages per second")
"Warmup persistent actor" should {
"exercise" in {
stressCommandsourcedPersistentActor(None)
}
}
def subscribeToConfirmation(probe: TestProbe): Unit =
system.eventStream.subscribe(probe.ref, classOf[DeliveredByPersistentChannel])
def awaitConfirmation(probe: TestProbe): Unit =
probe.expectMsgType[DeliveredByPersistentChannel]
"A command sourced processor" should {
"have some reasonable throughput" in {
stressCommandsourcedProcessor(None)
}
"have some reasonable throughput under failure conditions" in {
stressCommandsourcedProcessor(Some(warmupCycles + loadCycles / 10))
"exercise some more" in {
stressCommandsourcedPersistentActor(None)
}
}
@ -233,26 +169,20 @@ class PerformanceSpec extends AkkaSpec(PersistenceSpec.config("leveldb", "Perfor
"An event sourced persistent actor" should {
"have some reasonable throughput" in {
stressPersistentActor(None)
stressEventSourcedPersistentActor(None)
}
"have some reasonable throughput under failure conditions" in {
stressPersistentActor(Some(warmupCycles + loadCycles / 10))
stressEventSourcedPersistentActor(Some(loadCycles / 10))
}
"have some reasonable throughput with stashing and unstashing every 3rd command" in {
stressStashingPersistentActor()
}
}
"A persistent channel" should {
"A mixed command and event sourced persistent actor" should {
"have some reasonable throughput" in {
val probe = TestProbe()
subscribeToConfirmation(probe)
stressPersistentChannel()
probe.fishForMessage(100.seconds) {
case DeliveredByPersistentChannel(_, snr, _, _) snr == warmupCycles + loadCycles + 2
}
stressMixedPersistentActor(None)
}
}
}