add ?(msg, timeout) migration helper, see #1653
This commit is contained in:
parent
34a0f005b1
commit
f6d71881ea
4 changed files with 98 additions and 1 deletions
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package akka.migration
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.dispatch.Future
|
||||
import akka.util.Timeout
|
||||
|
||||
class AskableActorRef(val actorRef: ActorRef) {
|
||||
|
||||
/**
|
||||
* Sends a message asynchronously and returns a [[akka.dispatch.Future]]
|
||||
* holding the eventual reply message; this means that the target actor
|
||||
* needs to send the result to the `sender` reference provided. The Future
|
||||
* will be completed with an [[akka.actor.AskTimeoutException]] after the
|
||||
* given timeout has expired; this is independent from any timeout applied
|
||||
* while awaiting a result for this future (i.e. in
|
||||
* `Await.result(..., timeout)`).
|
||||
*
|
||||
* <b>Warning:</b>
|
||||
* When using future callbacks, inside actors you need to carefully avoid closing over
|
||||
* the containing actor’s object, i.e. do not call methods or access mutable state
|
||||
* on the enclosing actor from within the callback. This would break the actor
|
||||
* encapsulation and may introduce synchronization bugs and race conditions because
|
||||
* the callback will be scheduled concurrently to the enclosing actor. Unfortunately
|
||||
* there is not yet a way to detect these illegal accesses at compile time.
|
||||
*
|
||||
* <b>Recommended usage:</b>
|
||||
*
|
||||
* {{{
|
||||
* val f = worker.ask(request)(timeout)
|
||||
* flow {
|
||||
* EnrichedRequest(request, f())
|
||||
* } pipeTo nextActor
|
||||
* }}}
|
||||
*
|
||||
* [see the [[akka.dispatch.Future]] companion object for a description of `flow`]
|
||||
*/
|
||||
def ask(message: Any)(implicit timeout: Timeout = null): Future[Any] = akka.pattern.ask(actorRef, message)(timeout)
|
||||
|
||||
/**
|
||||
* Sends a message asynchronously and returns a [[akka.dispatch.Future]]
|
||||
* holding the eventual reply message; this means that the target actor
|
||||
* needs to send the result to the `sender` reference provided. The Future
|
||||
* will be completed with an [[akka.actor.AskTimeoutException]] after the
|
||||
* given timeout has expired; this is independent from any timeout applied
|
||||
* while awaiting a result for this future (i.e. in
|
||||
* `Await.result(..., timeout)`).
|
||||
*
|
||||
* <b>Warning:</b>
|
||||
* When using future callbacks, inside actors you need to carefully avoid closing over
|
||||
* the containing actor’s object, i.e. do not call methods or access mutable state
|
||||
* on the enclosing actor from within the callback. This would break the actor
|
||||
* encapsulation and may introduce synchronization bugs and race conditions because
|
||||
* the callback will be scheduled concurrently to the enclosing actor. Unfortunately
|
||||
* there is not yet a way to detect these illegal accesses at compile time.
|
||||
*
|
||||
* <b>Recommended usage:</b>
|
||||
*
|
||||
* {{{
|
||||
* val f = worker ? request
|
||||
* flow {
|
||||
* EnrichedRequest(request, f())
|
||||
* } pipeTo nextActor
|
||||
* }}}
|
||||
*
|
||||
* [see the [[akka.dispatch.Future]] companion object for a description of `flow`]
|
||||
*/
|
||||
def ?(message: Any)(implicit timeout: Timeout): Future[Any] = akka.pattern.ask(actorRef, message)(timeout)
|
||||
|
||||
@deprecated("use ?(msg)(timeout), this method has dangerous ambiguity", "2.0-migration")
|
||||
def ?(message: Any, timeout: Timeout)(i: Int = 0): Future[Any] = this.?(message)(timeout)
|
||||
}
|
||||
|
|
@ -31,4 +31,7 @@ package object migration {
|
|||
def stop(): Unit = GlobalActorSystem.stop(actorRef)
|
||||
}
|
||||
|
||||
implicit def ask(actorRef: ActorRef) = new akka.migration.AskableActorRef(actorRef)
|
||||
def ask(actorRef: ActorRef, message: Any)(implicit timeout: Timeout = null): Future[Any] = akka.pattern.ask(actorRef, message)(timeout)
|
||||
|
||||
}
|
||||
|
|
@ -81,7 +81,7 @@ object AskSupport {
|
|||
*
|
||||
* [see the [[akka.dispatch.Future]] companion object for a description of `flow`]
|
||||
*/
|
||||
def ?(message: Any)(implicit timeout: Timeout): Future[Any] = akka.pattern.ask(actorRef, message)(timeout)
|
||||
def ?(message: Any)(implicit timeout: Timeout = null): Future[Any] = akka.pattern.ask(actorRef, message)(timeout)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -205,6 +205,26 @@ Documentation:
|
|||
* :ref:`actors-scala`
|
||||
* :ref:`untyped-actors-java`
|
||||
|
||||
``ActorRef.?(msg, timeout)``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This method has a dangerous overlap with ``ActorRef.?(msg)(implicit timeout)``
|
||||
due to the fact that Scala allows to pass a :class:`Tuple` in place of the
|
||||
message without requiring extra parentheses::
|
||||
|
||||
actor ? (1, "hallo") // will send a tuple
|
||||
actor ? (1, Timeout()) // will send 1 with an explicit timeout
|
||||
|
||||
To remove this ambiguity, the latter variant is removed in version 2.0. If you
|
||||
were using it before, it will now send tuples where that is not desired. In
|
||||
order to correct all places in the code where this happens, simply import
|
||||
``akka.migration.ask`` instead of ``akka.pattern.ask`` to obtain a variant
|
||||
which will give deprecation warnings where the old method signature is used::
|
||||
|
||||
import akka.migration.ask
|
||||
|
||||
actor ? (1, Timeout(2 seconds)) // will give deprecation warning
|
||||
|
||||
ActorPool
|
||||
^^^^^^^^^
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue