Remove various features deprecated since 2.5.0 (#27023)

* Remove various features deprecated since 2.5.0
This commit is contained in:
Christopher Batey 2019-05-29 07:10:40 +01:00 committed by GitHub
parent 28fbd28e7a
commit e7672a9802
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 41 additions and 575 deletions

View file

@ -42,3 +42,17 @@ ProblemFilters.exclude[MissingTypesProblem]("akka.dispatch.Mailbox")
ProblemFilters.exclude[MissingTypesProblem]("akka.dispatch.BalancingDispatcher$SharingMailbox") ProblemFilters.exclude[MissingTypesProblem]("akka.dispatch.BalancingDispatcher$SharingMailbox")
ProblemFilters.exclude[MissingTypesProblem]("akka.dispatch.MonitorableThreadFactory$AkkaForkJoinWorkerThread") ProblemFilters.exclude[MissingTypesProblem]("akka.dispatch.MonitorableThreadFactory$AkkaForkJoinWorkerThread")
ProblemFilters.exclude[IncompatibleMethTypeProblem]("akka.dispatch.MonitorableThreadFactory#AkkaForkJoinWorkerThread.this") ProblemFilters.exclude[IncompatibleMethTypeProblem]("akka.dispatch.MonitorableThreadFactory#AkkaForkJoinWorkerThread.this")
# Remove deprecated features since 2.5.0 https://github.com/akka/akka/issues/26492
# The ActorCell and others are due to UntypedActorContext being removed from the Cell's hierarchy
ProblemFilters.exclude[MissingClassProblem]("akka.actor.UntypedActor")
ProblemFilters.exclude[MissingClassProblem]("akka.actor.UntypedActorWithUnboundedStash")
ProblemFilters.exclude[MissingTypesProblem]("akka.actor.ActorCell")
ProblemFilters.exclude[MissingClassProblem]("akka.actor.UntypedActorWithStash")
ProblemFilters.exclude[MissingClassProblem]("akka.actor.UntypedActorWithUnrestrictedStash")
ProblemFilters.exclude[MissingClassProblem]("akka.actor.UntypedActorContext")
ProblemFilters.exclude[MissingClassProblem]("akka.actor.ExtensionKey")
ProblemFilters.exclude[IncompatibleMethTypeProblem]("akka.event.LoggingReceive.create")
ProblemFilters.exclude[IncompatibleMethTypeProblem]("akka.event.Logging.getLogger")
ProblemFilters.exclude[MissingTypesProblem]("akka.routing.RoutedActorCell")
ProblemFilters.exclude[MissingTypesProblem]("akka.routing.ResizablePoolCell")

View file

@ -233,46 +233,6 @@ trait ActorContext extends ActorRefFactory {
throw new NotSerializableException("ActorContext is not serializable!") throw new NotSerializableException("ActorContext is not serializable!")
} }
/**
* UntypedActorContext is the UntypedActor equivalent of ActorContext,
* containing the Java API
*/
@deprecated("Use AbstractActor.ActorContext instead of UntypedActorContext.", since = "2.5.0")
trait UntypedActorContext extends ActorContext {
/**
* Returns an unmodifiable Java Collection containing the linked actors,
* please note that the backing map is thread-safe but not immutable
*/
def getChildren(): java.lang.Iterable[ActorRef]
/**
* Returns a reference to the named child or null if no child with
* that name exists.
*/
def getChild(name: String): ActorRef
/**
* Changes the Actor's behavior to become the new 'Procedure' handler.
* Replaces the current behavior on the top of the behavior stack.
*/
def become(behavior: Procedure[Any]): Unit
/**
* Changes the Actor's behavior to become the new 'Procedure' handler.
* This method acts upon the behavior stack as follows:
*
* - if `discardOld = true` it will replace the top element (i.e. the current behavior)
* - if `discardOld = false` it will keep the current behavior and push the given one atop
*
* The default of replacing the current behavior on the stack has been chosen to avoid memory
* leaks in case client code is written without consulting this documentation first (i.e.
* always pushing new behaviors and never issuing an `unbecome()`)
*/
def become(behavior: Procedure[Any], discardOld: Boolean): Unit
}
/** /**
* INTERNAL API * INTERNAL API
*/ */
@ -450,8 +410,7 @@ private[akka] class ActorCell(
final val props: Props, // Must be final so that it can be properly cleared in clearActorCellFields final val props: Props, // Must be final so that it can be properly cleared in clearActorCellFields
val dispatcher: MessageDispatcher, val dispatcher: MessageDispatcher,
val parent: InternalActorRef) val parent: InternalActorRef)
extends UntypedActorContext extends AbstractActor.ActorContext
with AbstractActor.ActorContext
with Cell with Cell
with dungeon.ReceiveTimeout with dungeon.ReceiveTimeout
with dungeon.Children with dungeon.Children

