fix NPE in SnapshotStore, #26580

* access of context.system from Future callback
* also changed import context.dispatcher, shouldn't be needed but
  rather safe than sorry
This commit is contained in:
Patrik Nordwall 2019-03-20 13:10:52 +01:00
parent 886088f03b
commit 610a89c2d0
2 changed files with 84 additions and 74 deletions

View file

@ -5,14 +5,17 @@
package akka.persistence.journal
import scala.concurrent.duration._
import akka.actor._
import akka.pattern.pipe
import akka.persistence._
import akka.util.Helpers.toRootLowerCase
import scala.collection.immutable
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.util.{ Failure, Success, Try }
import scala.util.control.NonFatal
import akka.pattern.CircuitBreaker
/**
@ -21,7 +24,6 @@ import akka.pattern.CircuitBreaker
trait AsyncWriteJournal extends Actor with WriteJournalBase with AsyncRecovery {
import AsyncWriteJournal._
import JournalProtocol._
import context.dispatcher
private val extension = Persistence(context.system)
private val publish = extension.settings.internal.publishPluginCommands
@ -56,6 +58,8 @@ trait AsyncWriteJournal extends Actor with WriteJournalBase with AsyncRecovery {
final val receiveWriteJournal: Actor.Receive = {
// cannot be a val in the trait due to binary compatibility
val replayDebugEnabled: Boolean = config.getBoolean("replay-filter.debug")
val eventStream = context.system.eventStream // used from Future callbacks
implicit val ec: ExecutionContext = context.dispatcher
{
case WriteMessages(messages, persistentActor, actorInstanceId) =>
@ -71,7 +75,7 @@ trait AsyncWriteJournal extends Actor with WriteJournalBase with AsyncRecovery {
catch { case NonFatal(e) => Future.failed(e) }
case f @ Failure(_) =>
// exception from preparePersistentBatch => rejected
Future.successful(messages.collect { case a: AtomicWrite => f })
Future.successful(messages.collect { case _: AtomicWrite => f })
}).map { results =>
if (results.nonEmpty && results.size != atomicWriteCount)
throw new IllegalStateException(
@ -171,7 +175,7 @@ trait AsyncWriteJournal extends Actor with WriteJournalBase with AsyncRecovery {
}
.pipeTo(replyTo)
.foreach { _ =>
if (publish) context.system.eventStream.publish(r)
if (publish) eventStream.publish(r)
}
case d @ DeleteMessagesTo(persistenceId, toSequenceNr, persistentActor) =>
@ -185,7 +189,7 @@ trait AsyncWriteJournal extends Actor with WriteJournalBase with AsyncRecovery {
}
.pipeTo(persistentActor)
.onComplete { _ =>
if (publish) context.system.eventStream.publish(d)
if (publish) eventStream.publish(d)
}
}
}

View file

@ -4,8 +4,10 @@
package akka.persistence.snapshot
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
import scala.concurrent.Future
import akka.actor._
import akka.pattern.pipe
import akka.persistence._
@ -16,7 +18,6 @@ import akka.pattern.CircuitBreaker
*/
trait SnapshotStore extends Actor with ActorLogging {
import SnapshotProtocol._
import context.dispatcher
private val extension = Persistence(context.system)
private val publish = extension.settings.internal.publishPluginCommands
@ -32,6 +33,10 @@ trait SnapshotStore extends Actor with ActorLogging {
final def receive = receiveSnapshotStore.orElse[Any, Unit](receivePluginInternal)
final val receiveSnapshotStore: Actor.Receive = {
val eventStream = context.system.eventStream // used from Future callbacks
implicit val ec: ExecutionContext = context.dispatcher
{
case LoadSnapshot(persistenceId, criteria, toSequenceNr) =>
if (criteria == SnapshotSelectionCriteria.None) {
senderPersistentActor() ! LoadSnapshotResult(snapshot = None, toSequenceNr)
@ -78,7 +83,7 @@ trait SnapshotStore extends Actor with ActorLogging {
}
.pipeTo(self)(senderPersistentActor())
.onComplete {
case _ => if (publish) context.system.eventStream.publish(d)
case _ => if (publish) eventStream.publish(d)
}
case evt: DeleteSnapshotSuccess =>
@ -99,7 +104,7 @@ trait SnapshotStore extends Actor with ActorLogging {
}
.pipeTo(self)(senderPersistentActor())
.onComplete {
case _ => if (publish) context.system.eventStream.publish(d)
case _ => if (publish) eventStream.publish(d)
}
case evt: DeleteSnapshotsFailure =>
@ -109,6 +114,7 @@ trait SnapshotStore extends Actor with ActorLogging {
try tryReceivePluginInternal(evt)
finally senderPersistentActor() ! evt
}
}
/** Documents intent that the sender() is expected to be the PersistentActor */
@inline private final def senderPersistentActor(): ActorRef = sender()