From 3a30f915c3bfb626c8d506a85e96b3957db1944a Mon Sep 17 00:00:00 2001 From: Roland Date: Mon, 23 Jan 2012 15:59:18 +0100 Subject: [PATCH] remove use of `akka.actor.timeout` property for `ask` --- .../akka/migration/AskableActorRef.scala | 2 +- .../src/test/scala/akka/pattern/AskSpec.scala | 3 +- .../main/scala/akka/pattern/AskSupport.scala | 4 +-- .../main/scala/akka/pattern/Patterns.scala | 33 ------------------- .../src/main/scala/akka/pattern/package.scala | 17 +++++----- .../docs/actor/UntypedActorDocTestBase.java | 4 +-- .../project/migration-guide-1.3.x-2.0.x.rst | 15 ++++++--- akka-docs/scala/actors.rst | 3 -- 8 files changed, 25 insertions(+), 56 deletions(-) diff --git a/akka-actor-migration/src/main/scala/akka/migration/AskableActorRef.scala b/akka-actor-migration/src/main/scala/akka/migration/AskableActorRef.scala index caf8921812..fc4f28cd8b 100644 --- a/akka-actor-migration/src/main/scala/akka/migration/AskableActorRef.scala +++ b/akka-actor-migration/src/main/scala/akka/migration/AskableActorRef.scala @@ -37,7 +37,7 @@ class AskableActorRef(val actorRef: ActorRef) { * * [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) + def ask(message: Any)(implicit timeout: Timeout): Future[Any] = akka.pattern.ask(actorRef, message)(timeout) /** * Sends a message asynchronously and returns a [[akka.dispatch.Future]] diff --git a/akka-actor-tests/src/test/scala/akka/pattern/AskSpec.scala b/akka-actor-tests/src/test/scala/akka/pattern/AskSpec.scala index 44cdd91eba..ecb9690594 100644 --- a/akka-actor-tests/src/test/scala/akka/pattern/AskSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/pattern/AskSpec.scala @@ -4,6 +4,7 @@ package akka.pattern import akka.testkit.AkkaSpec +import akka.util.duration._ class AskSpec extends AkkaSpec { @@ -11,7 +12,7 @@ class AskSpec extends AkkaSpec { "return broken promises on DeadLetters" in { val dead = system.actorFor("/system/deadLetters") - val f = dead ask 42 + val f = dead.ask(42)(1 second) f.isCompleted must be(true) f.value.get match { case Left(_: AskTimeoutException) ⇒ diff --git a/akka-actor/src/main/scala/akka/pattern/AskSupport.scala b/akka-actor/src/main/scala/akka/pattern/AskSupport.scala index 57dec1debe..492bb46ed8 100644 --- a/akka-actor/src/main/scala/akka/pattern/AskSupport.scala +++ b/akka-actor/src/main/scala/akka/pattern/AskSupport.scala @@ -51,7 +51,7 @@ object AskSupport { * * [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) + def ask(message: Any)(implicit timeout: Timeout): Future[Any] = akka.pattern.ask(actorRef, message)(timeout) /** * Sends a message asynchronously and returns a [[akka.dispatch.Future]] @@ -81,7 +81,7 @@ object AskSupport { * * [see the [[akka.dispatch.Future]] companion object for a description of `flow`] */ - def ?(message: Any)(implicit timeout: Timeout = null): Future[Any] = akka.pattern.ask(actorRef, message)(timeout) + def ?(message: Any)(implicit timeout: Timeout): Future[Any] = akka.pattern.ask(actorRef, message)(timeout) } /** diff --git a/akka-actor/src/main/scala/akka/pattern/Patterns.scala b/akka-actor/src/main/scala/akka/pattern/Patterns.scala index b1498ee2d0..8c52f096f1 100644 --- a/akka-actor/src/main/scala/akka/pattern/Patterns.scala +++ b/akka-actor/src/main/scala/akka/pattern/Patterns.scala @@ -9,39 +9,6 @@ object Patterns { import akka.pattern.{ ask ⇒ scalaAsk } import akka.util.{ Timeout, Duration } - /** - * Java API for `akka.pattern.ask`: - * 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)`). - * - * This variant will use the `akka.actor.timeout` from the configuration. - * - * Warning: - * 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. - * - * Recommended usage: - * - * {{{ - * final Future f = Patterns.ask(worker, request, timeout); - * f.onSuccess(new Procedure() { - * public void apply(Object o) { - * nextActor.tell(new EnrichedResult(request, o)); - * } - * }); - * }}} - */ - def ask(actor: ActorRef, message: Any): Future[AnyRef] = scalaAsk(actor, message).asInstanceOf[Future[AnyRef]] - /** * Java API for `akka.pattern.ask`: * Sends a message asynchronously and returns a [[akka.dispatch.Future]] diff --git a/akka-actor/src/main/scala/akka/pattern/package.scala b/akka-actor/src/main/scala/akka/pattern/package.scala index 4abb7c41d7..2689b72548 100644 --- a/akka-actor/src/main/scala/akka/pattern/package.scala +++ b/akka-actor/src/main/scala/akka/pattern/package.scala @@ -87,20 +87,19 @@ package object pattern { * * [see [[akka.dispatch.Future]] for a description of `flow`] */ - def ask(actorRef: ActorRef, message: Any)(implicit timeout: Timeout = null): Future[Any] = actorRef match { + def ask(actorRef: ActorRef, message: Any)(implicit timeout: Timeout): Future[Any] = actorRef match { case ref: InternalActorRef if ref.isTerminated ⇒ actorRef.tell(message) Promise.failed(new AskTimeoutException("sending to terminated ref breaks promises"))(ref.provider.dispatcher) case ref: InternalActorRef ⇒ val provider = ref.provider - (if (timeout == null) provider.settings.ActorTimeout else timeout) match { - case t if t.duration.length <= 0 ⇒ - actorRef.tell(message) - Promise.failed(new AskTimeoutException("not asking with negative timeout"))(provider.dispatcher) - case t ⇒ - val a = AskSupport.createAsker(provider, t) - actorRef.tell(message, a) - a.result + if (timeout.duration.length <= 0) { + actorRef.tell(message) + Promise.failed(new AskTimeoutException("not asking with negative timeout"))(provider.dispatcher) + } else { + val a = AskSupport.createAsker(provider, timeout) + actorRef.tell(message, a) + a.result } case _ ⇒ throw new IllegalArgumentException("incompatible ActorRef " + actorRef) } diff --git a/akka-docs/java/code/akka/docs/actor/UntypedActorDocTestBase.java b/akka-docs/java/code/akka/docs/actor/UntypedActorDocTestBase.java index eb8245ee57..a72c828862 100644 --- a/akka-docs/java/code/akka/docs/actor/UntypedActorDocTestBase.java +++ b/akka-docs/java/code/akka/docs/actor/UntypedActorDocTestBase.java @@ -231,8 +231,8 @@ public class UntypedActorDocTestBase { final Timeout t = new Timeout(Duration.create(5, TimeUnit.SECONDS)); final ArrayList> futures = new ArrayList>(); - futures.add(ask(actorA, "request")); // using `akka.actor.timeout` from config - futures.add(ask(actorB, "reqeest", t)); // using explicit timeout from above + futures.add(ask(actorA, "request", 1000)); // using 1000ms timeout + futures.add(ask(actorB, "reqeest", t)); // using timeout from above final Future> aggregate = Futures.sequence(futures, system.dispatcher()); diff --git a/akka-docs/project/migration-guide-1.3.x-2.0.x.rst b/akka-docs/project/migration-guide-1.3.x-2.0.x.rst index 273d44c1d1..4dd9b8cc39 100644 --- a/akka-docs/project/migration-guide-1.3.x-2.0.x.rst +++ b/akka-docs/project/migration-guide-1.3.x-2.0.x.rst @@ -207,6 +207,9 @@ reply to be received; it is independent of the timeout applied when awaiting completion of the :class:`Future`, however, the actor will complete the :class:`Future` with an :class:`AskTimeoutException` when it stops itself. +Since there is no good library default value for the ask-timeout, specification +of a timeout is required for all usages as shown below. + Also, since the ``ask`` feature is coupling futures and actors, it is no longer offered on the :class:`ActorRef` itself, but instead as a use pattern to be imported. While Scala’s implicit conversions enable transparent replacement, @@ -221,15 +224,17 @@ v2.0 (Scala):: import akka.pattern.ask - actorRef ? message - ask(actorRef, message) // will use `akka.actor.timeout` or implicit Timeout - ask(actorRef, message)(timeout) + implicit val timeout: Timeout = ... + actorRef ? message // uses implicit timeout + actorRef ask message // uses implicit timeout + actorRef.ask(message)(timeout) // uses explicit timeout + ask(actorRef, message) // uses implicit timeout + ask(actorRef, message)(timeout) // uses explicit timeout v2.0 (Java):: import akka.pattern.Patterns; - Patterns.ask(actorRef, message) // will use `akka.actor.timeout` Patterns.ask(actorRef, message, timeout) Documentation: @@ -358,7 +363,7 @@ v2.0:: import akka.event.Logging val log = Logging(context.system, this) // will include system name in message source - val log = Logging(system.eventStream, this) // will not include system name + val log = Logging(system.eventStream, getClass.getName) // will not include system name log.error(exception, message) log.warning(message) log.info(message) diff --git a/akka-docs/scala/actors.rst b/akka-docs/scala/actors.rst index da0ae5b91e..fe1b134b65 100644 --- a/akka-docs/scala/actors.rst +++ b/akka-docs/scala/actors.rst @@ -389,9 +389,6 @@ taken from one of the following locations in order of precedence: .. includecode:: code/akka/docs/actor/ActorDocSpec.scala#using-implicit-timeout -3. actor system’s default value from ``akka.actor.timeout`` setting for - :meth:`ask` methods - See :ref:`futures-scala` for more information on how to await or query a future.