View file

@ -4,8 +4,6 @@
package akka.actor package akka.actor
import scala.reflect.ClassTag
/** /**
* The basic ActorSystem covers all that is needed for locally running actors, * The basic ActorSystem covers all that is needed for locally running actors,
* using futures and so on. In addition, more features can hook into it and * using futures and so on. In addition, more features can hook into it and
@ -118,41 +116,3 @@ trait ExtensionIdProvider {
*/ */
def lookup(): ExtensionId[_ <: Extension] def lookup(): ExtensionId[_ <: Extension]
} }
/**
* This is a one-stop-shop if all you want is an extension which is
* constructed with the ExtendedActorSystem as its only constructor argument:
*
* {{{
* object MyExt extends ExtensionKey[Ext]
*
* class Ext(system: ExtendedActorSystem) extends Extension {
* ...
* }
* }}}
*
* Java API:
*
* {{{
* public class MyExt extends Extension {
* public static final ExtensionKey<MyExt> key = new ExtensionKey<MyExt>(MyExt.class);
*
* public MyExt(ExtendedActorSystem system) {
* ...
* }
* }
* }}}
*
* Note: Don't use this class if the extension is written in Scala and consumed in
* Eclipse Java projects. JDT has problems resolving correct type for the
* `get` method.
*
*/
@deprecated(message = "Use a regular Extension instead", since = "2.5.0")
abstract class ExtensionKey[T <: Extension](implicit m: ClassTag[T]) extends ExtensionId[T] with ExtensionIdProvider {
def this(clazz: Class[T]) = this()(ClassTag(clazz))
override def lookup(): ExtensionId[T] = this
def createExtension(system: ExtendedActorSystem): T =
system.dynamicAccess.createInstanceFor[T](m.runtimeClass, List(classOf[ExtendedActorSystem] -> system)).get
}

View file

@ -1,178 +0,0 @@
/*
* Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
*/
package akka.actor
/**
* Actor base trait that should be extended by or mixed to create an Actor with the semantics of the 'Actor Model':
* <a href="http://en.wikipedia.org/wiki/Actor_model">http://en.wikipedia.org/wiki/Actor_model</a>
*
* This class is the Java cousin to the [[akka.actor.Actor]] Scala interface.
* Subclass this abstract class to create a MDB-style untyped actor.
*
* An actor has a well-defined (non-cyclic) life-cycle.
* - ''RUNNING'' (created and started actor) - can receive messages
* - ''SHUTDOWN'' (when 'stop' or 'exit' is invoked) - can't do anything
*
* The Actor's own [[akka.actor.ActorRef]] is available as `getSelf()`, the current
* messages sender as `getSender()` and the [[akka.actor.UntypedActorContext]] as
* `getContext()`. The only abstract method is `onReceive()` which is invoked for
* each processed message unless dynamically overridden using `getContext().become()`.
*
* Here is an example on how to create and use an UntypedActor:
*
* {{{
* public class SampleUntypedActor extends UntypedActor {
*
* public static class Reply implements java.io.Serializable {
* final public ActorRef sender;
* final public Result result;
* Reply(ActorRef sender, Result result) {
* this.sender = sender;
* this.result = result;
* }
* }
*
* private static SupervisorStrategy strategy = new OneForOneStrategy(10, Duration.create("1 minute"),
* new Function<Throwable, Directive>() {
* @Override
* public Directive apply(Throwable t) {
* if (t instanceof ArithmeticException) {
* return resume();
* } else if (t instanceof NullPointerException) {
* return restart();
* } else if (t instanceof IllegalArgumentException) {
* return stop();
* } else {
* return escalate();
* }
* }
* });
*
* @Override
* public SupervisorStrategy supervisorStrategy() {
* return strategy;
* }
*
* public void onReceive(Object message) throws Exception {
* if (message instanceof String) {
* String msg = (String) message;
*
* if (msg.equals("UseSender")) {
* // Reply to original sender of message
* getSender().tell(msg, getSelf());
*
* } else if (msg.equals("SendToSelf")) {
* // Send message to the actor itself recursively
* getSelf().tell("SomeOtherMessage", getSelf());
*
* } else if (msg.equals("ErrorKernelWithDirectReply")) {
* // Send work to one-off child which will reply directly to original sender
* getContext().actorOf(Props.create(Worker.class)).tell("DoSomeDangerousWork", getSender());
*
* } else if (msg.equals("ErrorKernelWithReplyHere")) {
* // Send work to one-off child and collect the answer, reply handled further down
* getContext().actorOf(Props.create(Worker.class)).tell("DoWorkAndReplyToMe", getSelf());
*
* } else {
* unhandled(message);
* }
*
* } else if (message instanceof Reply) {
*
* final Reply reply = (Reply) message;
* // might want to do some processing/book-keeping here
* reply.sender.tell(reply.result, getSelf());
*
* } else {
* unhandled(message);
* }
* }
* }
* }}}
*/
@Deprecated
@deprecated("Use AbstractActor instead of UntypedActor.", since = "2.5.0")
abstract class UntypedActor extends Actor {
/**
* To be implemented by concrete UntypedActor, this defines the behavior of the
* UntypedActor.
*/
@throws(classOf[Throwable])
def onReceive(message: Any): Unit
/**
* Returns this UntypedActor's UntypedActorContext
* The UntypedActorContext is not thread safe so do not expose it outside of the
* UntypedActor.
*/
def getContext(): UntypedActorContext = context.asInstanceOf[UntypedActorContext]
/**
* Returns the ActorRef for this actor.
*/
def getSelf(): ActorRef = self
/**
* The reference sender Actor of the currently processed message. This is
* always a legal destination to send to, even if there is no logical recipient
* for the reply, in which case it will be sent to the dead letter mailbox.
*/
def getSender(): ActorRef = sender()
/**
* User overridable definition the strategy to use for supervising
* child actors.
*/
override def supervisorStrategy: SupervisorStrategy = super.supervisorStrategy
/**
* User overridable callback.
* <p/>
* Is called when an Actor is started.
* Actor are automatically started asynchronously when created.
* Empty default implementation.
*/
@throws(classOf[Exception])
override def preStart(): Unit = super.preStart()
/**
* User overridable callback.
* <p/>
* Is called asynchronously after 'actor.stop()' is invoked.
* Empty default implementation.
*/
@throws(classOf[Exception])
override def postStop(): Unit = super.postStop()
/**
* User overridable callback: '''By default it disposes of all children and then calls `postStop()`.'''
* <p/>
* Is called on a crashed Actor right BEFORE it is restarted to allow clean
* up of resources before Actor is terminated.
*/
@throws(classOf[Exception])
override def preRestart(reason: Throwable, message: Option[Any]): Unit = super.preRestart(reason, message)
/**
* User overridable callback: By default it calls `preStart()`.
* <p/>
* Is called right AFTER restart on the newly created Actor to allow reinitialization after an Actor crash.
*/
@throws(classOf[Exception])
override def postRestart(reason: Throwable): Unit = super.postRestart(reason)
final def receive = { case msg => onReceive(msg) }
/**
* Recommended convention is to call this method if the message
* isn't handled in [[#onReceive]] (e.g. unknown message type).
* By default it fails with either a [[akka.actor.DeathPactException]] (in
* case of an unhandled [[akka.actor.Terminated]] message) or publishes an [[akka.actor.UnhandledMessage]]
* to the actor's system's [[akka.event.EventStream]].
*/
override def unhandled(message: Any): Unit = super.unhandled(message)
}

View file

@ -1,63 +0,0 @@
/*
* Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
*/
package akka.actor
/**
* Actor base class that should be extended to create an actor with a stash.
*
* The stash enables an actor to temporarily stash away messages that can not or
* should not be handled using the actor's current behavior.
* <p/>
* Example:
* <pre>
* public class MyActorWithStash extends UntypedActorWithStash {
* int count = 0;
* public void onReceive(Object msg) {
* if (msg instanceof String) {
* if (count < 0) {
* getSender().tell(new Integer(((String) msg).length()), getSelf());
* } else if (count == 2) {
* count = -1;
* unstashAll();
* } else {
* count += 1;
* stash();
* }
* }
* }
* }
* </pre>
* Note that the subclasses of `UntypedActorWithStash` by default request a Deque based mailbox since this class
* implements the `RequiresMessageQueue&lt;DequeBasedMessageQueueSemantics&gt;` marker interface.
* You can override the default mailbox provided when `DequeBasedMessageQueueSemantics` are requested via config:
* <pre>
* akka.actor.mailbox.requirements {
* "akka.dispatch.BoundedDequeBasedMessageQueueSemantics" = your-custom-mailbox
* }
* </pre>
* Alternatively, you can add your own requirement marker to the actor and configure a mailbox type to be used
* for your marker.
*
* For a `Stash` based actor that enforces unbounded deques see [[akka.actor.UntypedActorWithUnboundedStash]].
* There is also an unrestricted version [[akka.actor.UntypedActorWithUnrestrictedStash]] that does not
* enforce the mailbox type.
*/
@deprecated("Use AbstractActorWithStash instead of UntypedActorWithStash.", since = "2.5.0")
abstract class UntypedActorWithStash extends UntypedActor with Stash
/**
* Actor base class with `Stash` that enforces an unbounded deque for the actor.
* See [[akka.actor.UntypedActorWithStash]] for details on how `Stash` works.
*/
@deprecated("Use AbstractActorWithUnboundedStash instead of UntypedActorWithUnboundedStash.", since = "2.5.0")
abstract class UntypedActorWithUnboundedStash extends UntypedActor with UnboundedStash
/**
* Actor base class with `Stash` that does not enforce any mailbox type. The proper mailbox has to be configured
* manually, and the mailbox should extend the [[akka.dispatch.DequeBasedMessageQueueSemantics]] marker trait.
* See [[akka.actor.UntypedActorWithStash]] for details on how `Stash` works.
*/
@deprecated("Use AbstractActorWithUnrestrictedStash instead of UntypedActorWithUnrestrictedStash.", since = "2.5.0")
abstract class UntypedActorWithUnrestrictedStash extends UntypedActor with UnrestrictedStash

View file

@ -675,17 +675,6 @@ object Logging {
*/ */
def getLogger(logSource: Actor): DiagnosticLoggingAdapter = apply(logSource) def getLogger(logSource: Actor): DiagnosticLoggingAdapter = apply(logSource)
/**
* Obtain LoggingAdapter with MDC support for the given actor.
* Don't use it outside its specific Actor as it isn't thread safe
*/
@deprecated("Use AbstractActor instead of UntypedActor.", since = "2.5.0")
def getLogger(logSource: UntypedActor): DiagnosticLoggingAdapter = {
val (str, clazz) = LogSource.fromAnyRef(logSource)
val system = logSource.getContext().system.asInstanceOf[ExtendedActorSystem]
new BusLogging(system.eventStream, str, clazz, system.logFilter) with DiagnosticLoggingAdapter
}
/** /**
* Artificial exception injected into Error events if no Throwable is * Artificial exception injected into Error events if no Throwable is
* supplied; used for getting a stack dump of error locations. * supplied; used for getting a stack dump of error locations.

View file

@ -38,12 +38,6 @@ object LoggingReceive {
*/ */
def apply(logLevel: LogLevel)(r: Receive)(implicit context: ActorContext): Receive = withLabel(null, logLevel)(r) def apply(logLevel: LogLevel)(r: Receive)(implicit context: ActorContext): Receive = withLabel(null, logLevel)(r)
/**
* Java API: compatible with lambda expressions
*/
@deprecated("Use the create method with `AbstractActor.Receive` parameter instead.", since = "2.5.0")
def create(r: Receive, context: ActorContext): Receive = apply(r)(context)
/** /**
* Java API: compatible with lambda expressions * Java API: compatible with lambda expressions
*/ */

View file

@ -110,10 +110,7 @@ class FusedGraphsBenchmark {
@Setup @Setup
def setup(): Unit = { def setup(): Unit = {
val settings = ActorMaterializerSettings(system) val settings = ActorMaterializerSettings(system).withFuzzing(false).withSyncProcessingLimit(Int.MaxValue)
.withFuzzing(false)
.withSyncProcessingLimit(Int.MaxValue)
.withAutoFusing(false) // We fuse manually in this test in the setup
materializer = ActorMaterializer(settings) materializer = ActorMaterializer(settings)
testElements = Array.fill(ElementCount)(new MutableElement(0)) testElements = Array.fill(ElementCount)(new MutableElement(0))

View file

@ -45,6 +45,25 @@ Use plain `system.actorOf` instead of the DSL to create Actors if you have been
`actorFor` has been deprecated since `2.2`. Use `ActorSelection` instead. `actorFor` has been deprecated since `2.2`. Use `ActorSelection` instead.
### Untyped actor removed
`UntypedActor` has been depcated since `2.5.0`. Use `AbstractActor` instead.
### UntypedPersistentActor removed
Use `AbstractPersistentActor` instead.
### UntypedPersistentActorWithAtLeastOnceDelivery removed
Use @apidoc[AbstractPersistentActorWithAtLeastOnceDelivery] instead.
### Various removed methods
* `Logging.getLogger(UntypedActor)` Untyped actor has been removed, use AbstractActor instead.
* `LoggingReceive.create(Receive, ActorContext)` use `AbstractActor.Receive` instead.
* `ActorMaterialzierSettings.withAutoFusing` disabling fusing is no longer possible.
## Deprecated features ## Deprecated features
### TypedActor ### TypedActor

View file

@ -6,7 +6,6 @@ package jdocs.persistence;
import akka.persistence.AbstractPersistentActor; import akka.persistence.AbstractPersistentActor;
import akka.persistence.RuntimePluginConfig; import akka.persistence.RuntimePluginConfig;
import akka.persistence.UntypedPersistentActor;
import com.typesafe.config.Config; import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory; import com.typesafe.config.ConfigFactory;

View file

@ -0,0 +1,3 @@
# Remove deprecated features since 2.5.0 https://github.com/akka/akka/issues/26492
ProblemFilters.exclude[MissingClassProblem]("akka.persistence.UntypedPersistentActor")
ProblemFilters.exclude[MissingClassProblem]("akka.persistence.UntypedPersistentActorWithAtLeastOnceDelivery")

View file

@ -404,66 +404,6 @@ trait AtLeastOnceDeliveryLike extends Eventsourced {
} }
} }
/**
* Java API: Use this class instead of `UntypedPersistentActor` to send messages
* with at-least-once delivery semantics to destinations.
* Full documentation in [[AtLeastOnceDelivery]].
*
* @see [[AtLeastOnceDelivery]]
* @see [[AtLeastOnceDeliveryLike]]
*/
@deprecated("Use AbstractPersistentActorWithAtLeastOnceDelivery instead.", since = "2.5.0")
abstract class UntypedPersistentActorWithAtLeastOnceDelivery
extends UntypedPersistentActor
with AtLeastOnceDeliveryLike {
/**
* Java API: Send the message created by the `deliveryIdToMessage` function to
* the `destination` actor. It will retry sending the message until
* the delivery is confirmed with [[#confirmDelivery]]. Correlation
* between `deliver` and `confirmDelivery` is performed with the
* `deliveryId` that is provided as parameter to the `deliveryIdToMessage`
* function. The `deliveryId` is typically passed in the message to the
* destination, which replies with a message containing the same `deliveryId`.
*
* The `deliveryId` is a strictly monotonically increasing sequence number without
* gaps. The same sequence is used for all destinations, i.e. when sending to
* multiple destinations the destinations will see gaps in the sequence if no
* translation is performed.
*
* During recovery this method will not send out the message, but it will be sent
* later if no matching `confirmDelivery` was performed.
*
* This method will throw [[AtLeastOnceDelivery.MaxUnconfirmedMessagesExceededException]]
* if [[#numberOfUnconfirmed]] is greater than or equal to [[#maxUnconfirmedMessages]].
*/
def deliver(destination: ActorPath, deliveryIdToMessage: akka.japi.Function[java.lang.Long, Object]): Unit =
internalDeliver(destination)(id => deliveryIdToMessage.apply(id))
/**
* Java API: Send the message created by the `deliveryIdToMessage` function to
* the `destination` actor. It will retry sending the message until
* the delivery is confirmed with [[#confirmDelivery]]. Correlation
* between `deliver` and `confirmDelivery` is performed with the
* `deliveryId` that is provided as parameter to the `deliveryIdToMessage`
* function. The `deliveryId` is typically passed in the message to the
* destination, which replies with a message containing the same `deliveryId`.
*
* The `deliveryId` is a strictly monotonically increasing sequence number without
* gaps. The same sequence is used for all destinations, i.e. when sending to
* multiple destinations the destinations will see gaps in the sequence if no
* translation is performed.
*
* During recovery this method will not send out the message, but it will be sent
* later if no matching `confirmDelivery` was performed.
*
* This method will throw [[AtLeastOnceDelivery.MaxUnconfirmedMessagesExceededException]]
* if [[#numberOfUnconfirmed]] is greater than or equal to [[#maxUnconfirmedMessages]].
*/
def deliver(destination: ActorSelection, deliveryIdToMessage: akka.japi.Function[java.lang.Long, Object]): Unit =
internalDeliver(destination)(id => deliveryIdToMessage.apply(id))
}
/** /**
* Java API: compatible with lambda expressions * Java API: compatible with lambda expressions
* *

View file

@ -288,166 +288,6 @@ trait PersistentActor extends Eventsourced with PersistenceIdentity {
} }
} }
/**
* Java API: an persistent actor - can be used to implement command or event sourcing.
*/
@deprecated("Use AbstractPersistentActor instead of UntypedPersistentActor.", since = "2.5.0")
abstract class UntypedPersistentActor extends UntypedActor with Eventsourced with PersistenceIdentity {
final def onReceive(message: Any) = onReceiveCommand(message)
final def receiveRecover: Receive = {
case msg => onReceiveRecover(msg)
}
final def receiveCommand: Receive = {
case msg => onReceiveCommand(msg)
}
/**
* 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 persistent actor
* 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 inherited user stash.
*
* An event `handler` may close over persistent actor 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 persistent actor state using persisted event
* data, notify listeners and reply to command senders.
*
* If persistence of an event fails, [[#onPersistFailure]] will be invoked and the actor will
* unconditionally be stopped. The reason that it cannot resume when persist fails is that it
* is unknown if the event was actually persisted or not, and therefore it is in an inconsistent
* state. Restarting on persistent failures will most likely fail anyway, since the journal
* is probably unavailable. It is better to stop the actor and after a back-off timeout start
* it again.
*
* @param event event to be persisted.
* @param handler handler for each persisted `event`
*/
def persist[A](event: A, handler: Procedure[A]): Unit =
internalPersist(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`
*/
def persistAll[A](events: JIterable[A], handler: Procedure[A]): Unit =
internalPersistAll(Util.immutableSeq(events))(event => handler(event))
/**
* JAVA API: asynchronously persists `event`. On successful persistence, `handler` is called with the
* persisted event.
*
* Unlike `persist` the persistent actor will continue to receive incoming 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 persistent actor 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, [[#onPersistFailure]] will be invoked and the actor will
* unconditionally be stopped. The reason that it cannot resume when persist fails is that it
* is unknown if the event was actually persisted or not, and therefore it is in an inconsistent
* state. Restarting on persistent failures will most likely fail anyway, since the journal
* is probably unavailable. It is better to stop the actor and after a back-off timeout start
* it again.
*
* @param event event to be persisted
* @param handler handler for each persisted `event`
*/
def persistAsync[A](event: A)(handler: Procedure[A]): Unit =
internalPersistAsync(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`
*/
def persistAllAsync[A](events: JIterable[A], handler: Procedure[A]): Unit =
internalPersistAllAsync(Util.immutableSeq(events))(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` or `persist` calls. That is, if `persistAsync` or `persist` was invoked before `deferAsync`,
* 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 immediately.
*
* If persistence of an earlier event fails, the persistent actor will stop, and the `handler`
* will not be run.
*
* @param event event to be handled in the future, when preceding persist operations have been processes
* @param handler handler for the given `event`
*/
def deferAsync[A](event: A)(handler: Procedure[A]): Unit =
internalDeferAsync(event)(event => handler(event))
/**
* Defer the handler execution until all pending handlers have been executed. It is guaranteed that no new commands
* will be received by a persistent actor between a call to `defer` and the execution of its `handler`.
* Allows to define logic within the actor, which will respect the invocation-order-guarantee
* in respect to `persistAsync` or `persist` calls. That is, if `persistAsync` or `persist` 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, use `persist` or `persistAsync` instead
* if the given event should possible to replay.
*
* If there are no pending persist handler calls, the handler will be called immediately.
*
* If persistence of an earlier event fails, the persistent actor will stop, and the `handler`
* will not be run.
*
* @param event event to be handled in the future, when preceding persist operations have been processes
* @param handler handler for the given `event`
*/
def defer[A](event: A)(handler: Procedure[A]): Unit = {
internalDefer(event)(event => handler(event))
}
/**
* Java API: recovery handler that receives persisted events during recovery. If a state snapshot
* 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 persistent actor state i.e. it
* should not perform actions that may fail, such as interacting with external services,
* for example.
*
* If there is a problem with recovering the state of the actor from the journal, the error
* will be logged and the actor will be stopped.
*
* @see [[Recovery]]
*/
@throws(classOf[Throwable])
def onReceiveRecover(msg: Any): Unit
/**
* Java API: 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`.
*/
@throws(classOf[Throwable])
def onReceiveCommand(msg: Any): Unit
}
/** /**
* Java API: an persistent actor - can be used to implement command or event sourcing. * Java API: an persistent actor - can be used to implement command or event sourcing.
*/ */

View file

@ -102,3 +102,6 @@ ProblemFilters.exclude[MissingClassProblem]("akka.stream.actor.AbstractActorPubl
ProblemFilters.exclude[MissingClassProblem]("akka.stream.impl.SinkQueueAdapter") ProblemFilters.exclude[MissingClassProblem]("akka.stream.impl.SinkQueueAdapter")
ProblemFilters.exclude[MissingClassProblem]("akka.stream.impl.SourceQueueAdapter") ProblemFilters.exclude[MissingClassProblem]("akka.stream.impl.SourceQueueAdapter")
# Remove deprecated features since 2.5.0 https://github.com/akka/akka/issues/26492
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.stream.ActorMaterializerSettings.withAutoFusing")

View file

@ -612,16 +612,6 @@ final class ActorMaterializerSettings @InternalApi private (
if (enable == this.debugLogging) this if (enable == this.debugLogging) this
else copy(debugLogging = enable) else copy(debugLogging = enable)
/**
* Enable automatic fusing of all graphs that are run. For short-lived streams
* this may cause an initial runtime overhead, but most of the time fusing is
* desirable since it reduces the number of Actors that are created.
*/
@deprecated("Turning off fusing is no longer possible with the traversal based materializer", since = "2.5.0")
def withAutoFusing(enable: Boolean): ActorMaterializerSettings =
if (enable == this.autoFusing) this
else copy(autoFusing = enable)
/** /**
* Configure the maximum buffer size for which a FixedSizeBuffer will be preallocated. * Configure the maximum buffer size for which a FixedSizeBuffer will be preallocated.
* This defaults to a large value because it is usually better to fail early when * This defaults to a large value because it is usually better to fail early when