diff --git a/akka-actor-tests/src/test/java/akka/dispatch/JavaFutureTests.java b/akka-actor-tests/src/test/java/akka/dispatch/JavaFutureTests.java index 3f56ae2781..cb9b99fadc 100644 --- a/akka-actor-tests/src/test/java/akka/dispatch/JavaFutureTests.java +++ b/akka-actor-tests/src/test/java/akka/dispatch/JavaFutureTests.java @@ -3,6 +3,8 @@ package akka.dispatch; import akka.actor.Timeout; import akka.actor.ActorSystem; +import akka.japi.*; +import akka.util.Duration; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -13,23 +15,19 @@ import java.lang.Iterable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import akka.japi.Function; -import akka.japi.Function2; -import akka.japi.Procedure; -import akka.japi.Option; import akka.testkit.AkkaSpec; public class JavaFutureTests { private static ActorSystem system; - private static FutureFactory ff; private static Timeout t; + + private final Duration timeout = Duration.create(5, TimeUnit.SECONDS); @BeforeClass public static void beforeAll() { system = ActorSystem.create("JavaFutureTests", AkkaSpec.testConf()); t = system.settings().ActorTimeout(); - ff = new FutureFactory(system.dispatcher(), t); } @AfterClass @@ -41,96 +39,76 @@ public class JavaFutureTests { @Test public void mustBeAbleToMapAFuture() { - Future f1 = ff.future(new Callable() { + Future f1 = Futures.future(new Callable() { public String call() { return "Hello"; } - }); + }, system.dispatcher()); Future f2 = f1.map(new Function() { public String apply(String s) { return s + " World"; } - }, t); + }); - assertEquals("Hello World", f2.get()); + assertEquals("Hello World", Await.result(f2, timeout)); } @Test public void mustBeAbleToExecuteAnOnResultCallback() throws Throwable { final CountDownLatch latch = new CountDownLatch(1); - Promise cf = new akka.dispatch.DefaultPromise(1000, TimeUnit.MILLISECONDS, system - .dispatcherFactory().defaultGlobalDispatcher()); + Promise cf = Futures.promise(system.dispatcher()); Future f = cf; - f.onResult(new Procedure() { - public void apply(String result) { - if (result.equals("foo")) - latch.countDown(); - } + f.onSuccess(new Procedure() { + public void apply(String result) { + if (result.equals("foo")) + latch.countDown(); + } }); - cf.completeWithResult("foo"); + cf.success("foo"); assertTrue(latch.await(5000, TimeUnit.MILLISECONDS)); - assertEquals(f.get(), "foo"); + assertEquals(Await.result(f, timeout), "foo"); } @Test public void mustBeAbleToExecuteAnOnExceptionCallback() throws Throwable { final CountDownLatch latch = new CountDownLatch(1); - Promise cf = new akka.dispatch.DefaultPromise(1000, TimeUnit.MILLISECONDS, system - .dispatcherFactory().defaultGlobalDispatcher()); + Promise cf = Futures.promise(system.dispatcher()); Future f = cf; - f.onException(new Procedure() { - public void apply(Throwable t) { - if (t instanceof NullPointerException) - latch.countDown(); - } + f.onFailure(new Procedure() { + public void apply(Throwable t) { + if (t instanceof NullPointerException) + latch.countDown(); + } }); Throwable exception = new NullPointerException(); - cf.completeWithException(exception); + cf.failure(exception); assertTrue(latch.await(5000, TimeUnit.MILLISECONDS)); - assertEquals(f.exception().get(), exception); - } - - @Test - public void mustBeAbleToExecuteAnOnTimeoutCallback() throws Throwable { - final CountDownLatch latch = new CountDownLatch(1); - Promise cf = new akka.dispatch.DefaultPromise(1000, TimeUnit.MILLISECONDS, system - .dispatcherFactory().defaultGlobalDispatcher()); - Future f = cf; - f.onTimeout(new Procedure>() { - public void apply(Future future) { - latch.countDown(); - } - }); - - assertTrue(latch.await(5000, TimeUnit.MILLISECONDS)); - assertTrue(f.value().isEmpty()); + assertEquals(f.value().get().left().get(), exception); } @Test public void mustBeAbleToExecuteAnOnCompleteCallback() throws Throwable { final CountDownLatch latch = new CountDownLatch(1); - Promise cf = new akka.dispatch.DefaultPromise(1000, TimeUnit.MILLISECONDS, system - .dispatcherFactory().defaultGlobalDispatcher()); + Promise cf = Futures.promise(system.dispatcher()); Future f = cf; - f.onComplete(new Procedure>() { - public void apply(akka.dispatch.Future future) { + f.onComplete(new Procedure2() { + public void apply(Throwable t, String r) { latch.countDown(); } }); - cf.completeWithResult("foo"); + cf.success("foo"); assertTrue(latch.await(5000, TimeUnit.MILLISECONDS)); - assertEquals(f.get(), "foo"); + assertEquals(Await.result(f, timeout), "foo"); } @Test public void mustBeAbleToForeachAFuture() throws Throwable { final CountDownLatch latch = new CountDownLatch(1); - Promise cf = new akka.dispatch.DefaultPromise(1000, TimeUnit.MILLISECONDS, system - .dispatcherFactory().defaultGlobalDispatcher()); + Promise cf = Futures.promise(system.dispatcher()); Future f = cf; f.foreach(new Procedure() { public void apply(String future) { @@ -138,50 +116,47 @@ public class JavaFutureTests { } }); - cf.completeWithResult("foo"); + cf.success("foo"); assertTrue(latch.await(5000, TimeUnit.MILLISECONDS)); - assertEquals(f.get(), "foo"); + assertEquals(Await.result(f, timeout), "foo"); } @Test public void mustBeAbleToFlatMapAFuture() throws Throwable { final CountDownLatch latch = new CountDownLatch(1); - Promise cf = new akka.dispatch.DefaultPromise(1000, TimeUnit.MILLISECONDS, system - .dispatcherFactory().defaultGlobalDispatcher()); - cf.completeWithResult("1000"); + Promise cf = Futures.promise(system.dispatcher()); + cf.success("1000"); Future f = cf; Future r = f.flatMap(new Function>() { public Future apply(String r) { latch.countDown(); - Promise cf = new akka.dispatch.DefaultPromise(1000, TimeUnit.MILLISECONDS, system - .dispatcherFactory().defaultGlobalDispatcher()); - cf.completeWithResult(Integer.parseInt(r)); + Promise cf = Futures.promise(system.dispatcher()); + cf.success(Integer.parseInt(r)); return cf; } - }, t); + }); - assertEquals(f.get(), "1000"); - assertEquals(r.get().intValue(), 1000); + assertEquals(Await.result(f, timeout), "1000"); + assertEquals(Await.result(r, timeout).intValue(), 1000); assertTrue(latch.await(5000, TimeUnit.MILLISECONDS)); } @Test public void mustBeAbleToFilterAFuture() throws Throwable { final CountDownLatch latch = new CountDownLatch(1); - Promise cf = new akka.dispatch.DefaultPromise(1000, TimeUnit.MILLISECONDS, system - .dispatcherFactory().defaultGlobalDispatcher()); + Promise cf = Futures.promise(system.dispatcher()); Future f = cf; Future r = f.filter(new Function() { public Boolean apply(String r) { latch.countDown(); return r.equals("foo"); } - }, t); + }); - cf.completeWithResult("foo"); + cf.success("foo"); assertTrue(latch.await(5000, TimeUnit.MILLISECONDS)); - assertEquals(f.get(), "foo"); - assertEquals(r.get(), "foo"); + assertEquals(Await.result(f, timeout), "foo"); + assertEquals(Await.result(r, timeout), "foo"); } // TODO: Improve this test, perhaps with an Actor @@ -192,16 +167,16 @@ public class JavaFutureTests { for (int i = 0; i < 10; i++) { listExpected.add("test"); - listFutures.add(ff.future(new Callable() { + listFutures.add(Futures.future(new Callable() { public String call() { return "test"; } - })); + }, system.dispatcher())); } - Future> futureList = ff.sequence(listFutures, t); + Future> futureList = Futures.sequence(listFutures, system.dispatcher()); - assertEquals(futureList.get(), listExpected); + assertEquals(Await.result(futureList, timeout), listExpected); } // TODO: Improve this test, perhaps with an Actor @@ -212,20 +187,20 @@ public class JavaFutureTests { for (int i = 0; i < 10; i++) { expected.append("test"); - listFutures.add(ff.future(new Callable() { + listFutures.add(Futures.future(new Callable() { public String call() { return "test"; } - })); + }, system.dispatcher())); } - Future result = ff.fold("", 15000, listFutures, new Function2() { + Future result = Futures.fold("", listFutures, new Function2() { public String apply(String r, String t) { return r + t; } - }); + }, system.dispatcher()); - assertEquals(result.get(), expected.toString()); + assertEquals(Await.result(result, timeout), expected.toString()); } @Test @@ -235,20 +210,20 @@ public class JavaFutureTests { for (int i = 0; i < 10; i++) { expected.append("test"); - listFutures.add(ff.future(new Callable() { + listFutures.add(Futures.future(new Callable() { public String call() { return "test"; } - })); + }, system.dispatcher())); } - Future result = ff.reduce(listFutures, 15000, new Function2() { + Future result = Futures.reduce(listFutures, new Function2() { public String apply(String r, String t) { return r + t; } - }); + }, system.dispatcher()); - assertEquals(result.get(), expected.toString()); + assertEquals(Await.result(result, timeout), expected.toString()); } @Test @@ -261,17 +236,17 @@ public class JavaFutureTests { listStrings.add("test"); } - Future> result = ff.traverse(listStrings, t, new Function>() { + Future> result = Futures.traverse(listStrings, new Function>() { public Future apply(final String r) { - return ff.future(new Callable() { + return Futures.future(new Callable() { public String call() { return r.toUpperCase(); } - }); + }, system.dispatcher()); } - }); + }, system.dispatcher()); - assertEquals(result.get(), expectedStrings); + assertEquals(Await.result(result, timeout), expectedStrings); } @Test @@ -279,20 +254,28 @@ public class JavaFutureTests { LinkedList> listFutures = new LinkedList>(); for (int i = 0; i < 10; i++) { final Integer fi = i; - listFutures.add(ff.future(new Callable() { + listFutures.add(Futures.future(new Callable() { public Integer call() { return fi; } - })); + }, system.dispatcher())); } final Integer expect = 5; - Future> f = ff.find(listFutures, new Function() { + Future> f = Futures.find(listFutures, new Function() { public Boolean apply(Integer i) { return i == 5; } - }, t); + }, system.dispatcher()); - final Integer got = f.get().get(); - assertEquals(expect, got); + assertEquals(expect, Await.result(f, timeout)); + } + + @Test + public void BlockMustBeCallable() { + Promise p = Futures.promise(system.dispatcher()); + Duration d = Duration.create(1, TimeUnit.SECONDS); + p.success("foo"); + Await.ready(p, d); + assertEquals(Await.result(p, d), "foo"); } } diff --git a/akka-actor-tests/src/test/scala/akka/actor/ActorFireForgetRequestReplySpec.scala b/akka-actor-tests/src/test/scala/akka/actor/ActorFireForgetRequestReplySpec.scala index e374453901..c059497259 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/ActorFireForgetRequestReplySpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/ActorFireForgetRequestReplySpec.scala @@ -7,7 +7,7 @@ package akka.actor import akka.testkit._ import org.scalatest.BeforeAndAfterEach import akka.util.duration._ -import akka.dispatch.Dispatchers +import akka.dispatch.Await object ActorFireForgetRequestReplySpec { @@ -81,7 +81,7 @@ class ActorFireForgetRequestReplySpec extends AkkaSpec with BeforeAndAfterEach w "should shutdown crashed temporary actor" in { filterEvents(EventFilter[Exception]("Expected exception")) { val supervisor = system.actorOf(Props[Supervisor].withFaultHandler(OneForOneStrategy(List(classOf[Exception]), Some(0)))) - val actor = (supervisor ? Props[CrashingActor]).as[ActorRef].get + val actor = Await.result((supervisor ? Props[CrashingActor]).mapTo[ActorRef], timeout.duration) actor.isTerminated must be(false) actor ! "Die" state.finished.await diff --git a/akka-actor-tests/src/test/scala/akka/actor/ActorLifeCycleSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/ActorLifeCycleSpec.scala index 0bb1682b81..b203ff256f 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/ActorLifeCycleSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/ActorLifeCycleSpec.scala @@ -11,6 +11,7 @@ import akka.actor.Actor._ import akka.testkit._ import akka.util.duration._ import java.util.concurrent.atomic._ +import akka.dispatch.Await object ActorLifeCycleSpec { @@ -40,7 +41,7 @@ class ActorLifeCycleSpec extends AkkaSpec with BeforeAndAfterEach with ImplicitS override def preRestart(reason: Throwable, message: Option[Any]) { report("preRestart") } override def postRestart(reason: Throwable) { report("postRestart") } }) - val restarter = (supervisor ? restarterProps).as[ActorRef].get + val restarter = Await.result((supervisor ? restarterProps).mapTo[ActorRef], timeout.duration) expectMsg(("preStart", id, 0)) restarter ! Kill @@ -71,7 +72,7 @@ class ActorLifeCycleSpec extends AkkaSpec with BeforeAndAfterEach with ImplicitS val supervisor = system.actorOf(Props[Supervisor].withFaultHandler(OneForOneStrategy(List(classOf[Exception]), Some(3)))) val gen = new AtomicInteger(0) val restarterProps = Props(new LifeCycleTestActor(testActor, id, gen)) - val restarter = (supervisor ? restarterProps).as[ActorRef].get + val restarter = Await.result((supervisor ? restarterProps).mapTo[ActorRef], timeout.duration) expectMsg(("preStart", id, 0)) restarter ! Kill @@ -101,7 +102,7 @@ class ActorLifeCycleSpec extends AkkaSpec with BeforeAndAfterEach with ImplicitS val supervisor = system.actorOf(Props[Supervisor].withFaultHandler(OneForOneStrategy(List(classOf[Exception]), Some(3)))) val gen = new AtomicInteger(0) val props = Props(new LifeCycleTestActor(testActor, id, gen)) - val a = (supervisor ? props).as[ActorRef].get + val a = Await.result((supervisor ? props).mapTo[ActorRef], timeout.duration) expectMsg(("preStart", id, 0)) a ! "status" expectMsg(("OK", id, 0)) diff --git a/akka-actor-tests/src/test/scala/akka/actor/ActorLookupSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/ActorLookupSpec.scala index e2ec943789..6ef64df1b2 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/ActorLookupSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/ActorLookupSpec.scala @@ -5,6 +5,7 @@ package akka.actor import akka.testkit._ import akka.util.duration._ +import akka.dispatch.Await object ActorLookupSpec { @@ -36,7 +37,7 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout { val c1 = system.actorOf(p, "c1") val c2 = system.actorOf(p, "c2") - val c21 = (c2 ? Create("c21")).as[ActorRef].get + val c21 = Await.result((c2 ? Create("c21")).mapTo[ActorRef], timeout.duration) val user = system.asInstanceOf[ActorSystemImpl].guardian val syst = system.asInstanceOf[ActorSystemImpl].systemGuardian @@ -122,7 +123,7 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout { f.isCompleted must be === false a ! 42 f.isCompleted must be === true - f.get must be === 42 + Await.result(f, timeout.duration) must be === 42 // clean-up is run as onComplete callback, i.e. dispatched on another thread awaitCond(system.actorFor(a.path) == system.deadLetters, 1 second) } @@ -135,7 +136,7 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout { "find actors by looking up their path" in { def check(looker: ActorRef, pathOf: ActorRef, result: ActorRef) { - (looker ? LookupPath(pathOf.path)).get must be === result + Await.result(looker ? LookupPath(pathOf.path), timeout.duration) must be === result } for { looker ← all @@ -145,8 +146,8 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout { "find actors by looking up their string representation" in { def check(looker: ActorRef, pathOf: ActorRef, result: ActorRef) { - (looker ? LookupString(pathOf.path.toString)).get must be === result - (looker ? LookupString(pathOf.path.toString + "/")).get must be === result + Await.result(looker ? LookupString(pathOf.path.toString), timeout.duration) must be === result + Await.result(looker ? LookupString(pathOf.path.toString + "/"), timeout.duration) must be === result } for { looker ← all @@ -156,8 +157,8 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout { "find actors by looking up their root-anchored relative path" in { def check(looker: ActorRef, pathOf: ActorRef, result: ActorRef) { - (looker ? LookupString(pathOf.path.elements.mkString("/", "/", ""))).get must be === result - (looker ? LookupString(pathOf.path.elements.mkString("/", "/", "/"))).get must be === result + Await.result(looker ? LookupString(pathOf.path.elements.mkString("/", "/", "")), timeout.duration) must be === result + Await.result(looker ? LookupString(pathOf.path.elements.mkString("/", "/", "/")), timeout.duration) must be === result } for { looker ← all @@ -167,9 +168,9 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout { "find actors by looking up their relative path" in { def check(looker: ActorRef, result: ActorRef, elems: String*) { - (looker ? LookupElems(elems)).get must be === result - (looker ? LookupString(elems mkString "/")).get must be === result - (looker ? LookupString(elems mkString ("", "/", "/"))).get must be === result + Await.result(looker ? LookupElems(elems), timeout.duration) must be === result + Await.result(looker ? LookupString(elems mkString "/"), timeout.duration) must be === result + Await.result(looker ? LookupString(elems mkString ("", "/", "/")), timeout.duration) must be === result } check(c1, user, "..") for { @@ -184,11 +185,11 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout { "find system-generated actors" in { def check(target: ActorRef) { for (looker ← all) { - (looker ? LookupPath(target.path)).get must be === target - (looker ? LookupString(target.path.toString)).get must be === target - (looker ? LookupString(target.path.toString + "/")).get must be === target - (looker ? LookupString(target.path.elements.mkString("/", "/", ""))).get must be === target - if (target != root) (looker ? LookupString(target.path.elements.mkString("/", "/", "/"))).get must be === target + Await.result(looker ? LookupPath(target.path), timeout.duration) must be === target + Await.result(looker ? LookupString(target.path.toString), timeout.duration) must be === target + Await.result(looker ? LookupString(target.path.toString + "/"), timeout.duration) must be === target + Await.result(looker ? LookupString(target.path.elements.mkString("/", "/", "")), timeout.duration) must be === target + if (target != root) Await.result(looker ? LookupString(target.path.elements.mkString("/", "/", "/")), timeout.duration) must be === target } } for (target ← Seq(root, syst, user, system.deadLetters)) check(target) @@ -198,7 +199,7 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout { import scala.collection.JavaConverters._ def checkOne(looker: ActorRef, query: Query) { - (looker ? query).get must be === system.deadLetters + Await.result(looker ? query, timeout.duration) must be === system.deadLetters } def check(looker: ActorRef) { Seq(LookupString("a/b/c"), @@ -217,21 +218,21 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout { val f = c1 ? GetSender(testActor) val a = expectMsgType[ActorRef] a.path.elements.head must be === "temp" - (c2 ? LookupPath(a.path)).get must be === a - (c2 ? LookupString(a.path.toString)).get must be === a - (c2 ? LookupString(a.path.elements.mkString("/", "/", ""))).get must be === a - (c2 ? LookupString("../../" + a.path.elements.mkString("/"))).get must be === a - (c2 ? LookupString(a.path.toString + "/")).get must be === a - (c2 ? LookupString(a.path.elements.mkString("/", "/", "") + "/")).get must be === a - (c2 ? LookupString("../../" + a.path.elements.mkString("/") + "/")).get must be === a - (c2 ? LookupElems(Seq("..", "..") ++ a.path.elements)).get must be === a - (c2 ? LookupElems(Seq("..", "..") ++ a.path.elements :+ "")).get must be === a + Await.result(c2 ? LookupPath(a.path), timeout.duration) must be === a + Await.result(c2 ? LookupString(a.path.toString), timeout.duration) must be === a + Await.result(c2 ? LookupString(a.path.elements.mkString("/", "/", "")), timeout.duration) must be === a + Await.result(c2 ? LookupString("../../" + a.path.elements.mkString("/")), timeout.duration) must be === a + Await.result(c2 ? LookupString(a.path.toString + "/"), timeout.duration) must be === a + Await.result(c2 ? LookupString(a.path.elements.mkString("/", "/", "") + "/"), timeout.duration) must be === a + Await.result(c2 ? LookupString("../../" + a.path.elements.mkString("/") + "/"), timeout.duration) must be === a + Await.result(c2 ? LookupElems(Seq("..", "..") ++ a.path.elements), timeout.duration) must be === a + Await.result(c2 ? LookupElems(Seq("..", "..") ++ a.path.elements :+ ""), timeout.duration) must be === a f.isCompleted must be === false a ! 42 f.isCompleted must be === true - f.get must be === 42 + Await.result(f, timeout.duration) must be === 42 // clean-up is run as onComplete callback, i.e. dispatched on another thread - awaitCond((c2 ? LookupPath(a.path)).get == system.deadLetters, 1 second) + awaitCond(Await.result(c2 ? LookupPath(a.path), timeout.duration) == system.deadLetters, 1 second) } } diff --git a/akka-actor-tests/src/test/scala/akka/actor/ActorRefSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/ActorRefSpec.scala index 47dc5dcae8..248b665b63 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/ActorRefSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/ActorRefSpec.scala @@ -11,9 +11,9 @@ import akka.testkit._ import akka.util.duration._ import java.lang.IllegalStateException import akka.util.ReflectiveAccess -import akka.dispatch.{ DefaultPromise, Promise, Future } import akka.serialization.Serialization import java.util.concurrent.{ CountDownLatch, TimeUnit } +import akka.dispatch.{ Await, DefaultPromise, Promise, Future } object ActorRefSpec { @@ -117,18 +117,18 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout { def promiseIntercept(f: ⇒ Actor)(to: Promise[Actor]): Actor = try { val r = f - to.completeWithResult(r) + to.success(r) r } catch { case e ⇒ - to.completeWithException(e) + to.failure(e) throw e } def wrap[T](f: Promise[Actor] ⇒ T): T = { - val result = new DefaultPromise[Actor](10 * 60 * 1000) + val result = Promise[Actor]() val r = f(result) - result.get + Await.result(result, 1 minute) r } @@ -306,7 +306,7 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout { def receive = { case _ ⇒ sender ! nested } })) - val nested = (a ? "any").as[ActorRef].get + val nested = Await.result((a ? "any").mapTo[ActorRef], timeout.duration) a must not be null nested must not be null (a ne nested) must be === true @@ -314,13 +314,13 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout { "support advanced nested actorOfs" in { val a = system.actorOf(Props(new OuterActor(system.actorOf(Props(new InnerActor))))) - val inner = (a ? "innerself").as[Any].get + val inner = Await.result(a ? "innerself", timeout.duration) - (a ? a).as[ActorRef].get must be(a) - (a ? "self").as[ActorRef].get must be(a) + Await.result(a ? a, timeout.duration) must be(a) + Await.result(a ? "self", timeout.duration) must be(a) inner must not be a - (a ? "msg").as[String] must be === Some("msg") + Await.result(a ? "msg", timeout.duration) must be === "msg" } "support reply via sender" in { @@ -361,8 +361,8 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout { val fnull = (ref ? (null, timeout)).mapTo[String] ref ! PoisonPill - ffive.get must be("five") - fnull.get must be("null") + Await.result(ffive, timeout.duration) must be("five") + Await.result(fnull, timeout.duration) must be("null") awaitCond(ref.isTerminated, 2000 millis) } diff --git a/akka-actor-tests/src/test/scala/akka/actor/ActorTimeoutSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/ActorTimeoutSpec.scala index f97c68913e..4df3b0d5e9 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/ActorTimeoutSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/ActorTimeoutSpec.scala @@ -4,10 +4,11 @@ package akka.actor import org.scalatest.BeforeAndAfterAll -import akka.dispatch.FutureTimeoutException import akka.util.duration._ import akka.testkit.AkkaSpec import akka.testkit.DefaultTimeout +import java.util.concurrent.TimeoutException +import akka.dispatch.Await @org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) class ActorTimeoutSpec extends AkkaSpec with BeforeAndAfterAll with DefaultTimeout { @@ -28,7 +29,7 @@ class ActorTimeoutSpec extends AkkaSpec with BeforeAndAfterAll with DefaultTimeo val echo = actorWithTimeout(Timeout(12)) try { val f = echo ? "hallo" - intercept[FutureTimeoutException] { f.await } + intercept[TimeoutException] { Await.ready(f, system.settings.ActorTimeout.duration) } } finally { system.stop(echo) } } } @@ -39,7 +40,7 @@ class ActorTimeoutSpec extends AkkaSpec with BeforeAndAfterAll with DefaultTimeo val echo = actorWithTimeout(Props.defaultTimeout) try { val f = (echo ? "hallo").mapTo[String] - intercept[FutureTimeoutException] { f.await } + intercept[TimeoutException] { Await.ready(f, timeout.duration) } f.value must be(None) } finally { system.stop(echo) } } @@ -48,7 +49,11 @@ class ActorTimeoutSpec extends AkkaSpec with BeforeAndAfterAll with DefaultTimeo "use explicitly supplied timeout" in { within(testTimeout - 100.millis, testTimeout + 300.millis) { val echo = actorWithTimeout(Props.defaultTimeout) - try { (echo.?("hallo", testTimeout)).as[String] must be(None) } finally { system.stop(echo) } + val f = echo.?("hallo", testTimeout) + try { + intercept[TimeoutException] { Await.ready(f, testTimeout) } + f.value must be === None + } finally { system.stop(echo) } } } } diff --git a/akka-actor-tests/src/test/scala/akka/actor/DeathWatchSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/DeathWatchSpec.scala index c3fae8e8a8..5abf768c22 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/DeathWatchSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/DeathWatchSpec.scala @@ -8,6 +8,7 @@ import org.scalatest.BeforeAndAfterEach import akka.testkit._ import akka.util.duration._ import java.util.concurrent.atomic._ +import akka.dispatch.Await @org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) class DeathWatchSpec extends AkkaSpec with BeforeAndAfterEach with ImplicitSender with DefaultTimeout { @@ -78,13 +79,13 @@ class DeathWatchSpec extends AkkaSpec with BeforeAndAfterEach with ImplicitSende filterException[ActorKilledException] { val supervisor = system.actorOf(Props[Supervisor].withFaultHandler(OneForOneStrategy(List(classOf[Exception]), Some(2)))) val terminalProps = Props(context ⇒ { case x ⇒ context.sender ! x }) - val terminal = (supervisor ? terminalProps).as[ActorRef].get + val terminal = Await.result((supervisor ? terminalProps).mapTo[ActorRef], timeout.duration) val monitor = startWatching(terminal) terminal ! Kill terminal ! Kill - (terminal ? "foo").as[String] must be === Some("foo") + Await.result(terminal ? "foo", timeout.duration) must be === "foo" terminal ! Kill expectTerminationOf(terminal) @@ -105,11 +106,11 @@ class DeathWatchSpec extends AkkaSpec with BeforeAndAfterEach with ImplicitSende } })) - val failed = (supervisor ? Props.empty).as[ActorRef].get - val brother = (supervisor ? Props(new Actor { + val failed = Await.result((supervisor ? Props.empty).mapTo[ActorRef], timeout.duration) + val brother = Await.result((supervisor ? Props(new Actor { context.watch(failed) def receive = Actor.emptyBehavior - })).as[ActorRef].get + })).mapTo[ActorRef], timeout.duration) startWatching(brother) diff --git a/akka-actor-tests/src/test/scala/akka/actor/ForwardActorSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/ForwardActorSpec.scala index aa2cd4c9ff..12b0c796f6 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/ForwardActorSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/ForwardActorSpec.scala @@ -8,6 +8,7 @@ import akka.testkit._ import akka.util.duration._ import Actor._ import akka.util.Duration +import akka.dispatch.Await object ForwardActorSpec { val ExpectedMessage = "FOO" @@ -32,20 +33,21 @@ class ForwardActorSpec extends AkkaSpec { "A Forward Actor" must { - "forward actor reference when invoking forward on bang" in { + "forward actor reference when invoking forward on tell" in { val latch = new TestLatch(1) - val replyTo = system.actorOf(Props(new Actor { def receive = { case ExpectedMessage ⇒ latch.countDown() } })) + val replyTo = system.actorOf(Props(new Actor { def receive = { case ExpectedMessage ⇒ testActor ! ExpectedMessage } })) val chain = createForwardingChain(system) chain.tell(ExpectedMessage, replyTo) - latch.await(Duration(5, "s")) must be === true + expectMsg(5 seconds, ExpectedMessage) } - "forward actor reference when invoking forward on bang bang" in { + "forward actor reference when invoking forward on ask" in { val chain = createForwardingChain(system) - chain.ask(ExpectedMessage, 5000).get must be === ExpectedMessage + chain.ask(ExpectedMessage, 5000) onSuccess { case ExpectedMessage ⇒ testActor ! ExpectedMessage } + expectMsg(5 seconds, ExpectedMessage) } } } diff --git a/akka-actor-tests/src/test/scala/akka/actor/IOActor.scala b/akka-actor-tests/src/test/scala/akka/actor/IOActor.scala index 7047760371..9b1ba99459 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/IOActor.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/IOActor.scala @@ -8,9 +8,9 @@ import org.scalatest.BeforeAndAfterEach import akka.util.ByteString import akka.util.cps._ -import akka.dispatch.Future import scala.util.continuations._ import akka.testkit._ +import akka.dispatch.{ Await, Future } object IOActorSpec { import IO._ @@ -193,9 +193,9 @@ class IOActorSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeout { val f1 = client ? ByteString("Hello World!1") val f2 = client ? ByteString("Hello World!2") val f3 = client ? ByteString("Hello World!3") - f1.get must equal(ByteString("Hello World!1")) - f2.get must equal(ByteString("Hello World!2")) - f3.get must equal(ByteString("Hello World!3")) + Await.result(f1, timeout.duration) must equal(ByteString("Hello World!1")) + Await.result(f2, timeout.duration) must equal(ByteString("Hello World!2")) + Await.result(f3, timeout.duration) must equal(ByteString("Hello World!3")) system.stop(client) system.stop(server) system.stop(ioManager) @@ -209,7 +209,7 @@ class IOActorSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeout { val client = system.actorOf(Props(new SimpleEchoClient("localhost", 8065, ioManager))) val list = List.range(0, 1000) val f = Future.traverse(list)(i ⇒ client ? ByteString(i.toString)) - assert(f.get.size === 1000) + assert(Await.result(f, timeout.duration).size === 1000) system.stop(client) system.stop(server) system.stop(ioManager) @@ -223,7 +223,7 @@ class IOActorSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeout { val client = system.actorOf(Props(new SimpleEchoClient("localhost", 8066, ioManager))) val list = List.range(0, 1000) val f = Future.traverse(list)(i ⇒ client ? ByteString(i.toString)) - assert(f.get.size === 1000) + assert(Await.result(f, timeout.duration).size === 1000) system.stop(client) system.stop(server) system.stop(ioManager) @@ -239,17 +239,17 @@ class IOActorSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeout { val f1 = client1 ? (('set, "hello", ByteString("World"))) val f2 = client1 ? (('set, "test", ByteString("No one will read me"))) val f3 = client1 ? (('get, "hello")) - f2.await + Await.ready(f2, timeout.duration) val f4 = client2 ? (('set, "test", ByteString("I'm a test!"))) - f4.await + Await.ready(f4, timeout.duration) val f5 = client1 ? (('get, "test")) val f6 = client2 ? 'getall - f1.get must equal("OK") - f2.get must equal("OK") - f3.get must equal(ByteString("World")) - f4.get must equal("OK") - f5.get must equal(ByteString("I'm a test!")) - f6.get must equal(Map("hello" -> ByteString("World"), "test" -> ByteString("I'm a test!"))) + Await.result(f1, timeout.duration) must equal("OK") + Await.result(f2, timeout.duration) must equal("OK") + Await.result(f3, timeout.duration) must equal(ByteString("World")) + Await.result(f4, timeout.duration) must equal("OK") + Await.result(f5, timeout.duration) must equal(ByteString("I'm a test!")) + Await.result(f6, timeout.duration) must equal(Map("hello" -> ByteString("World"), "test" -> ByteString("I'm a test!"))) system.stop(client1) system.stop(client2) system.stop(server) diff --git a/akka-actor-tests/src/test/scala/akka/actor/LocalActorRefProviderSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/LocalActorRefProviderSpec.scala index ad92865124..bb3bf4c58e 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/LocalActorRefProviderSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/LocalActorRefProviderSpec.scala @@ -6,7 +6,7 @@ package akka.actor import akka.testkit._ import akka.util.duration._ -import akka.dispatch.Future +import akka.dispatch.{ Await, Future } @org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) class LocalActorRefProviderSpec extends AkkaSpec { @@ -32,7 +32,7 @@ class LocalActorRefProviderSpec extends AkkaSpec { val address = "new-actor" + i implicit val timeout = Timeout(5 seconds) val actors = for (j ← 1 to 4) yield Future(system.actorOf(Props(c ⇒ { case _ ⇒ }), address)) - val set = Set() ++ actors.map(_.await.value match { + val set = Set() ++ actors.map(a ⇒ Await.ready(a, timeout.duration).value match { case Some(Right(a: ActorRef)) ⇒ 1 case Some(Left(ex: InvalidActorNameException)) ⇒ 2 case x ⇒ x diff --git a/akka-actor-tests/src/test/scala/akka/actor/RestartStrategySpec.scala b/akka-actor-tests/src/test/scala/akka/actor/RestartStrategySpec.scala index f3f70a09d7..44f678d0a3 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/RestartStrategySpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/RestartStrategySpec.scala @@ -6,6 +6,7 @@ package akka.actor import java.lang.Thread.sleep import org.scalatest.BeforeAndAfterAll +import akka.dispatch.Await import akka.testkit.TestEvent._ import akka.testkit.EventFilter import java.util.concurrent.{ TimeUnit, CountDownLatch } @@ -51,7 +52,7 @@ class RestartStrategySpec extends AkkaSpec with DefaultTimeout { stopLatch.open } }) - val slave = (boss ? slaveProps).as[ActorRef].get + val slave = Await.result((boss ? slaveProps).mapTo[ActorRef], timeout.duration) slave ! Ping slave ! Crash @@ -86,7 +87,7 @@ class RestartStrategySpec extends AkkaSpec with DefaultTimeout { countDownLatch.countDown() } }) - val slave = (boss ? slaveProps).as[ActorRef].get + val slave = Await.result((boss ? slaveProps).mapTo[ActorRef], timeout.duration) (1 to 100) foreach { _ ⇒ slave ! Crash } assert(countDownLatch.await(120, TimeUnit.SECONDS)) @@ -124,7 +125,7 @@ class RestartStrategySpec extends AkkaSpec with DefaultTimeout { } } }) - val slave = (boss ? slaveProps).as[ActorRef].get + val slave = Await.result((boss ? slaveProps).mapTo[ActorRef], timeout.duration) slave ! Ping slave ! Crash @@ -175,7 +176,7 @@ class RestartStrategySpec extends AkkaSpec with DefaultTimeout { stopLatch.open } }) - val slave = (boss ? slaveProps).as[ActorRef].get + val slave = Await.result((boss ? slaveProps).mapTo[ActorRef], timeout.duration) slave ! Ping slave ! Crash @@ -227,7 +228,7 @@ class RestartStrategySpec extends AkkaSpec with DefaultTimeout { stopLatch.open } }) - val slave = (boss ? slaveProps).as[ActorRef].get + val slave = Await.result((boss ? slaveProps).mapTo[ActorRef], timeout.duration) slave ! Ping slave ! Crash diff --git a/akka-actor-tests/src/test/scala/akka/actor/SchedulerSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/SchedulerSpec.scala index ceeb768b6c..babed49370 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/SchedulerSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/SchedulerSpec.scala @@ -7,6 +7,7 @@ import akka.testkit.EventFilter import akka.util.duration._ import java.util.concurrent.{ CountDownLatch, ConcurrentLinkedQueue, TimeUnit } import akka.testkit.DefaultTimeout +import akka.dispatch.Await @org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) class SchedulerSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeout { @@ -113,7 +114,7 @@ class SchedulerSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeout override def postRestart(reason: Throwable) = restartLatch.open }) - val actor = (supervisor ? props).as[ActorRef].get + val actor = Await.result((supervisor ? props).mapTo[ActorRef], timeout.duration) collectCancellable(system.scheduler.schedule(500 milliseconds, 500 milliseconds, actor, Ping)) // appx 2 pings before crash diff --git a/akka-actor-tests/src/test/scala/akka/actor/SupervisorHierarchySpec.scala b/akka-actor-tests/src/test/scala/akka/actor/SupervisorHierarchySpec.scala index d51b333b35..fb34e2345b 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/SupervisorHierarchySpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/SupervisorHierarchySpec.scala @@ -7,6 +7,7 @@ package akka.actor import akka.testkit._ import java.util.concurrent.{ TimeUnit, CountDownLatch } +import akka.dispatch.Await object SupervisorHierarchySpec { class FireWorkerException(msg: String) extends Exception(msg) @@ -35,10 +36,10 @@ class SupervisorHierarchySpec extends AkkaSpec with DefaultTimeout { val boss = system.actorOf(Props[Supervisor].withFaultHandler(OneForOneStrategy(List(classOf[Exception]), None, None))) val managerProps = Props(new CountDownActor(countDown)).withFaultHandler(AllForOneStrategy(List(), None, None)) - val manager = (boss ? managerProps).as[ActorRef].get + val manager = Await.result((boss ? managerProps).mapTo[ActorRef], timeout.duration) val workerProps = Props(new CountDownActor(countDown)) - val workerOne, workerTwo, workerThree = (manager ? workerProps).as[ActorRef].get + val workerOne, workerTwo, workerThree = Await.result((manager ? workerProps).mapTo[ActorRef], timeout.duration) filterException[ActorKilledException] { workerOne ! Kill diff --git a/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala index 899626330f..63c3065231 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala @@ -4,7 +4,7 @@ package akka.actor import akka.testkit.{ filterEvents, EventFilter } -import akka.dispatch.{ PinnedDispatcher, Dispatchers } +import akka.dispatch.{ PinnedDispatcher, Dispatchers, Await } import java.util.concurrent.{ TimeUnit, CountDownLatch } import akka.testkit.AkkaSpec import akka.testkit.DefaultTimeout @@ -28,13 +28,11 @@ class SupervisorMiscSpec extends AkkaSpec with DefaultTimeout { } }) - val actor1 = (supervisor ? workerProps.withDispatcher(system.dispatcherFactory.newPinnedDispatcher("pinned"))).as[ActorRef].get + val actor1, actor2 = Await.result((supervisor ? workerProps.withDispatcher(system.dispatcherFactory.newPinnedDispatcher("pinned"))).mapTo[ActorRef], timeout.duration) - val actor2 = (supervisor ? workerProps.withDispatcher(system.dispatcherFactory.newPinnedDispatcher("pinned"))).as[ActorRef].get + val actor3 = Await.result((supervisor ? workerProps.withDispatcher(system.dispatcherFactory.newDispatcher("test").build)).mapTo[ActorRef], timeout.duration) - val actor3 = (supervisor ? workerProps.withDispatcher(system.dispatcherFactory.newDispatcher("test").build)).as[ActorRef].get - - val actor4 = (supervisor ? workerProps.withDispatcher(system.dispatcherFactory.newPinnedDispatcher("pinned"))).as[ActorRef].get + val actor4 = Await.result((supervisor ? workerProps.withDispatcher(system.dispatcherFactory.newPinnedDispatcher("pinned"))).mapTo[ActorRef], timeout.duration) actor1 ! Kill actor2 ! Kill @@ -42,10 +40,10 @@ class SupervisorMiscSpec extends AkkaSpec with DefaultTimeout { actor4 ! Kill countDownLatch.await(10, TimeUnit.SECONDS) - assert((actor1 ? "status").as[String].get == "OK", "actor1 is shutdown") - assert((actor2 ? "status").as[String].get == "OK", "actor2 is shutdown") - assert((actor3 ? "status").as[String].get == "OK", "actor3 is shutdown") - assert((actor4 ? "status").as[String].get == "OK", "actor4 is shutdown") + assert(Await.result(actor1 ? "status", timeout.duration) == "OK", "actor1 is shutdown") + assert(Await.result(actor2 ? "status", timeout.duration) == "OK", "actor2 is shutdown") + assert(Await.result(actor3 ? "status", timeout.duration) == "OK", "actor3 is shutdown") + assert(Await.result(actor4 ? "status", timeout.duration) == "OK", "actor4 is shutdown") } } } diff --git a/akka-actor-tests/src/test/scala/akka/actor/SupervisorSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/SupervisorSpec.scala index a78c8576c2..e68e6f3906 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/SupervisorSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/SupervisorSpec.scala @@ -7,11 +7,10 @@ package akka.actor import org.scalatest.BeforeAndAfterEach import akka.util.duration._ import akka.{ Die, Ping } -import akka.actor.Actor._ import akka.testkit.TestEvent._ import akka.testkit._ import java.util.concurrent.atomic.AtomicInteger -import java.util.concurrent.LinkedBlockingQueue +import akka.dispatch.Await object SupervisorSpec { val Timeout = 5 seconds @@ -73,7 +72,7 @@ class SupervisorSpec extends AkkaSpec with BeforeAndAfterEach with ImplicitSende // Creating actors and supervisors // ===================================================== - private def child(supervisor: ActorRef, props: Props): ActorRef = (supervisor ? props).as[ActorRef].get + private def child(supervisor: ActorRef, props: Props): ActorRef = Await.result((supervisor ? props).mapTo[ActorRef], props.timeout.duration) def temporaryActorAllForOne = { val supervisor = system.actorOf(Props[Supervisor].withFaultHandler(AllForOneStrategy(List(classOf[Exception]), Some(0)))) @@ -129,14 +128,14 @@ class SupervisorSpec extends AkkaSpec with BeforeAndAfterEach with ImplicitSende } def ping(pingPongActor: ActorRef) = { - (pingPongActor.?(Ping, TimeoutMillis)).as[String] must be === Some(PongMessage) + Await.result(pingPongActor.?(Ping, TimeoutMillis), TimeoutMillis millis) must be === PongMessage expectMsg(Timeout, PingMessage) } def kill(pingPongActor: ActorRef) = { val result = (pingPongActor ? (DieReply, TimeoutMillis)) expectMsg(Timeout, ExceptionMessage) - intercept[RuntimeException] { result.get } + intercept[RuntimeException] { Await.result(result, TimeoutMillis millis) } } "A supervisor" must { @@ -152,7 +151,7 @@ class SupervisorSpec extends AkkaSpec with BeforeAndAfterEach with ImplicitSende "not restart temporary actor" in { val (temporaryActor, _) = temporaryActorAllForOne - intercept[RuntimeException] { (temporaryActor.?(DieReply, TimeoutMillis)).get } + intercept[RuntimeException] { Await.result(temporaryActor.?(DieReply, TimeoutMillis), TimeoutMillis millis) } expectNoMsg(1 second) } @@ -293,16 +292,16 @@ class SupervisorSpec extends AkkaSpec with BeforeAndAfterEach with ImplicitSende throw e } }) - val dyingActor = (supervisor ? dyingProps).as[ActorRef].get + val dyingActor = Await.result((supervisor ? dyingProps).mapTo[ActorRef], timeout.duration) filterEvents(EventFilter[RuntimeException]("Expected", occurrences = 1), EventFilter[IllegalStateException]("error while creating actor", occurrences = 1)) { intercept[RuntimeException] { - (dyingActor.?(DieReply, TimeoutMillis)).get + Await.result(dyingActor.?(DieReply, TimeoutMillis), TimeoutMillis millis) } } - (dyingActor.?(Ping, TimeoutMillis)).as[String] must be === Some(PongMessage) + Await.result(dyingActor.?(Ping, TimeoutMillis), TimeoutMillis millis) must be === PongMessage inits.get must be(3) diff --git a/akka-actor-tests/src/test/scala/akka/actor/SupervisorTreeSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/SupervisorTreeSpec.scala index c3723b8564..3985f6ea48 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/SupervisorTreeSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/SupervisorTreeSpec.scala @@ -6,12 +6,12 @@ package akka.actor import org.scalatest.WordSpec import org.scalatest.matchers.MustMatchers import akka.util.duration._ -import akka.dispatch.Dispatchers import akka.actor.Actor._ import akka.testkit.{ TestKit, EventFilter, filterEvents, filterException } import akka.testkit.AkkaSpec import akka.testkit.ImplicitSender import akka.testkit.DefaultTimeout +import akka.dispatch.{ Await, Dispatchers } @org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) class SupervisorTreeSpec extends AkkaSpec with ImplicitSender with DefaultTimeout { @@ -28,8 +28,8 @@ class SupervisorTreeSpec extends AkkaSpec with ImplicitSender with DefaultTimeou override def preRestart(cause: Throwable, msg: Option[Any]) { testActor ! self.path } }).withFaultHandler(OneForOneStrategy(List(classOf[Exception]), 3, 1000)) val headActor = system.actorOf(p) - val middleActor = (headActor ? p).as[ActorRef].get - val lastActor = (middleActor ? p).as[ActorRef].get + val middleActor = Await.result((headActor ? p).mapTo[ActorRef], timeout.duration) + val lastActor = Await.result((middleActor ? p).mapTo[ActorRef], timeout.duration) middleActor ! Kill expectMsg(middleActor.path) diff --git a/akka-actor-tests/src/test/scala/akka/actor/Ticket669Spec.scala b/akka-actor-tests/src/test/scala/akka/actor/Ticket669Spec.scala index 032c2ade05..3b5f29c950 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/Ticket669Spec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/Ticket669Spec.scala @@ -10,6 +10,7 @@ import akka.testkit.{ TestKit, filterEvents, EventFilter } import akka.testkit.AkkaSpec import akka.testkit.ImplicitSender import akka.testkit.DefaultTimeout +import akka.dispatch.Await @org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) class Ticket669Spec extends AkkaSpec with BeforeAndAfterAll with ImplicitSender with DefaultTimeout { @@ -24,7 +25,7 @@ class Ticket669Spec extends AkkaSpec with BeforeAndAfterAll with ImplicitSender "be able to reply on failure during preRestart" in { filterEvents(EventFilter[Exception]("test", occurrences = 1)) { val supervisor = system.actorOf(Props[Supervisor].withFaultHandler(AllForOneStrategy(List(classOf[Exception]), 5, 10000))) - val supervised = (supervisor ? Props[Supervised]).as[ActorRef].get + val supervised = Await.result((supervisor ? Props[Supervised]).mapTo[ActorRef], timeout.duration) supervised.!("test")(testActor) expectMsg("failure1") @@ -35,7 +36,7 @@ class Ticket669Spec extends AkkaSpec with BeforeAndAfterAll with ImplicitSender "be able to reply on failure during postStop" in { filterEvents(EventFilter[Exception]("test", occurrences = 1)) { val supervisor = system.actorOf(Props[Supervisor].withFaultHandler(AllForOneStrategy(List(classOf[Exception]), Some(0), None))) - val supervised = (supervisor ? Props[Supervised]).as[ActorRef].get + val supervised = Await.result((supervisor ? Props[Supervised]).mapTo[ActorRef], timeout.duration) supervised.!("test")(testActor) expectMsg("failure2") diff --git a/akka-actor-tests/src/test/scala/akka/actor/TypedActorSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/TypedActorSpec.scala index b2265367c7..f50b9bd381 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/TypedActorSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/TypedActorSpec.scala @@ -7,7 +7,6 @@ package akka.actor import org.scalatest.{ BeforeAndAfterAll, BeforeAndAfterEach } import akka.util.Duration import akka.util.duration._ -import akka.dispatch.{ Dispatchers, Future, KeptPromise } import akka.serialization.Serialization import java.util.concurrent.atomic.AtomicReference import annotation.tailrec @@ -17,6 +16,7 @@ import akka.actor.TypedActor.{ PostRestart, PreRestart, PostStop, PreStart } import java.util.concurrent.{ TimeUnit, CountDownLatch } import akka.japi.{ Creator, Option ⇒ JOption } import akka.testkit.DefaultTimeout +import akka.dispatch.{ Await, Dispatchers, Future, Promise } object TypedActorSpec { @@ -85,7 +85,7 @@ object TypedActorSpec { def pigdog = "Pigdog" - def futurePigdog(): Future[String] = new KeptPromise(Right(pigdog)) + def futurePigdog(): Future[String] = Promise.successful(pigdog) def futurePigdog(delay: Long): Future[String] = { Thread.sleep(delay) @@ -94,7 +94,7 @@ object TypedActorSpec { def futurePigdog(delay: Long, numbered: Int): Future[String] = { Thread.sleep(delay) - new KeptPromise(Right(pigdog + numbered)) + Promise.successful(pigdog + numbered) } def futureComposePigdogFrom(foo: Foo): Future[String] = { @@ -247,7 +247,7 @@ class TypedActorSpec extends AkkaSpec with BeforeAndAfterEach with BeforeAndAfte val t = newFooBar val f = t.futurePigdog(200) f.isCompleted must be(false) - f.get must be("Pigdog") + Await.result(f, timeout.duration) must be("Pigdog") mustStop(t) } @@ -255,7 +255,7 @@ class TypedActorSpec extends AkkaSpec with BeforeAndAfterEach with BeforeAndAfte val t = newFooBar val futures = for (i ← 1 to 20) yield (i, t.futurePigdog(20, i)) for ((i, f) ← futures) { - f.get must be("Pigdog" + i) + Await.result(f, timeout.duration) must be("Pigdog" + i) } mustStop(t) } @@ -278,7 +278,7 @@ class TypedActorSpec extends AkkaSpec with BeforeAndAfterEach with BeforeAndAfte val t, t2 = newFooBar(Duration(2, "s")) val f = t.futureComposePigdogFrom(t2) f.isCompleted must be(false) - f.get must equal("PIGDOG") + Await.result(f, timeout.duration) must equal("PIGDOG") mustStop(t) mustStop(t2) } @@ -290,13 +290,13 @@ class TypedActorSpec extends AkkaSpec with BeforeAndAfterEach with BeforeAndAfte }).withFaultHandler(OneForOneStrategy { case e: IllegalStateException if e.getMessage == "expected" ⇒ FaultHandlingStrategy.Resume })) - val t = (boss ? Props().withTimeout(2 seconds)).as[Foo].get + val t = Await.result((boss ? Props().withTimeout(2 seconds)).mapTo[Foo], timeout.duration) t.incr() t.failingPigdog() t.read() must be(1) //Make sure state is not reset after failure - t.failingFuturePigdog.await.exception.get.getMessage must be("expected") + intercept[IllegalStateException] { Await.result(t.failingFuturePigdog, 2 seconds) }.getMessage must be("expected") t.read() must be(1) //Make sure state is not reset after failure (intercept[IllegalStateException] { t.failingJOptionPigdog }).getMessage must be("expected") @@ -323,7 +323,7 @@ class TypedActorSpec extends AkkaSpec with BeforeAndAfterEach with BeforeAndAfte val f2 = t.futurePigdog(0) f2.isCompleted must be(false) f.isCompleted must be(false) - f.get must equal(f2.get) + Await.result(f, timeout.duration) must equal(Await.result(f2, timeout.duration)) mustStop(t) } @@ -348,7 +348,7 @@ class TypedActorSpec extends AkkaSpec with BeforeAndAfterEach with BeforeAndAfte val results = for (i ← 1 to 120) yield (i, iterator.next.futurePigdog(200L, i)) - for ((i, r) ← results) r.get must be("Pigdog" + i) + for ((i, r) ← results) Await.result(r, timeout.duration) must be("Pigdog" + i) for (t ← thais) mustStop(t) } diff --git a/akka-actor-tests/src/test/scala/akka/actor/dispatch/ActorModelSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/dispatch/ActorModelSpec.scala index 5bcf8467c3..ced2b0d158 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/dispatch/ActorModelSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/dispatch/ActorModelSpec.scala @@ -31,7 +31,7 @@ object ActorModelSpec { case class Increment(counter: AtomicLong) extends ActorModelMessage - case class Await(latch: CountDownLatch) extends ActorModelMessage + case class AwaitLatch(latch: CountDownLatch) extends ActorModelMessage case class Meet(acknowledge: CountDownLatch, waitFor: CountDownLatch) extends ActorModelMessage @@ -68,7 +68,7 @@ object ActorModelSpec { } def receive = { - case Await(latch) ⇒ ack; latch.await(); busy.switchOff() + case AwaitLatch(latch) ⇒ ack; latch.await(); busy.switchOff() case Meet(sign, wait) ⇒ ack; sign.countDown(); wait.await(); busy.switchOff() case Wait(time) ⇒ ack; Thread.sleep(time); busy.switchOff() case WaitAck(time, l) ⇒ ack; Thread.sleep(time); l.countDown(); busy.switchOff() @@ -385,17 +385,17 @@ abstract class ActorModelSpec extends AkkaSpec with DefaultTimeout { val a = newTestActor(dispatcher) val f1 = a ? Reply("foo") val f2 = a ? Reply("bar") - val f3 = try { a ? Interrupt } catch { case ie: InterruptedException ⇒ new KeptPromise(Left(ActorInterruptedException(ie))) } + val f3 = try { a ? Interrupt } catch { case ie: InterruptedException ⇒ Promise.failed(ActorInterruptedException(ie)) } val f4 = a ? Reply("foo2") - val f5 = try { a ? Interrupt } catch { case ie: InterruptedException ⇒ new KeptPromise(Left(ActorInterruptedException(ie))) } + val f5 = try { a ? Interrupt } catch { case ie: InterruptedException ⇒ Promise.failed(ActorInterruptedException(ie)) } val f6 = a ? Reply("bar2") - assert(f1.get === "foo") - assert(f2.get === "bar") - assert(f4.get === "foo2") - assert(intercept[ActorInterruptedException](f3.get).getMessage === "Ping!") - assert(f6.get === "bar2") - assert(intercept[ActorInterruptedException](f5.get).getMessage === "Ping!") + assert(Await.result(f1, timeout.duration) === "foo") + assert(Await.result(f2, timeout.duration) === "bar") + assert(Await.result(f4, timeout.duration) === "foo2") + assert(intercept[ActorInterruptedException](Await.result(f3, timeout.duration)).getMessage === "Ping!") + assert(Await.result(f6, timeout.duration) === "bar2") + assert(intercept[ActorInterruptedException](Await.result(f5, timeout.duration)).getMessage === "Ping!") } } @@ -410,12 +410,12 @@ abstract class ActorModelSpec extends AkkaSpec with DefaultTimeout { val f5 = a ? ThrowException(new RemoteException("RemoteException")) val f6 = a ? Reply("bar2") - assert(f1.get === "foo") - assert(f2.get === "bar") - assert(f4.get === "foo2") - assert(f6.get === "bar2") - assert(f3.result === None) - assert(f5.result === None) + assert(Await.result(f1, timeout.duration) === "foo") + assert(Await.result(f2, timeout.duration) === "bar") + assert(Await.result(f4, timeout.duration) === "foo2") + assert(Await.result(f6, timeout.duration) === "bar2") + assert(f3.value.isEmpty) + assert(f5.value.isEmpty) } } } diff --git a/akka-actor-tests/src/test/scala/akka/actor/dispatch/DispatcherActorSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/dispatch/DispatcherActorSpec.scala index 3b3ba56c37..e559d63f4c 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/dispatch/DispatcherActorSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/dispatch/DispatcherActorSpec.scala @@ -3,11 +3,11 @@ package akka.actor.dispatch import java.util.concurrent.{ CountDownLatch, TimeUnit } import java.util.concurrent.atomic.{ AtomicBoolean, AtomicInteger } import akka.testkit.{ filterEvents, EventFilter, AkkaSpec } -import akka.dispatch.{ PinnedDispatcher, Dispatchers, Dispatcher } import akka.actor.{ Props, Actor } import akka.util.Duration import akka.util.duration._ import akka.testkit.DefaultTimeout +import akka.dispatch.{ Await, PinnedDispatcher, Dispatchers, Dispatcher } object DispatcherActorSpec { class TestActor extends Actor { @@ -44,8 +44,7 @@ class DispatcherActorSpec extends AkkaSpec with DefaultTimeout { "support ask/reply" in { val actor = system.actorOf(Props[TestActor].withDispatcher(system.dispatcherFactory.newDispatcher("test").build)) - val result = (actor ? "Hello").as[String] - assert("World" === result.get) + assert("World" === Await.result(actor ? "Hello", timeout.duration)) system.stop(actor) } @@ -67,7 +66,7 @@ class DispatcherActorSpec extends AkkaSpec with DefaultTimeout { case "ping" ⇒ if (works.get) latch.countDown() }).withDispatcher(throughputDispatcher)) - assert((slowOne ? "hogexecutor").get === "OK") + assert(Await.result(slowOne ? "hogexecutor", timeout.duration) === "OK") (1 to 100) foreach { _ ⇒ slowOne ! "ping" } fastOne ! "sabotage" start.countDown() diff --git a/akka-actor-tests/src/test/scala/akka/actor/dispatch/PinnedActorSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/dispatch/PinnedActorSpec.scala index fd26780d65..a194fb35b3 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/dispatch/PinnedActorSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/dispatch/PinnedActorSpec.scala @@ -3,10 +3,10 @@ package akka.actor.dispatch import java.util.concurrent.{ CountDownLatch, TimeUnit } import akka.testkit._ -import akka.dispatch.{ PinnedDispatcher, Dispatchers } import akka.actor.{ Props, Actor } import akka.testkit.AkkaSpec import org.scalatest.BeforeAndAfterEach +import akka.dispatch.{ Await, PinnedDispatcher, Dispatchers } object PinnedActorSpec { class TestActor extends Actor { @@ -35,8 +35,7 @@ class PinnedActorSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTimeo "support ask/reply" in { val actor = system.actorOf(Props[TestActor].withDispatcher(system.dispatcherFactory.newPinnedDispatcher("test"))) - val result = (actor ? "Hello").as[String] - assert("World" === result.get) + assert("World" === Await.result(actor ? "Hello", timeout.duration)) system.stop(actor) } } diff --git a/akka-actor-tests/src/test/scala/akka/dataflow/Future2Actor.scala b/akka-actor-tests/src/test/scala/akka/dataflow/Future2Actor.scala index d684474b16..5d24b9678f 100644 --- a/akka-actor-tests/src/test/scala/akka/dataflow/Future2Actor.scala +++ b/akka-actor-tests/src/test/scala/akka/dataflow/Future2Actor.scala @@ -4,7 +4,7 @@ package akka.dataflow import akka.actor.{ Actor, Props } -import akka.dispatch.Future +import akka.dispatch.{ Future, Await } import akka.actor.future2actor import akka.util.duration._ import akka.testkit.AkkaSpec @@ -26,9 +26,9 @@ class Future2ActorSpec extends AkkaSpec with DefaultTimeout { case "ex" ⇒ Future(throw new AssertionError) pipeTo context.sender } })) - (actor ? "do").as[Int] must be(Some(31)) + Await.result(actor ? "do", timeout.duration) must be(31) intercept[AssertionError] { - (actor ? "ex").get + Await.result(actor ? "ex", timeout.duration) } } } diff --git a/akka-actor-tests/src/test/scala/akka/dispatch/FutureSpec.scala b/akka-actor-tests/src/test/scala/akka/dispatch/FutureSpec.scala index 804d3b5e62..7193d914f1 100644 --- a/akka-actor-tests/src/test/scala/akka/dispatch/FutureSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/dispatch/FutureSpec.scala @@ -10,11 +10,11 @@ import akka.actor._ import akka.testkit.{ EventFilter, filterEvents, filterException } import akka.util.duration._ import org.multiverse.api.latches.StandardLatch -import java.util.concurrent.{ TimeUnit, CountDownLatch } import akka.testkit.AkkaSpec import org.scalatest.junit.JUnitSuite import java.lang.ArithmeticException import akka.testkit.DefaultTimeout +import java.util.concurrent.{ TimeoutException, TimeUnit, CountDownLatch } object FutureSpec { class TestActor extends Actor { @@ -37,6 +37,7 @@ object FutureSpec { } } +@org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) class JavaFutureSpec extends JavaFutureTests with JUnitSuite @org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) @@ -47,8 +48,9 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa "never completed" must { behave like emptyFuture(_(Promise())) "return supplied value on timeout" in { - val promise = Promise[String](100) orElse "Timedout" - promise.get must be("Timedout") + val timedOut = Promise.successful[String]("Timedout") + val promise = Promise[String]() orElse timedOut + Await.result(promise, timeout.duration) must be("Timedout") } } "completed with a result" must { @@ -61,9 +63,6 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa val future = Promise[String]().complete(Left(new RuntimeException(message))) behave like futureWithException[RuntimeException](_(future, message)) } - "expired" must { - behave like expiredFuture(_(Promise(0))) - } } "A Future" when { @@ -78,7 +77,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa } test(future) latch.open - future.await + Await.ready(future, timeout.duration) } } "is completed" must { @@ -90,7 +89,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa result } latch.open - future.await + Await.ready(future, timeout.duration) test(future, result) } } @@ -99,8 +98,8 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa filterException[ArithmeticException] { check({ (future: Future[Int], actions: List[FutureAction]) ⇒ val result = (future /: actions)(_ /: _) - val expected = (future.await.value.get /: actions)(_ /: _) - ((result.await.value.get, expected) match { + val expected = (Await.ready(future, timeout.duration).value.get /: actions)(_ /: _) + ((Await.ready(result, timeout.duration).value.get, expected) match { case (Right(a), Right(b)) ⇒ a == b case (Left(a), Left(b)) if a.toString == b.toString ⇒ true case (Left(a), Left(b)) if a.getStackTrace.isEmpty || b.getStackTrace.isEmpty ⇒ @@ -118,7 +117,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa behave like futureWithResult { test ⇒ val actor = system.actorOf(Props[TestActor]) val future = actor ? "Hello" - future.await + Await.ready(future, timeout.duration) test(future, "World") system.stop(actor) } @@ -128,7 +127,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa filterException[RuntimeException] { val actor = system.actorOf(Props[TestActor]) val future = actor ? "Failure" - future.await + Await.ready(future, timeout.duration) test(future, "Expected exception; to test fault-tolerance") system.stop(actor) } @@ -142,7 +141,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa val actor1 = system.actorOf(Props[TestActor]) val actor2 = system.actorOf(Props(new Actor { def receive = { case s: String ⇒ sender ! s.toUpperCase } })) val future = actor1 ? "Hello" flatMap { case s: String ⇒ actor2 ? s } - future.await + Await.ready(future, timeout.duration) test(future, "WORLD") system.stop(actor1) system.stop(actor2) @@ -154,7 +153,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa val actor1 = system.actorOf(Props[TestActor]) val actor2 = system.actorOf(Props(new Actor { def receive = { case s: String ⇒ sender ! Status.Failure(new ArithmeticException("/ by zero")) } })) val future = actor1 ? "Hello" flatMap { case s: String ⇒ actor2 ? s } - future.await + Await.ready(future, timeout.duration) test(future, "/ by zero") system.stop(actor1) system.stop(actor2) @@ -167,7 +166,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa val actor1 = system.actorOf(Props[TestActor]) val actor2 = system.actorOf(Props(new Actor { def receive = { case s: String ⇒ sender ! s.toUpperCase } })) val future = actor1 ? "Hello" flatMap { case i: Int ⇒ actor2 ? i } - future.await + Await.ready(future, timeout.duration) test(future, "World (of class java.lang.String)") system.stop(actor1) system.stop(actor2) @@ -201,9 +200,9 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa c ← (actor ? 7).mapTo[String] } yield b + "-" + c - future1.get must be("10-14") + Await.result(future1, timeout.duration) must be("10-14") assert(checkType(future1, manifest[String])) - intercept[ClassCastException] { future2.get } + intercept[ClassCastException] { Await.result(future2, timeout.duration) } system.stop(actor) } } @@ -231,8 +230,8 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa Res(c: Int) ← actor ? Req(7) } yield b + "-" + c - future1.get must be("10-14") - intercept[MatchError] { future2.get } + Await.result(future1, timeout.duration) must be("10-14") + intercept[MatchError] { Await.result(future2, timeout.duration) } system.stop(actor) } } @@ -268,34 +267,34 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa } val future11 = actor ? "Failure" recover { case _ ⇒ "Oops!" } - future1.get must be(5) - intercept[ArithmeticException] { future2.get } - intercept[ArithmeticException] { future3.get } - future4.get must be("5") - future5.get must be("0") - intercept[ArithmeticException] { future6.get } - future7.get must be("You got ERROR") - intercept[RuntimeException] { future8.get } - future9.get must be("FAIL!") - future10.get must be("World") - future11.get must be("Oops!") + Await.result(future1, timeout.duration) must be(5) + intercept[ArithmeticException] { Await.result(future2, timeout.duration) } + intercept[ArithmeticException] { Await.result(future3, timeout.duration) } + Await.result(future4, timeout.duration) must be("5") + Await.result(future5, timeout.duration) must be("0") + intercept[ArithmeticException] { Await.result(future6, timeout.duration) } + Await.result(future7, timeout.duration) must be("You got ERROR") + intercept[RuntimeException] { Await.result(future8, timeout.duration) } + Await.result(future9, timeout.duration) must be("FAIL!") + Await.result(future10, timeout.duration) must be("World") + Await.result(future11, timeout.duration) must be("Oops!") system.stop(actor) } } "firstCompletedOf" in { - val futures = Vector.fill[Future[Int]](10)(new DefaultPromise[Int]()) :+ new KeptPromise[Int](Right(5)) - Future.firstCompletedOf(futures).get must be(5) + val futures = Vector.fill[Future[Int]](10)(Promise[Int]()) :+ Promise.successful[Int](5) + Await.result(Future.firstCompletedOf(futures), timeout.duration) must be(5) } "find" in { val futures = for (i ← 1 to 10) yield Future { i } val result = Future.find[Int](futures)(_ == 3) - result.get must be(Some(3)) + Await.result(result, timeout.duration) must be(Some(3)) val notFound = Future.find[Int](futures)(_ == 11) - notFound.get must be(None) + Await.result(notFound, timeout.duration) must be(None) } "fold" in { @@ -306,7 +305,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa } val timeout = 10000 def futures = actors.zipWithIndex map { case (actor: ActorRef, idx: Int) ⇒ actor.?((idx, idx * 200), timeout).mapTo[Int] } - Future.fold(futures, timeout)(0)(_ + _).get must be(45) + Await.result(Future.fold(futures)(0)(_ + _), timeout millis) must be(45) } "fold by composing" in { @@ -316,7 +315,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa })) } def futures = actors.zipWithIndex map { case (actor: ActorRef, idx: Int) ⇒ actor.?((idx, idx * 200), 10000).mapTo[Int] } - futures.foldLeft(Future(0))((fr, fa) ⇒ for (r ← fr; a ← fa) yield (r + a)).get must be(45) + Await.result(futures.foldLeft(Future(0))((fr, fa) ⇒ for (r ← fr; a ← fa) yield (r + a)), timeout.duration) must be(45) } "fold with an exception" in { @@ -333,18 +332,19 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa } val timeout = 10000 def futures = actors.zipWithIndex map { case (actor: ActorRef, idx: Int) ⇒ actor.?((idx, idx * 100), timeout).mapTo[Int] } - Future.fold(futures, timeout)(0)(_ + _).await.exception.get.getMessage must be("shouldFoldResultsWithException: expected") + intercept[Throwable] { Await.result(Future.fold(futures)(0)(_ + _), timeout millis) }.getMessage must be("shouldFoldResultsWithException: expected") } } "fold mutable zeroes safely" in { import scala.collection.mutable.ArrayBuffer def test(testNumber: Int) { - val fs = (0 to 1000) map (i ⇒ Future(i, 10000)) - val result = Future.fold(fs, 10000)(ArrayBuffer.empty[AnyRef]) { + val fs = (0 to 1000) map (i ⇒ Future(i)) + val f = Future.fold(fs)(ArrayBuffer.empty[AnyRef]) { case (l, i) if i % 2 == 0 ⇒ l += i.asInstanceOf[AnyRef] case (l, _) ⇒ l - }.get.asInstanceOf[ArrayBuffer[Int]].sum + } + val result = Await.result(f.mapTo[ArrayBuffer[Int]], 10000 millis).sum assert(result === 250500) } @@ -353,7 +353,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa } "return zero value if folding empty list" in { - Future.fold(List[Future[Int]]())(0)(_ + _).get must be(0) + Await.result(Future.fold(List[Future[Int]]())(0)(_ + _), timeout.duration) must be(0) } "shouldReduceResults" in { @@ -364,7 +364,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa } val timeout = 10000 def futures = actors.zipWithIndex map { case (actor: ActorRef, idx: Int) ⇒ actor.?((idx, idx * 200), timeout).mapTo[Int] } - assert(Future.reduce(futures, timeout)(_ + _).get === 45) + assert(Await.result(Future.reduce(futures)(_ + _), timeout millis) === 45) } "shouldReduceResultsWithException" in { @@ -381,20 +381,20 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa } val timeout = 10000 def futures = actors.zipWithIndex map { case (actor: ActorRef, idx: Int) ⇒ actor.?((idx, idx * 100), timeout).mapTo[Int] } - assert(Future.reduce(futures, timeout)(_ + _).await.exception.get.getMessage === "shouldFoldResultsWithException: expected") + intercept[Throwable] { Await.result(Future.reduce(futures)(_ + _), timeout millis) }.getMessage must be === "shouldFoldResultsWithException: expected" } } "shouldReduceThrowIAEOnEmptyInput" in { filterException[IllegalArgumentException] { - intercept[UnsupportedOperationException] { Future.reduce(List[Future[Int]]())(_ + _).get } + intercept[java.util.NoSuchElementException] { Await.result(Future.reduce(List[Future[Int]]())(_ + _), timeout.duration) } } } "receiveShouldExecuteOnComplete" in { val latch = new StandardLatch val actor = system.actorOf(Props[TestActor]) - actor ? "Hello" onResult { case "World" ⇒ latch.open } + actor ? "Hello" onSuccess { case "World" ⇒ latch.open } assert(latch.tryAwait(5, TimeUnit.SECONDS)) system.stop(actor) } @@ -410,52 +410,46 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa })) val oddFutures = List.fill(100)(oddActor ? 'GetNext mapTo manifest[Int]) - assert(Future.sequence(oddFutures).get.sum === 10000) + + assert(Await.result(Future.sequence(oddFutures), timeout.duration).sum === 10000) system.stop(oddActor) val list = (1 to 100).toList - assert(Future.traverse(list)(x ⇒ Future(x * 2 - 1)).get.sum === 10000) + assert(Await.result(Future.traverse(list)(x ⇒ Future(x * 2 - 1)), timeout.duration).sum === 10000) } "shouldHandleThrowables" in { class ThrowableTest(m: String) extends Throwable(m) filterException[ThrowableTest] { - val f1 = Future { throw new ThrowableTest("test") } - f1.await - intercept[ThrowableTest] { f1.get } + val f1 = Future[Any] { throw new ThrowableTest("test") } + intercept[ThrowableTest] { Await.result(f1, timeout.duration) } val latch = new StandardLatch val f2 = Future { latch.tryAwait(5, TimeUnit.SECONDS); "success" } f2 foreach (_ ⇒ throw new ThrowableTest("dispatcher foreach")) - f2 onResult { case _ ⇒ throw new ThrowableTest("dispatcher receive") } + f2 onSuccess { case _ ⇒ throw new ThrowableTest("dispatcher receive") } val f3 = f2 map (s ⇒ s.toUpperCase) latch.open - f2.await - assert(f2.get === "success") + assert(Await.result(f2, timeout.duration) === "success") f2 foreach (_ ⇒ throw new ThrowableTest("current thread foreach")) - f2 onResult { case _ ⇒ throw new ThrowableTest("current thread receive") } - f3.await - assert(f3.get === "SUCCESS") + f2 onSuccess { case _ ⇒ throw new ThrowableTest("current thread receive") } + assert(Await.result(f3, timeout.duration) === "SUCCESS") } } "shouldBlockUntilResult" in { val latch = new StandardLatch - val f = Future({ latch.await; 5 }) - val f2 = Future({ f.get + 5 }) + val f = Future { latch.await; 5 } + val f2 = Future { Await.result(f, timeout.duration) + 5 } - assert(f2.resultOrException === None) + intercept[TimeoutException](Await.ready(f2, 100 millis)) latch.open - assert(f2.get === 10) + assert(Await.result(f2, timeout.duration) === 10) - val f3 = Future({ Thread.sleep(10); 5 }, 10 millis) - filterException[FutureTimeoutException] { - intercept[FutureTimeoutException] { - f3.get - } - } + val f3 = Future { Thread.sleep(100); 5 } + filterException[TimeoutException] { intercept[TimeoutException] { Await.ready(f3, 0 millis) } } } "futureComposingWithContinuations" in { @@ -468,7 +462,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa val r = flow(x() + " " + y() + "!") - assert(r.get === "Hello World!") + assert(Await.result(r, timeout.duration) === "Hello World!") system.stop(actor) } @@ -482,7 +476,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa val r = flow(x() + " " + y.map(_ / 0).map(_.toString).apply, 100) - intercept[java.lang.ArithmeticException](r.get) + intercept[java.lang.ArithmeticException](Await.result(r, timeout.duration)) } } @@ -497,7 +491,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa val r = flow(x() + y(), 100) - intercept[ClassCastException](r.get) + intercept[ClassCastException](Await.result(r, timeout.duration)) } } @@ -512,7 +506,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa val r = flow(x() + y()) - intercept[ClassCastException](r.get) + intercept[ClassCastException](Await.result(r, timeout.duration)) } } @@ -536,44 +530,30 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa flow { x << 5 } - assert(y.get === 5) - assert(z.get === 5) + assert(Await.result(y, timeout.duration) === 5) + assert(Await.result(z, timeout.duration) === 5) assert(lz.isOpen) - assert(result.get === 10) + assert(Await.result(result, timeout.duration) === 10) val a, b, c = Promise[Int]() val result2 = flow { - val n = (a << c).result.get + 10 + val n = (a << c).value.get.right.get + 10 b << (c() - 2) a() + n * b() } c completeWith Future(5) - assert(a.get === 5) - assert(b.get === 3) - assert(result2.get === 50) - } - - "shouldNotAddOrRunCallbacksAfterFailureToBeCompletedBeforeExpiry" in { - val latch = new StandardLatch - val f = Promise[Int](0) - Thread.sleep(25) - f.onComplete(_ ⇒ latch.open) //Shouldn't throw any exception here - - assert(f.isExpired) //Should be expired - - f.complete(Right(1)) //Shouldn't complete the Future since it is expired - - assert(f.value.isEmpty) //Shouldn't be completed - assert(!latch.isOpen) //Shouldn't run the listener + assert(Await.result(a, timeout.duration) === 5) + assert(Await.result(b, timeout.duration) === 3) + assert(Await.result(result2, timeout.duration) === 50) } "futureDataFlowShouldEmulateBlocking1" in { import Future.flow - val one, two = Promise[Int](1000 * 60) + val one, two = Promise[Int]() val simpleResult = flow { one() + two() } @@ -582,23 +562,23 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa flow { one << 1 } - one.await + Await.ready(one, 1 minute) assert(one.isCompleted) assert(List(two, simpleResult).forall(_.isCompleted == false)) flow { two << 9 } - two.await + Await.ready(two, 1 minute) assert(List(one, two).forall(_.isCompleted == true)) - assert(simpleResult.get === 10) + assert(Await.result(simpleResult, timeout.duration) === 10) } "futureDataFlowShouldEmulateBlocking2" in { import Future.flow - val x1, x2, y1, y2 = Promise[Int](1000 * 60) + val x1, x2, y1, y2 = Promise[Int]() val lx, ly, lz = new StandardLatch val result = flow { lx.open() @@ -616,17 +596,17 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa flow { y1 << 1 } // When this is set, it should cascade down the line assert(ly.tryAwaitUninterruptible(2000, TimeUnit.MILLISECONDS)) - assert(x1.get === 1) + assert(Await.result(x1, 1 minute) === 1) assert(!lz.isOpen) flow { y2 << 9 } // When this is set, it should cascade down the line assert(lz.tryAwaitUninterruptible(2000, TimeUnit.MILLISECONDS)) - assert(x2.get === 9) + assert(Await.result(x2, 1 minute) === 9) - assert(List(x1, x2, y1, y2).forall(_.isCompleted == true)) + assert(List(x1, x2, y1, y2).forall(_.isCompleted)) - assert(result.get === 10) + assert(Await.result(result, 1 minute) === 10) } "dataFlowAPIshouldbeSlick" in { @@ -646,7 +626,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa assert(i2.tryAwaitUninterruptible(2000, TimeUnit.MILLISECONDS)) s1.open s2.open - assert(result.get === 10) + assert(Await.result(result, timeout.duration) === 10) } "futureCompletingWithContinuationsFailure" in { @@ -670,8 +650,8 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa flow { x << 5 } - assert(y.get === 5) - intercept[java.lang.ArithmeticException](result.get) + assert(Await.result(y, timeout.duration) === 5) + intercept[java.lang.ArithmeticException](Await.result(result, timeout.duration)) assert(z.value === None) assert(!lz.isOpen) } @@ -694,7 +674,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa latch.open - assert(result.get === Some("Hello")) + assert(Await.result(result, timeout.duration) === Some("Hello")) } "futureFlowShouldBeTypeSafe" in { @@ -717,8 +697,8 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa assert(!checkType(rInt, manifest[Nothing])) assert(!checkType(rInt, manifest[Any])) - rString.await - rInt.await + Await.result(rString, timeout.duration) + Await.result(rInt, timeout.duration) } "futureFlowSimpleAssign" in { @@ -732,7 +712,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa flow { x << 40 } flow { y << 2 } - assert(z.get === 42) + assert(Await.result(z, timeout.duration) === 42) } "futureFlowLoops" in { @@ -754,7 +734,7 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa var i = 0 promises foreach { p ⇒ - assert(p.get === i) + assert(Await.result(p, timeout.duration) === i) i += 1 } @@ -810,88 +790,102 @@ class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll with Defa latch(8).open latch(9).await - f4.await must be('completed) + Await.ready(f4, timeout.duration) must be('completed) } "should not deadlock with nested await (ticket 1313)" in { - val simple = Future() map (_ ⇒ (Future(()) map (_ ⇒ ())).get) - simple.await must be('completed) + val simple = Future() map (_ ⇒ Await.result((Future(()) map (_ ⇒ ())), timeout.duration)) + Await.ready(simple, timeout.duration) must be('completed) val l1, l2 = new StandardLatch val complex = Future() map { _ ⇒ - Future.blocking() - val nested = Future() + Future.blocking(system.dispatcher) + val nested = Future(()) nested foreach (_ ⇒ l1.open) l1.await // make sure nested is completed nested foreach (_ ⇒ l2.open) l2.await } - assert(complex.await.isCompleted) + Await.ready(complex, timeout.duration) must be('completed) } } } def emptyFuture(f: (Future[Any] ⇒ Unit) ⇒ Unit) { "not be completed" in { f(_ must not be ('completed)) } - "not be expired" in { f(_ must not be ('expired)) } "not contain a value" in { f(_.value must be(None)) } - "not contain a result" in { f(_.result must be(None)) } - "not contain an exception" in { f(_.exception must be(None)) } } def futureWithResult(f: ((Future[Any], Any) ⇒ Unit) ⇒ Unit) { "be completed" in { f((future, _) ⇒ future must be('completed)) } - "not be expired" in { f((future, _) ⇒ future must not be ('expired)) } "contain a value" in { f((future, result) ⇒ future.value must be(Some(Right(result)))) } - "contain a result" in { f((future, result) ⇒ future.result must be(Some(result))) } - "not contain an exception" in { f((future, _) ⇒ future.exception must be(None)) } - "return result with 'get'" in { f((future, result) ⇒ future.get must be(result)) } - "return result with 'resultOrException'" in { f((future, result) ⇒ future.resultOrException must be(Some(result))) } - "not timeout" in { f((future, _) ⇒ future.await) } + "return result with 'get'" in { f((future, result) ⇒ Await.result(future, timeout.duration) must be(result)) } + "return result with 'Await.sync'" in { f((future, result) ⇒ Await.result(future, timeout.duration) must be(result)) } + "not timeout" in { f((future, _) ⇒ Await.ready(future, 0 millis)) } "filter result" in { f { (future, result) ⇒ - (future filter (_ ⇒ true)).get must be(result) - (evaluating { (future filter (_ ⇒ false)).get } must produce[MatchError]).getMessage must startWith(result.toString) + Await.result((future filter (_ ⇒ true)), timeout.duration) must be(result) + (evaluating { Await.result((future filter (_ ⇒ false)), timeout.duration) } must produce[MatchError]).getMessage must startWith(result.toString) } } - "transform result with map" in { f((future, result) ⇒ (future map (_.toString.length)).get must be(result.toString.length)) } - "compose result with flatMap" is pending - "perform action with foreach" is pending - "match result with collect" is pending - "not recover from exception" is pending - "perform action on result" is pending + "transform result with map" in { f((future, result) ⇒ Await.result((future map (_.toString.length)), timeout.duration) must be(result.toString.length)) } + "compose result with flatMap" in { + f { (future, result) ⇒ + val r = for (r ← future; p ← Promise.successful("foo")) yield r.toString + p + Await.result(r, timeout.duration) must be(result.toString + "foo") + } + } + "perform action with foreach" in { + f { (future, result) ⇒ + val p = Promise[Any]() + future foreach p.success + Await.result(p, timeout.duration) must be(result) + } + } + "not recover from exception" in { f((future, result) ⇒ Await.result(future.recover({ case _ ⇒ "pigdog" }), timeout.duration) must be(result)) } + "perform action on result" in { + f { (future, result) ⇒ + val p = Promise[Any]() + future.onSuccess { case x ⇒ p.success(x) } + Await.result(p, timeout.duration) must be(result) + } + } + "not project a failure" in { f((future, result) ⇒ (evaluating { Await.result(future.failed, timeout.duration) } must produce[NoSuchElementException]).getMessage must be("Future.failed not completed with a throwable. Instead completed with: " + result)) } "not perform action on exception" is pending - "cast using mapTo" is pending + "cast using mapTo" in { f((future, result) ⇒ Await.result(future.mapTo[Boolean].recover({ case _: ClassCastException ⇒ false }), timeout.duration) must be(false)) } } def futureWithException[E <: Throwable: Manifest](f: ((Future[Any], String) ⇒ Unit) ⇒ Unit) { "be completed" in { f((future, _) ⇒ future must be('completed)) } - "not be expired" in { f((future, _) ⇒ future must not be ('expired)) } - "contain a value" in { f((future, _) ⇒ future.value must be('defined)) } - "not contain a result" in { f((future, _) ⇒ future.result must be(None)) } - "contain an exception" in { f((future, message) ⇒ future.exception.get.getMessage must be(message)) } - "throw exception with 'get'" in { f((future, message) ⇒ (evaluating { future.get } must produce[E]).getMessage must be(message)) } - "throw exception with 'resultOrException'" in { f((future, message) ⇒ (evaluating { future.resultOrException } must produce[E]).getMessage must be(message)) } - "not timeout" in { f((future, _) ⇒ future.await) } + "contain a value" in { + f((future, message) ⇒ { + future.value must be('defined) + future.value.get must be('left) + future.value.get.left.get.getMessage must be(message) + }) + } + "throw exception with 'get'" in { f((future, message) ⇒ (evaluating { Await.result(future, timeout.duration) } must produce[E]).getMessage must be(message)) } + "throw exception with 'Await.sync'" in { f((future, message) ⇒ (evaluating { Await.result(future, timeout.duration) } must produce[E]).getMessage must be(message)) } "retain exception with filter" in { f { (future, message) ⇒ - (evaluating { (future filter (_ ⇒ true)).get } must produce[E]).getMessage must be(message) - (evaluating { (future filter (_ ⇒ false)).get } must produce[E]).getMessage must be(message) + (evaluating { Await.result(future filter (_ ⇒ true), timeout.duration) } must produce[E]).getMessage must be(message) + (evaluating { Await.result(future filter (_ ⇒ false), timeout.duration) } must produce[E]).getMessage must be(message) } } - "retain exception with map" in { f((future, message) ⇒ (evaluating { (future map (_.toString.length)).get } must produce[E]).getMessage must be(message)) } - "retain exception with flatMap" is pending + "retain exception with map" in { f((future, message) ⇒ (evaluating { Await.result(future map (_.toString.length), timeout.duration) } must produce[E]).getMessage must be(message)) } + "retain exception with flatMap" in { f((future, message) ⇒ (evaluating { Await.result(future flatMap (_ ⇒ Promise.successful[Any]("foo")), timeout.duration) } must produce[E]).getMessage must be(message)) } "not perform action with foreach" is pending - "retain exception with collect" is pending - "recover from exception" is pending + "recover from exception" in { f((future, message) ⇒ Await.result(future.recover({ case e if e.getMessage == message ⇒ "pigdog" }), timeout.duration) must be("pigdog")) } "not perform action on result" is pending - "perform action on exception" is pending - "always cast successfully using mapTo" is pending - } - - def expiredFuture(f: (Future[Any] ⇒ Unit) ⇒ Unit) { - "not be completed" in { f(_ must not be ('completed)) } - "be expired" in { f(_ must be('expired)) } + "project a failure" in { f((future, message) ⇒ Await.result(future.failed, timeout.duration).getMessage must be(message)) } + "perform action on exception" in { + f { (future, message) ⇒ + val p = Promise[Any]() + future.onFailure { case _ ⇒ p.success(message) } + Await.result(p, timeout.duration) must be(message) + } + } + "always cast successfully using mapTo" in { f((future, message) ⇒ (evaluating { Await.result(future.mapTo[java.lang.Thread], timeout.duration) } must produce[E]).getMessage must be(message)) } } sealed trait IntAction { def apply(that: Int): Int } diff --git a/akka-actor-tests/src/test/scala/akka/dispatch/MailboxConfigSpec.scala b/akka-actor-tests/src/test/scala/akka/dispatch/MailboxConfigSpec.scala index 7af8f057d8..d0c2053243 100644 --- a/akka-actor-tests/src/test/scala/akka/dispatch/MailboxConfigSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/dispatch/MailboxConfigSpec.scala @@ -17,13 +17,9 @@ abstract class MailboxSpec extends AkkaSpec with BeforeAndAfterAll with BeforeAn val q = factory(config) ensureInitialMailboxState(config, q) - implicit val within = 1 second + val f = spawn { q.dequeue } - val f = spawn { - q.dequeue - } - - f.await.resultOrException must be === Some(null) + Await.result(f, 1 second) must be(null) } "create a bounded mailbox with 10 capacity and with push timeout" in { @@ -61,13 +57,13 @@ abstract class MailboxSpec extends AkkaSpec with BeforeAndAfterAll with BeforeAn } //CANDIDATE FOR TESTKIT - def spawn[T <: AnyRef](fun: ⇒ T)(implicit within: Duration): Future[T] = { - val result = new DefaultPromise[T](within.length, within.unit) + def spawn[T <: AnyRef](fun: ⇒ T): Future[T] = { + val result = Promise[T]() val t = new Thread(new Runnable { def run = try { - result.completeWithResult(fun) + result.success(fun) } catch { - case e: Throwable ⇒ result.completeWithException(e) + case e: Throwable ⇒ result.failure(e) } }) t.start @@ -119,8 +115,8 @@ abstract class MailboxSpec extends AkkaSpec with BeforeAndAfterAll with BeforeAn val consumers = for (i ← (1 to 4).toList) yield createConsumer - val ps = producers.map(_.await.resultOrException.get) - val cs = consumers.map(_.await.resultOrException.get) + val ps = producers.map(Await.result(_, within)) + val cs = consumers.map(Await.result(_, within)) ps.map(_.size).sum must be === totalMessages //Must have produced 1000 messages cs.map(_.size).sum must be === totalMessages //Must have consumed all produced messages diff --git a/akka-actor-tests/src/test/scala/akka/dispatch/PriorityDispatcherSpec.scala b/akka-actor-tests/src/test/scala/akka/dispatch/PriorityDispatcherSpec.scala index f332f18030..ccc632c6be 100644 --- a/akka-actor-tests/src/test/scala/akka/dispatch/PriorityDispatcherSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/dispatch/PriorityDispatcherSpec.scala @@ -43,7 +43,7 @@ class PriorityDispatcherSpec extends AkkaSpec with DefaultTimeout { actor.resume //Signal the actor to start treating it's message backlog - actor.?('Result).as[List[Int]].get must be === (msgs.reverse) + Await.result(actor.?('Result).mapTo[List[Int]], timeout.duration) must be === msgs.reverse } } diff --git a/akka-actor-tests/src/test/scala/akka/dispatch/PromiseStreamSpec.scala b/akka-actor-tests/src/test/scala/akka/dispatch/PromiseStreamSpec.scala index 724beba6bb..e41dc9c4cd 100644 --- a/akka-actor-tests/src/test/scala/akka/dispatch/PromiseStreamSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/dispatch/PromiseStreamSpec.scala @@ -21,9 +21,9 @@ class PromiseStreamSpec extends AkkaSpec with DefaultTimeout { b << q c << q() } - assert(a.get === 1) - assert(b.get === 2) - assert(c.get === 3) + assert(Await.result(a, timeout.duration) === 1) + assert(Await.result(b, timeout.duration) === 2) + assert(Await.result(c, timeout.duration) === 3) } "pend" in { @@ -35,43 +35,9 @@ class PromiseStreamSpec extends AkkaSpec with DefaultTimeout { c << q } flow { q <<< List(1, 2, 3) } - assert(a.get === 1) - assert(b.get === 2) - assert(c.get === 3) - } - - "timeout" in { - val a, c = Promise[Int]() - val b = Promise[Int](0) - val q = PromiseStream[Int](1000) - flow { - a << q() - b << q() - c << q() - } - Thread.sleep(10) - flow { - q << (1, 2) - q << 3 - } - assert(a.get === 1) - intercept[FutureTimeoutException] { b.get } - assert(c.get === 3) - } - - "timeout again" in { - val q = PromiseStream[Int](500) - val a = q.dequeue() - val b = q.dequeue() - q += 1 - Thread.sleep(500) - q += (2, 3) - val c = q.dequeue() - val d = q.dequeue() - assert(a.get === 1) - intercept[FutureTimeoutException] { b.get } - assert(c.get === 2) - assert(d.get === 3) + assert(Await.result(a, timeout.duration) === 1) + assert(Await.result(b, timeout.duration) === 2) + assert(Await.result(c, timeout.duration) === 3) } "pend again" in { @@ -88,10 +54,10 @@ class PromiseStreamSpec extends AkkaSpec with DefaultTimeout { c << q1 d << q1 } - assert(a.get === 1) - assert(b.get === 2) - assert(c.get === 3) - assert(d.get === 4) + assert(Await.result(a, timeout.duration) === 1) + assert(Await.result(b, timeout.duration) === 2) + assert(Await.result(c, timeout.duration) === 3) + assert(Await.result(d, timeout.duration) === 4) } "enque" in { @@ -105,10 +71,10 @@ class PromiseStreamSpec extends AkkaSpec with DefaultTimeout { } q ++= List(1, 2, 3, 4) - assert(a.get === 1) - assert(b.get === 2) - assert(c.get === 3) - assert(d.get === 4) + assert(Await.result(a, timeout.duration) === 1) + assert(Await.result(b, timeout.duration) === 2) + assert(Await.result(c, timeout.duration) === 3) + assert(Await.result(d, timeout.duration) === 4) } "map" in { @@ -124,9 +90,9 @@ class PromiseStreamSpec extends AkkaSpec with DefaultTimeout { flow { qs << ("Hello", "World!", "Test") } - assert(a.get === 5) - assert(b.get === "World!") - assert(c.get === 4) + assert(Await.result(a, timeout.duration) === 5) + assert(Await.result(b, timeout.duration) === "World!") + assert(Await.result(c, timeout.duration) === 4) } "not fail under concurrent stress" in { @@ -162,8 +128,7 @@ class PromiseStreamSpec extends AkkaSpec with DefaultTimeout { } } - val result = future.get - assert(result === (1L to 100000L).sum) + assert(Await.result(future, timeout.duration) === (1L to 100000L).sum) } } } diff --git a/akka-actor-tests/src/test/scala/akka/performance/trading/system/MatchingEngine.scala b/akka-actor-tests/src/test/scala/akka/performance/trading/system/MatchingEngine.scala index cabf890488..cf5142f0ba 100644 --- a/akka-actor-tests/src/test/scala/akka/performance/trading/system/MatchingEngine.scala +++ b/akka-actor-tests/src/test/scala/akka/performance/trading/system/MatchingEngine.scala @@ -2,9 +2,6 @@ package akka.performance.trading.system import akka.performance.trading.domain._ import akka.actor._ -import akka.dispatch.Future -import akka.dispatch.FutureTimeoutException -import akka.dispatch.MessageDispatcher trait MatchingEngine { val meId: String diff --git a/akka-actor-tests/src/test/scala/akka/routing/ActorPoolSpec.scala b/akka-actor-tests/src/test/scala/akka/routing/ActorPoolSpec.scala index 9ef69ab028..c87e4aeb89 100644 --- a/akka-actor-tests/src/test/scala/akka/routing/ActorPoolSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/routing/ActorPoolSpec.scala @@ -1,11 +1,11 @@ package akka.routing -import akka.dispatch.{ KeptPromise, Future } import akka.actor._ import akka.testkit._ import akka.util.duration._ import java.util.concurrent.atomic.{ AtomicBoolean, AtomicInteger } import akka.testkit.AkkaSpec +import akka.dispatch.{ Await, Promise, Future } object ActorPoolSpec { @@ -17,7 +17,7 @@ object ActorPoolSpec { import TypedActor.dispatcher def sq(x: Int, sleep: Long): Future[Int] = { if (sleep > 0) Thread.sleep(sleep) - new KeptPromise(Right(x * x)) + Promise.successful(x * x) } } @@ -47,7 +47,7 @@ class TypedActorPoolSpec extends AkkaSpec with DefaultTimeout { val results = for (i ← 1 to 100) yield (i, pool.sq(i, 0)) for ((i, r) ← results) - r.get must equal(i * i) + Await.result(r, timeout.duration) must equal(i * i) ta.stop(pool) } @@ -97,7 +97,7 @@ class ActorPoolSpec extends AkkaSpec with DefaultTimeout { count.get must be(2) - (pool ? ActorPool.Stat).as[ActorPool.Stats].get.size must be(2) + Await.result((pool ? ActorPool.Stat).mapTo[ActorPool.Stats], timeout.duration).size must be(2) system.stop(pool) } @@ -125,8 +125,8 @@ class ActorPoolSpec extends AkkaSpec with DefaultTimeout { }).withFaultHandler(faultHandler)) try { - (for (count ← 1 to 500) yield pool.?("Test", 20000)) foreach { - _.await.resultOrException.get must be("Response") + (for (count ← 1 to 500) yield pool.?("Test", 20 seconds)) foreach { + Await.result(_, 20 seconds) must be("Response") } } finally { system.stop(pool) @@ -163,7 +163,7 @@ class ActorPoolSpec extends AkkaSpec with DefaultTimeout { pool ! 1 - (pool ? ActorPool.Stat).as[ActorPool.Stats].get.size must be(2) + Await.result((pool ? ActorPool.Stat).mapTo[ActorPool.Stats], timeout.duration).size must be(2) var loops = 0 def loop(t: Int) = { @@ -183,7 +183,7 @@ class ActorPoolSpec extends AkkaSpec with DefaultTimeout { latch.await count.get must be(loops) - (pool ? ActorPool.Stat).as[ActorPool.Stats].get.size must be(2) + Await.result((pool ? ActorPool.Stat).mapTo[ActorPool.Stats], timeout.duration).size must be(2) // a whole bunch should max it out @@ -192,7 +192,7 @@ class ActorPoolSpec extends AkkaSpec with DefaultTimeout { latch.await count.get must be(loops) - (pool ? ActorPool.Stat).as[ActorPool.Stats].get.size must be(4) + Await.result((pool ? ActorPool.Stat).mapTo[ActorPool.Stats], timeout.duration).size must be(4) system.stop(pool) } @@ -239,7 +239,7 @@ class ActorPoolSpec extends AkkaSpec with DefaultTimeout { latch.await count.get must be(loops) - (pool ? ActorPool.Stat).as[ActorPool.Stats].get.size must be(2) + Await.result((pool ? ActorPool.Stat).mapTo[ActorPool.Stats], timeout.duration).size must be(2) // send a bunch over the threshold and observe an increment loops = 15 @@ -248,7 +248,7 @@ class ActorPoolSpec extends AkkaSpec with DefaultTimeout { latch.await(10 seconds) count.get must be(loops) - (pool ? ActorPool.Stat).as[ActorPool.Stats].get.size must be >= (3) + Await.result((pool ? ActorPool.Stat).mapTo[ActorPool.Stats], timeout.duration).size must be >= (3) system.stop(pool) } @@ -342,7 +342,7 @@ class ActorPoolSpec extends AkkaSpec with DefaultTimeout { (5 millis).dilated.sleep - val z = (pool ? ActorPool.Stat).as[ActorPool.Stats].get.size + val z = Await.result((pool ? ActorPool.Stat).mapTo[ActorPool.Stats], timeout.duration).size z must be >= (2) @@ -353,7 +353,7 @@ class ActorPoolSpec extends AkkaSpec with DefaultTimeout { (500 millis).dilated.sleep } - (pool ? ActorPool.Stat).as[ActorPool.Stats].get.size must be <= (z) + Await.result((pool ? ActorPool.Stat).mapTo[ActorPool.Stats], timeout.duration).size must be <= (z) system.stop(pool) } diff --git a/akka-actor-tests/src/test/scala/akka/routing/ConfiguredLocalRoutingSpec.scala b/akka-actor-tests/src/test/scala/akka/routing/ConfiguredLocalRoutingSpec.scala index ff72daa101..45e86fc387 100644 --- a/akka-actor-tests/src/test/scala/akka/routing/ConfiguredLocalRoutingSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/routing/ConfiguredLocalRoutingSpec.scala @@ -6,6 +6,7 @@ import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.{ CountDownLatch, TimeUnit } import akka.testkit._ import akka.util.duration._ +import akka.dispatch.Await @org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) class ConfiguredLocalRoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender { @@ -74,7 +75,7 @@ class ConfiguredLocalRoutingSpec extends AkkaSpec with DefaultTimeout with Impli for (i ← 0 until iterationCount) { for (k ← 0 until connectionCount) { - val id = (actor ? "hit").as[Int].getOrElse(fail("No id returned by actor")) + val id = Await.result((actor ? "hit").mapTo[Int], timeout.duration) replies = replies + (id -> (replies(id) + 1)) } } @@ -159,7 +160,7 @@ class ConfiguredLocalRoutingSpec extends AkkaSpec with DefaultTimeout with Impli for (i ← 0 until iterationCount) { for (k ← 0 until connectionCount) { - val id = (actor ? "hit").as[Int].getOrElse(fail("No id returned by actor")) + val id = Await.result((actor ? "hit").mapTo[Int], timeout.duration) replies = replies + (id -> (replies(id) + 1)) } } diff --git a/akka-actor-tests/src/test/scala/akka/routing/RoutingSpec.scala b/akka-actor-tests/src/test/scala/akka/routing/RoutingSpec.scala index ea8b5a6e05..6f08ba6dcf 100644 --- a/akka-actor-tests/src/test/scala/akka/routing/RoutingSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/routing/RoutingSpec.scala @@ -9,6 +9,7 @@ import collection.mutable.LinkedList import java.util.concurrent.{ CountDownLatch, TimeUnit } import akka.testkit._ import akka.util.duration._ +import akka.dispatch.Await object RoutingSpec { @@ -317,7 +318,7 @@ class RoutingSpec extends AkkaSpec with DefaultTimeout with ImplicitSender { routedActor ! Broadcast(Stop(Some(1))) shutdownLatch.await - (routedActor ? Broadcast(0)).as[Int].get must be(22) + Await.result(routedActor ? Broadcast(0), timeout.duration) must be(22) } case class Stop(id: Option[Int] = None) diff --git a/akka-actor-tests/src/test/scala/akka/ticket/Ticket703Spec.scala b/akka-actor-tests/src/test/scala/akka/ticket/Ticket703Spec.scala index 09b5f5e24c..f51beb7617 100644 --- a/akka-actor-tests/src/test/scala/akka/ticket/Ticket703Spec.scala +++ b/akka-actor-tests/src/test/scala/akka/ticket/Ticket703Spec.scala @@ -3,6 +3,8 @@ package akka.ticket import akka.actor._ import akka.routing._ import akka.testkit.AkkaSpec +import akka.dispatch.Await +import akka.util.duration._ @org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) class Ticket703Spec extends AkkaSpec { @@ -26,7 +28,7 @@ class Ticket703Spec extends AkkaSpec { } })) }).withFaultHandler(OneForOneStrategy(List(classOf[Exception]), 5, 1000))) - (actorPool.?("Ping", 10000)).await.result must be === Some("Response") + Await.result(actorPool.?("Ping", 10000), 10 seconds) must be === "Response" } } } diff --git a/akka-actor-tests/src/test/scala/akka/util/IndexSpec.scala b/akka-actor-tests/src/test/scala/akka/util/IndexSpec.scala index 271f8a9ac0..9f869fe907 100644 --- a/akka-actor-tests/src/test/scala/akka/util/IndexSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/util/IndexSpec.scala @@ -4,7 +4,7 @@ package akka.util import org.scalatest.matchers.MustMatchers -import akka.dispatch.Future +import akka.dispatch.{ Future, Await } import akka.testkit.AkkaSpec import scala.util.Random import akka.testkit.DefaultTimeout @@ -125,8 +125,7 @@ class IndexSpec extends AkkaSpec with MustMatchers with DefaultTimeout { val tasks = List.fill(nrOfTasks)(executeRandomTask) - tasks.foreach(_.await) - tasks.foreach(_.exception.map(throw _)) + tasks.foreach(Await.result(_, timeout.duration)) } } } \ No newline at end of file diff --git a/akka-actor/src/main/scala/akka/actor/ActorRef.scala b/akka-actor/src/main/scala/akka/actor/ActorRef.scala index f2b8afa1e2..7eab12c41b 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorRef.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorRef.scala @@ -15,6 +15,7 @@ import akka.event.DeathWatch import scala.annotation.tailrec import java.util.concurrent.ConcurrentHashMap import akka.event.LoggingAdapter +import java.util.concurrent.atomic.AtomicBoolean /** * ActorRef is an immutable and serializable handle to an Actor. @@ -321,7 +322,7 @@ private[akka] class LocalActorRef private[akka] ( a.result case None ⇒ this.!(message)(null) - new DefaultPromise[Any](0)(actorCell.system.dispatcher) + Promise[Any]()(actorCell.system.dispatcher) } } @@ -407,7 +408,7 @@ class DeadLetterActorRef(val eventStream: EventStream) extends MinimalActorRef { private[akka] def init(dispatcher: MessageDispatcher, rootPath: ActorPath) { _path = rootPath / "deadLetters" - brokenPromise = new KeptPromise[Any](Left(new ActorKilledException("In DeadLetterActorRef - promises are always broken.")))(dispatcher) + brokenPromise = Promise.failed(new ActorKilledException("In DeadLetterActorRef - promises are always broken."))(dispatcher) } override def isTerminated(): Boolean = true @@ -466,24 +467,16 @@ class VirtualPathContainer(val path: ActorPath, override val getParent: Internal class AskActorRef( val path: ActorPath, override val getParent: InternalActorRef, - deathWatch: DeathWatch, - timeout: Timeout, - val dispatcher: MessageDispatcher) extends MinimalActorRef { + val dispatcher: MessageDispatcher, + val deathWatch: DeathWatch) extends MinimalActorRef { - final val result = new DefaultPromise[Any](timeout)(dispatcher) + final val running = new AtomicBoolean(true) + final val result = Promise[Any]()(dispatcher) - { - val callback: Future[Any] ⇒ Unit = { _ ⇒ deathWatch.publish(Terminated(AskActorRef.this)); whenDone() } - result onComplete callback - result onTimeout callback - } - - protected def whenDone(): Unit = () - - override def !(message: Any)(implicit sender: ActorRef = null): Unit = message match { - case Status.Success(r) ⇒ result.completeWithResult(r) - case Status.Failure(f) ⇒ result.completeWithException(f) - case other ⇒ result.completeWithResult(other) + override def !(message: Any)(implicit sender: ActorRef = null): Unit = if (running.get) message match { + case Status.Success(r) ⇒ result.success(r) + case Status.Failure(f) ⇒ result.failure(f) + case other ⇒ result.success(other) } override def sendSystemMessage(message: SystemMessage): Unit = message match { @@ -492,11 +485,13 @@ class AskActorRef( } override def ?(message: Any)(implicit timeout: Timeout): Future[Any] = - new KeptPromise[Any](Left(new UnsupportedOperationException("Ask/? is not supported for [%s]".format(getClass.getName))))(dispatcher) + Promise.failed(new UnsupportedOperationException("Ask/? is not supported for %s".format(getClass.getName)))(dispatcher) - override def isTerminated = result.isCompleted || result.isExpired + override def isTerminated = result.isCompleted - override def stop(): Unit = if (!isTerminated) result.completeWithException(new ActorKilledException("Stopped")) + override def stop(): Unit = if (running.getAndSet(false)) { + deathWatch.publish(Terminated(this)) + } @throws(classOf[java.io.ObjectStreamException]) private def writeReplace(): AnyRef = SerializedActorRef(path.toString) diff --git a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala index a07b14ac43..4b081f6ee8 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala @@ -393,7 +393,7 @@ class LocalActorRefProvider( def dispatcher: MessageDispatcher = system.dispatcher - lazy val terminationFuture: DefaultPromise[Unit] = new DefaultPromise[Unit](Timeout.never)(dispatcher) + lazy val terminationFuture: Promise[Unit] = Promise[Unit]()(dispatcher) @volatile private var extraNames: Map[String, InternalActorRef] = Map() @@ -431,7 +431,7 @@ class LocalActorRefProvider( lazy val tempContainer = new VirtualPathContainer(tempNode, rootGuardian, log) - val deathWatch = new LocalDeathWatch + val deathWatch = new LocalDeathWatch(1024) //TODO make configrable def init(_system: ActorSystemImpl) { system = _system @@ -480,20 +480,20 @@ class LocalActorRefProvider( case t ⇒ val path = tempPath() val name = path.name - val a = new AskActorRef(path, tempContainer, deathWatch, t, dispatcher) { - override def whenDone() { - tempContainer.removeChild(name) - } - } + val a = new AskActorRef(path, tempContainer, dispatcher, deathWatch) tempContainer.addChild(name, a) + val f = dispatcher.prerequisites.scheduler.scheduleOnce(t.duration) { tempContainer.removeChild(name); a.stop() } + a.result onComplete { _ ⇒ + try { a.stop(); f.cancel() } + finally { tempContainer.removeChild(name) } + } + Some(a) } } } -class LocalDeathWatch extends DeathWatch with ActorClassification { - - def mapSize = 1024 +class LocalDeathWatch(val mapSize: Int) extends DeathWatch with ActorClassification { override def publish(event: Event): Unit = { val monitors = dissociate(classify(event)) diff --git a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala index 0ce6b4d529..19c5a68bd5 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala @@ -340,7 +340,7 @@ class ActorSystemImpl(val name: String, applicationConfig: Config) extends Actor private[akka] def systemActorOf(props: Props, name: String): ActorRef = { implicit val timeout = settings.CreationTimeout - (systemGuardian ? CreateChild(props, name)).get match { + Await.result(systemGuardian ? CreateChild(props, name), timeout.duration) match { case ref: ActorRef ⇒ ref case ex: Exception ⇒ throw ex } @@ -348,7 +348,7 @@ class ActorSystemImpl(val name: String, applicationConfig: Config) extends Actor def actorOf(props: Props, name: String): ActorRef = { implicit val timeout = settings.CreationTimeout - (guardian ? CreateChild(props, name)).get match { + Await.result(guardian ? CreateChild(props, name), timeout.duration) match { case ref: ActorRef ⇒ ref case ex: Exception ⇒ throw ex } @@ -356,7 +356,7 @@ class ActorSystemImpl(val name: String, applicationConfig: Config) extends Actor def actorOf(props: Props): ActorRef = { implicit val timeout = settings.CreationTimeout - (guardian ? CreateRandomNameChild(props)).get match { + Await.result(guardian ? CreateRandomNameChild(props), timeout.duration) match { case ref: ActorRef ⇒ ref case ex: Exception ⇒ throw ex } @@ -368,8 +368,8 @@ class ActorSystemImpl(val name: String, applicationConfig: Config) extends Actor val guard = guardian.path val sys = systemGuardian.path path.parent match { - case `guard` ⇒ (guardian ? StopChild(actor)).get - case `sys` ⇒ (systemGuardian ? StopChild(actor)).get + case `guard` ⇒ Await.result(guardian ? StopChild(actor), timeout.duration) + case `sys` ⇒ Await.result(systemGuardian ? StopChild(actor), timeout.duration) case _ ⇒ actor.asInstanceOf[InternalActorRef].stop() } } diff --git a/akka-actor/src/main/scala/akka/actor/TypedActor.scala b/akka-actor/src/main/scala/akka/actor/TypedActor.scala index a488c967d9..daf8f075d8 100644 --- a/akka-actor/src/main/scala/akka/actor/TypedActor.scala +++ b/akka-actor/src/main/scala/akka/actor/TypedActor.scala @@ -11,6 +11,7 @@ import java.util.concurrent.atomic.{ AtomicReference ⇒ AtomVar } import akka.serialization.{ Serializer, Serialization } import akka.dispatch._ import akka.serialization.SerializationExtension +import java.util.concurrent.TimeoutException trait TypedActorFactory { @@ -338,10 +339,8 @@ object TypedActor extends ExtensionId[TypedActorExtension] with ExtensionIdProvi if (m.returnsFuture_?) { val s = sender m(me).asInstanceOf[Future[Any]] onComplete { - _.value.get match { - case Left(f) ⇒ s ! Status.Failure(f) - case Right(r) ⇒ s ! r - } + case Left(f) ⇒ s ! Status.Failure(f) + case Right(r) ⇒ s ! r } } else { sender ! m(me) @@ -418,12 +417,12 @@ object TypedActor extends ExtensionId[TypedActorExtension] with ExtensionIdProvi case m if m.returnsFuture_? ⇒ actor.?(m, timeout) case m if m.returnsJOption_? || m.returnsOption_? ⇒ val f = actor.?(m, timeout) - (try { f.await.value } catch { case _: FutureTimeoutException ⇒ None }) match { + (try { Await.ready(f, timeout.duration).value } catch { case _: TimeoutException ⇒ None }) match { case None | Some(Right(null)) ⇒ if (m.returnsJOption_?) JOption.none[Any] else None case Some(Right(joption: AnyRef)) ⇒ joption case Some(Left(ex)) ⇒ throw ex } - case m ⇒ (actor.?(m, timeout)).get.asInstanceOf[AnyRef] + case m ⇒ Await.result(actor.?(m, timeout), timeout.duration).asInstanceOf[AnyRef] } } } diff --git a/akka-actor/src/main/scala/akka/actor/package.scala b/akka-actor/src/main/scala/akka/actor/package.scala index 569c66f03e..cfe5bc1b0d 100644 --- a/akka-actor/src/main/scala/akka/actor/package.scala +++ b/akka-actor/src/main/scala/akka/actor/package.scala @@ -30,8 +30,10 @@ package object actor { implicit def future2actor[T](f: akka.dispatch.Future[T]) = new { def pipeTo(actor: ActorRef): this.type = { - def send(f: akka.dispatch.Future[T]) { f.value.get.fold(f ⇒ actor ! Status.Failure(f), r ⇒ actor ! r) } - if (f.isCompleted) send(f) else f onComplete send + f onComplete { + case Right(r) ⇒ actor ! r + case Left(f) ⇒ actor ! Status.Failure(f) + } this } } diff --git a/akka-actor/src/main/scala/akka/dispatch/Future.scala b/akka-actor/src/main/scala/akka/dispatch/Future.scala index a09f28f6a9..2bbc1fcb15 100644 --- a/akka-actor/src/main/scala/akka/dispatch/Future.scala +++ b/akka-actor/src/main/scala/akka/dispatch/Future.scala @@ -13,7 +13,6 @@ import akka.japi.{ Procedure, Function ⇒ JFunc, Option ⇒ JOption } import scala.util.continuations._ -import java.util.concurrent.{ ConcurrentLinkedQueue, TimeUnit, Callable } import java.util.concurrent.TimeUnit.{ NANOSECONDS, MILLISECONDS } import java.lang.{ Iterable ⇒ JIterable } import java.util.{ LinkedList ⇒ JLinkedList } @@ -22,68 +21,56 @@ import scala.annotation.tailrec import scala.collection.mutable.Stack import akka.util.{ Switch, Duration, BoxedType } import java.util.concurrent.atomic.{ AtomicReferenceFieldUpdater, AtomicInteger, AtomicBoolean } +import java.util.concurrent.{ TimeoutException, ConcurrentLinkedQueue, TimeUnit, Callable } +import akka.dispatch.Await.CanAwait -class FutureTimeoutException(message: String, cause: Throwable = null) extends AkkaException(message, cause) { - def this(message: String) = this(message, null) +object Await { + sealed trait CanAwait + + trait Awaitable[+T] { + /** + * Should throw java.util.concurrent.TimeoutException if times out + */ + def ready(atMost: Duration)(implicit permit: CanAwait): this.type + + /** + * Throws exceptions if cannot produce a T within the specified time + */ + def result(atMost: Duration)(implicit permit: CanAwait): T + } + + private implicit val permit = new CanAwait {} + + def ready[T <: Awaitable[_]](awaitable: T, atMost: Duration): T = awaitable.ready(atMost) + def result[T](awaitable: Awaitable[T], atMost: Duration): T = awaitable.result(atMost) } -class FutureFactory()(implicit dispatcher: MessageDispatcher, timeout: Timeout) { +object Futures { /** * Java API, equivalent to Future.apply */ - def future[T](body: Callable[T]): Future[T] = - Future(body.call, timeout) + def future[T](body: Callable[T], dispatcher: MessageDispatcher): Future[T] = Future(body.call)(dispatcher) /** - * Java API, equivalent to Future.apply + * Java API, equivalent to Promise.apply */ - def future[T](body: Callable[T], timeout: Timeout): Future[T] = - Future(body.call, timeout) - - /** - * Java API, equivalent to Future.apply - */ - def future[T](body: Callable[T], timeout: Long): Future[T] = - Future(body.call, timeout) - - /** - * Java API, equivalent to Future.apply - */ - def future[T](body: Callable[T], dispatcher: MessageDispatcher): Future[T] = - Future(body.call)(dispatcher, timeout) - - /** - * Java API, equivalent to Future.apply - */ - def future[T](body: Callable[T], timeout: Timeout, dispatcher: MessageDispatcher): Future[T] = - Future(body.call)(dispatcher, timeout) - - /** - * Java API, equivalent to Future.apply - */ - def future[T](body: Callable[T], timeout: Long, dispatcher: MessageDispatcher): Future[T] = - Future(body.call)(dispatcher, timeout) + def promise[T](dispatcher: MessageDispatcher): Promise[T] = Promise[T]()(dispatcher) /** * Java API. * Returns a Future that will hold the optional result of the first Future with a result that matches the predicate */ - def find[T <: AnyRef](futures: JIterable[Future[T]], predicate: JFunc[T, java.lang.Boolean], timeout: Timeout): Future[JOption[T]] = { - val pred: T ⇒ Boolean = predicate.apply(_) - Future.find[T]((scala.collection.JavaConversions.iterableAsScalaIterable(futures)), timeout)(pred).map(JOption.fromScalaOption(_))(timeout) + def find[T <: AnyRef](futures: JIterable[Future[T]], predicate: JFunc[T, java.lang.Boolean], dispatcher: MessageDispatcher): Future[JOption[T]] = { + Future.find[T]((scala.collection.JavaConversions.iterableAsScalaIterable(futures)))(predicate.apply(_))(dispatcher).map(JOption.fromScalaOption(_)) } - def find[T <: AnyRef](futures: JIterable[Future[T]], predicate: JFunc[T, java.lang.Boolean]): Future[JOption[T]] = find(futures, predicate, timeout) - /** * Java API. * Returns a Future to the result of the first future in the list that is completed */ - def firstCompletedOf[T <: AnyRef](futures: JIterable[Future[T]], timeout: Timeout): Future[T] = - Future.firstCompletedOf(scala.collection.JavaConversions.iterableAsScalaIterable(futures), timeout) - - def firstCompletedOf[T <: AnyRef](futures: JIterable[Future[T]]): Future[T] = firstCompletedOf(futures, timeout) + def firstCompletedOf[T <: AnyRef](futures: JIterable[Future[T]], dispatcher: MessageDispatcher): Future[T] = + Future.firstCompletedOf(scala.collection.JavaConversions.iterableAsScalaIterable(futures))(dispatcher) /** * Java API @@ -92,31 +79,23 @@ class FutureFactory()(implicit dispatcher: MessageDispatcher, timeout: Timeout) * the result will be the first failure of any of the futures, or any failure in the actual fold, * or the result of the fold. */ - def fold[T <: AnyRef, R <: AnyRef](zero: R, timeout: Timeout, futures: java.lang.Iterable[Future[T]], fun: akka.japi.Function2[R, T, R]): Future[R] = - Future.fold(scala.collection.JavaConversions.iterableAsScalaIterable(futures), timeout)(zero)(fun.apply _) - - def fold[T <: AnyRef, R <: AnyRef](zero: R, timeout: Long, futures: java.lang.Iterable[Future[T]], fun: akka.japi.Function2[R, T, R]): Future[R] = fold(zero, timeout: Timeout, futures, fun) - - def fold[T <: AnyRef, R <: AnyRef](zero: R, futures: java.lang.Iterable[Future[T]], fun: akka.japi.Function2[R, T, R]): Future[R] = fold(zero, timeout, futures, fun) + def fold[T <: AnyRef, R <: AnyRef](zero: R, futures: JIterable[Future[T]], fun: akka.japi.Function2[R, T, R], dispatcher: MessageDispatcher): Future[R] = + Future.fold(scala.collection.JavaConversions.iterableAsScalaIterable(futures))(zero)(fun.apply _)(dispatcher) /** * Java API. * Initiates a fold over the supplied futures where the fold-zero is the result value of the Future that's completed first */ - def reduce[T <: AnyRef, R >: T](futures: java.lang.Iterable[Future[T]], timeout: Timeout, fun: akka.japi.Function2[R, T, T]): Future[R] = - Future.reduce(scala.collection.JavaConversions.iterableAsScalaIterable(futures), timeout)(fun.apply _) - - def reduce[T <: AnyRef, R >: T](futures: java.lang.Iterable[Future[T]], timeout: Long, fun: akka.japi.Function2[R, T, T]): Future[R] = reduce(futures, timeout: Timeout, fun) - - def reduce[T <: AnyRef, R >: T](futures: java.lang.Iterable[Future[T]], fun: akka.japi.Function2[R, T, T]): Future[R] = reduce(futures, timeout, fun) + def reduce[T <: AnyRef, R >: T](futures: JIterable[Future[T]], fun: akka.japi.Function2[R, T, T], dispatcher: MessageDispatcher): Future[R] = + Future.reduce(scala.collection.JavaConversions.iterableAsScalaIterable(futures))(fun.apply _)(dispatcher) /** * Java API. - * Simple version of Future.traverse. Transforms a java.lang.Iterable[Future[A]] into a Future[java.lang.Iterable[A]]. + * Simple version of Future.traverse. Transforms a JIterable[Future[A]] into a Future[JIterable[A]]. * Useful for reducing many Futures into a single Future. */ - def sequence[A](in: JIterable[Future[A]], timeout: Timeout): Future[JIterable[A]] = { - implicit val t = timeout + def sequence[A](in: JIterable[Future[A]], dispatcher: MessageDispatcher): Future[JIterable[A]] = { + implicit val d = dispatcher scala.collection.JavaConversions.iterableAsScalaIterable(in).foldLeft(Future(new JLinkedList[A]()))((fr, fa) ⇒ for (r ← fr; a ← fa) yield { r add a @@ -124,27 +103,19 @@ class FutureFactory()(implicit dispatcher: MessageDispatcher, timeout: Timeout) }) } - def sequence[A](in: JIterable[Future[A]]): Future[JIterable[A]] = sequence(in, timeout) - /** * Java API. - * Transforms a java.lang.Iterable[A] into a Future[java.lang.Iterable[B]] using the provided Function A ⇒ Future[B]. + * Transforms a JIterable[A] into a Future[JIterable[B]] using the provided Function A ⇒ Future[B]. * This is useful for performing a parallel map. For example, to apply a function to all items of a list * in parallel. */ - def traverse[A, B](in: JIterable[A], timeout: Timeout, fn: JFunc[A, Future[B]]): Future[JIterable[B]] = { - implicit val t = timeout + def traverse[A, B](in: JIterable[A], fn: JFunc[A, Future[B]], dispatcher: MessageDispatcher): Future[JIterable[B]] = { + implicit val d = dispatcher scala.collection.JavaConversions.iterableAsScalaIterable(in).foldLeft(Future(new JLinkedList[B]())) { (fr, a) ⇒ val fb = fn(a) - for (r ← fr; b ← fb) yield { - r add b - r - } + for (r ← fr; b ← fb) yield { r add b; r } } } - - def traverse[A, B](in: JIterable[A], fn: JFunc[A, Future[B]]): Future[JIterable[B]] = traverse(in, timeout, fn) - } object Future { @@ -153,8 +124,8 @@ object Future { * This method constructs and returns a Future that will eventually hold the result of the execution of the supplied body * The execution is performed by the specified Dispatcher. */ - def apply[T](body: ⇒ T)(implicit dispatcher: MessageDispatcher, timeout: Timeout): Future[T] = { - val promise = new DefaultPromise[T](timeout) + def apply[T](body: ⇒ T)(implicit dispatcher: MessageDispatcher): Future[T] = { + val promise = Promise[T]() dispatcher dispatchTask { () ⇒ promise complete { try { @@ -168,15 +139,6 @@ object Future { promise } - def apply[T](body: ⇒ T, timeout: Timeout)(implicit dispatcher: MessageDispatcher): Future[T] = - apply(body)(dispatcher, timeout) - - def apply[T](body: ⇒ T, timeout: Duration)(implicit dispatcher: MessageDispatcher): Future[T] = - apply(body)(dispatcher, timeout) - - def apply[T](body: ⇒ T, timeout: Long)(implicit dispatcher: MessageDispatcher): Future[T] = - apply(body)(dispatcher, timeout) - import scala.collection.mutable.Builder import scala.collection.generic.CanBuildFrom @@ -184,50 +146,45 @@ object Future { * Simple version of Futures.traverse. Transforms a Traversable[Future[A]] into a Future[Traversable[A]]. * Useful for reducing many Futures into a single Future. */ - def sequence[A, M[_] <: Traversable[_]](in: M[Future[A]])(implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]], timeout: Timeout, dispatcher: MessageDispatcher): Future[M[A]] = - in.foldLeft(new KeptPromise(Right(cbf(in))): Future[Builder[A, M[A]]])((fr, fa) ⇒ for (r ← fr; a ← fa.asInstanceOf[Future[A]]) yield (r += a)).map(_.result) - - def sequence[A, M[_] <: Traversable[_]](in: M[Future[A]], timeout: Timeout)(implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]], dispatcher: MessageDispatcher): Future[M[A]] = - sequence(in)(cbf, timeout, dispatcher) + def sequence[A, M[_] <: Traversable[_]](in: M[Future[A]])(implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]], dispatcher: MessageDispatcher): Future[M[A]] = + in.foldLeft(Promise.successful(cbf(in)): Future[Builder[A, M[A]]])((fr, fa) ⇒ for (r ← fr; a ← fa.asInstanceOf[Future[A]]) yield (r += a)).map(_.result) /** * Returns a Future to the result of the first future in the list that is completed */ - def firstCompletedOf[T](futures: Iterable[Future[T]])(implicit dispatcher: MessageDispatcher, timeout: Timeout): Future[T] = { - val futureResult = new DefaultPromise[T](timeout) + def firstCompletedOf[T](futures: Traversable[Future[T]])(implicit dispatcher: MessageDispatcher): Future[T] = { + val futureResult = Promise[T]() - val completeFirst: Future[T] ⇒ Unit = _.value.foreach(futureResult complete _) + val completeFirst: Either[Throwable, T] ⇒ Unit = futureResult complete _ futures.foreach(_ onComplete completeFirst) futureResult } - def firstCompletedOf[T](futures: Iterable[Future[T]], timeout: Timeout)(implicit dispatcher: MessageDispatcher): Future[T] = - firstCompletedOf(futures)(dispatcher, timeout) - /** * Returns a Future that will hold the optional result of the first Future with a result that matches the predicate */ - def find[T](futures: Iterable[Future[T]])(predicate: T ⇒ Boolean)(implicit dispatcher: MessageDispatcher, timeout: Timeout): Future[Option[T]] = { - if (futures.isEmpty) new KeptPromise[Option[T]](Right(None)) + def find[T](futures: Traversable[Future[T]])(predicate: T ⇒ Boolean)(implicit dispatcher: MessageDispatcher): Future[Option[T]] = { + if (futures.isEmpty) Promise.successful[Option[T]](None) else { - val result = new DefaultPromise[Option[T]](timeout) + val result = Promise[Option[T]]() val ref = new AtomicInteger(futures.size) - val search: Future[T] ⇒ Unit = f ⇒ try { - f.result.filter(predicate).foreach(r ⇒ result completeWithResult Some(r)) + val search: Either[Throwable, T] ⇒ Unit = v ⇒ try { + v match { + case Right(r) ⇒ if (predicate(r)) result success Some(r) + case _ ⇒ + } } finally { if (ref.decrementAndGet == 0) - result completeWithResult None + result success None } + futures.foreach(_ onComplete search) result } } - def find[T](futures: Iterable[Future[T]], timeout: Timeout)(predicate: T ⇒ Boolean)(implicit dispatcher: MessageDispatcher): Future[Option[T]] = - find(futures)(predicate)(dispatcher, timeout) - /** * A non-blocking fold over the specified futures. * The fold is performed on the thread where the last future is completed, @@ -235,83 +192,25 @@ object Future { * or the result of the fold. * Example: *
-   *   val result = Futures.fold(0)(futures)(_ + _).await.result
+   *   val result = Await.result(Futures.fold(0)(futures)(_ + _), 5 seconds)
    * 
*/ - def fold[T, R](futures: Iterable[Future[T]])(zero: R)(foldFun: (R, T) ⇒ R)(implicit dispatcher: MessageDispatcher, timeout: Timeout): Future[R] = { - if (futures.isEmpty) { - new KeptPromise[R](Right(zero)) - } else { - val result = new DefaultPromise[R](timeout) - val results = new ConcurrentLinkedQueue[T]() - val done = new Switch(false) - val allDone = futures.size - - val aggregate: Future[T] ⇒ Unit = f ⇒ if (done.isOff && !result.isCompleted) { //TODO: This is an optimization, is it premature? - f.value.get match { - case Right(value) ⇒ - val added = results add value - if (added && results.size == allDone) { //Only one thread can get here - if (done.switchOn) { - try { - val i = results.iterator - var currentValue = zero - while (i.hasNext) { currentValue = foldFun(currentValue, i.next) } - result completeWithResult currentValue - } catch { - case e: Exception ⇒ - dispatcher.prerequisites.eventStream.publish(Error(e, "Future.fold", e.getMessage)) - result completeWithException e - } finally { - results.clear - } - } - } - case Left(exception) ⇒ - if (done.switchOn) { - result completeWithException exception - results.clear - } - } - } - - futures foreach { _ onComplete aggregate } - result - } + def fold[T, R](futures: Traversable[Future[T]])(zero: R)(foldFun: (R, T) ⇒ R)(implicit dispatcher: MessageDispatcher): Future[R] = { + if (futures.isEmpty) Promise.successful(zero) + else sequence(futures).map(_.foldLeft(zero)(foldFun)) } - def fold[T, R](futures: Iterable[Future[T]], timeout: Timeout)(zero: R)(foldFun: (R, T) ⇒ R)(implicit dispatcher: MessageDispatcher): Future[R] = - fold(futures)(zero)(foldFun)(dispatcher, timeout) - /** * Initiates a fold over the supplied futures where the fold-zero is the result value of the Future that's completed first * Example: *
-   *   val result = Futures.reduce(futures)(_ + _).await.result
+   *   val result = Await.result(Futures.reduce(futures)(_ + _), 5 seconds)
    * 
*/ - def reduce[T, R >: T](futures: Iterable[Future[T]])(op: (R, T) ⇒ T)(implicit dispatcher: MessageDispatcher, timeout: Timeout): Future[R] = { - if (futures.isEmpty) - new KeptPromise[R](Left(new UnsupportedOperationException("empty reduce left"))) - else { - val result = new DefaultPromise[R](timeout) - val seedFound = new AtomicBoolean(false) - val seedFold: Future[T] ⇒ Unit = f ⇒ { - if (seedFound.compareAndSet(false, true)) { //Only the first completed should trigger the fold - f.value.get match { - case Right(value) ⇒ result.completeWith(fold(futures.filterNot(_ eq f))(value)(op)) - case Left(exception) ⇒ result.completeWithException(exception) - } - } - } - for (f ← futures) f onComplete seedFold //Attach the listener to the Futures - result - } + def reduce[T, R >: T](futures: Traversable[Future[T]])(op: (R, T) ⇒ T)(implicit dispatcher: MessageDispatcher): Future[R] = { + if (futures.isEmpty) Promise[R].failure(new NoSuchElementException("reduce attempted on empty collection")) + else sequence(futures).map(_ reduce op) } - - def reduce[T, R >: T](futures: Iterable[Future[T]], timeout: Timeout)(op: (R, T) ⇒ T)(implicit dispatcher: MessageDispatcher): Future[R] = - reduce(futures)(op)(dispatcher, timeout) - /** * Transforms a Traversable[A] into a Future[Traversable[B]] using the provided Function A ⇒ Future[B]. * This is useful for performing a parallel map. For example, to apply a function to all items of a list @@ -320,15 +219,12 @@ object Future { * val myFutureList = Futures.traverse(myList)(x ⇒ Future(myFunc(x))) * */ - def traverse[A, B, M[_] <: Traversable[_]](in: M[A])(fn: A ⇒ Future[B])(implicit cbf: CanBuildFrom[M[A], B, M[B]], timeout: Timeout, dispatcher: MessageDispatcher): Future[M[B]] = - in.foldLeft(new KeptPromise(Right(cbf(in))): Future[Builder[B, M[B]]]) { (fr, a) ⇒ + def traverse[A, B, M[_] <: Traversable[_]](in: M[A])(fn: A ⇒ Future[B])(implicit cbf: CanBuildFrom[M[A], B, M[B]], dispatcher: MessageDispatcher): Future[M[B]] = + in.foldLeft(Promise.successful(cbf(in)): Future[Builder[B, M[B]]]) { (fr, a) ⇒ val fb = fn(a.asInstanceOf[A]) for (r ← fr; b ← fb) yield (r += b) }.map(_.result) - def traverse[A, B, M[_] <: Traversable[_]](in: M[A], timeout: Timeout)(fn: A ⇒ Future[B])(implicit cbf: CanBuildFrom[M[A], B, M[B]], dispatcher: MessageDispatcher): Future[M[B]] = - traverse(in)(fn)(cbf, timeout, dispatcher) - /** * Captures a block that will be transformed into 'Continuation Passing Style' using Scala's Delimited * Continuations plugin. @@ -345,18 +241,16 @@ object Future { * * The Delimited Continuations compiler plugin must be enabled in order to use this method. */ - def flow[A](body: ⇒ A @cps[Future[Any]])(implicit dispatcher: MessageDispatcher, timeout: Timeout): Future[A] = { - val future = Promise[A](timeout) + def flow[A](body: ⇒ A @cps[Future[Any]])(implicit dispatcher: MessageDispatcher): Future[A] = { + val future = Promise[A] dispatchTask({ () ⇒ - (reify(body) foreachFull (future completeWithResult, future completeWithException): Future[Any]) onException { - case e: Exception ⇒ future completeWithException e + (reify(body) foreachFull (future success, future failure): Future[Any]) onFailure { + case e: Exception ⇒ future failure e } }, true) future } - // TODO make variant of flow(timeout)(body) which does NOT break type inference - /** * Assures that any Future tasks initiated in the current thread will be * executed asynchronously, including any tasks currently queued to be @@ -364,7 +258,7 @@ object Future { * block, causing delays in executing the remaining tasks which in some * cases may cause a deadlock. * - * Note: Calling 'Future.await' will automatically trigger this method. + * Note: Calling 'Await.result(future)' or 'Await.ready(future)' will automatically trigger this method. * * For example, in the following block of code the call to 'latch.open' * might not be executed until after the call to 'latch.await', causing @@ -381,7 +275,7 @@ object Future { * } * */ - def blocking()(implicit dispatcher: MessageDispatcher): Unit = + def blocking(implicit dispatcher: MessageDispatcher): Unit = _taskStack.get match { case Some(taskStack) if taskStack.nonEmpty ⇒ val tasks = taskStack.elems @@ -419,7 +313,7 @@ object Future { } } -sealed trait Future[+T] extends japi.Future[T] { +sealed trait Future[+T] extends japi.Future[T] with Await.Awaitable[T] { implicit def dispatcher: MessageDispatcher @@ -429,92 +323,13 @@ sealed trait Future[+T] extends japi.Future[T] { * Returns the result of this Future without blocking, by suspending execution and storing it as a * continuation until the result is available. */ - def apply()(implicit timeout: Timeout): T @cps[Future[Any]] = shift(this flatMap (_: T ⇒ Future[Any])) - - /** - * Blocks awaiting completion of this Future, then returns the resulting value, - * or throws the completed exception - * - * Scala & Java API - * - * throws FutureTimeoutException if this Future times out when waiting for completion - */ - def get: T = this.await.resultOrException.get - - /** - * Blocks the current thread until the Future has been completed or the - * timeout has expired. In the case of the timeout expiring a - * FutureTimeoutException will be thrown. - */ - def await: Future[T] - - /** - * Blocks the current thread until the Future has been completed or the - * timeout has expired, additionally bounding the waiting period according to - * the atMost parameter. The timeout will be the lesser value of - * 'atMost' and the timeout supplied at the constructuion of this Future. In - * the case of the timeout expiring a FutureTimeoutException will be thrown. - * Other callers of this method are not affected by the additional bound - * imposed by atMost. - */ - def await(atMost: Duration): Future[T] - - /** - * Await completion of this Future and return its value if it conforms to A's - * erased type. Will throw a ClassCastException if the value does not - * conform, or any exception the Future was completed with. Will return None - * in case of a timeout. - */ - def as[A](implicit m: Manifest[A]): Option[A] = { - try await catch { case _: FutureTimeoutException ⇒ } - value match { - case None ⇒ None - case Some(Left(ex)) ⇒ throw ex - case Some(Right(v)) ⇒ - try { Some(BoxedType(m.erasure).cast(v).asInstanceOf[A]) } catch { - case c: ClassCastException ⇒ - if (v.asInstanceOf[AnyRef] eq null) throw new ClassCastException("null cannot be cast to " + m.erasure) - else throw new ClassCastException("'" + v + "' of class " + v.asInstanceOf[AnyRef].getClass + " cannot be cast to " + m.erasure) - } - } - } - - /** - * Await completion of this Future and return its value if it conforms to A's - * erased type, None otherwise. Will throw any exception the Future was - * completed with. Will return None in case of a timeout. - */ - def asSilently[A](implicit m: Manifest[A]): Option[A] = { - try await catch { case _: FutureTimeoutException ⇒ } - value match { - case None ⇒ None - case Some(Left(ex)) ⇒ throw ex - case Some(Right(v)) ⇒ - try Some(BoxedType(m.erasure).cast(v).asInstanceOf[A]) - catch { case _: ClassCastException ⇒ None } - } - } + def apply(): T @cps[Future[Any]] = shift(this flatMap (_: T ⇒ Future[Any])) /** * Tests whether this Future has been completed. */ final def isCompleted: Boolean = value.isDefined - /** - * Tests whether this Future's timeout has expired. - * - * Note that an expired Future may still contain a value, or it may be - * completed with a value. - */ - def isExpired: Boolean - - def timeout: Timeout - - /** - * This Future's timeout in nanoseconds. - */ - def timeoutInNanos = if (timeout.duration.isFinite) timeout.duration.toNanos else Long.MaxValue - /** * The contained value of this Future. Before this Future is completed * the value will be None. After completion the value will be Some(Right(t)) @@ -523,68 +338,64 @@ sealed trait Future[+T] extends japi.Future[T] { */ def value: Option[Either[Throwable, T]] - /** - * Returns the successful result of this Future if it exists. - */ - final def result: Option[T] = value match { - case Some(Right(r)) ⇒ Some(r) - case _ ⇒ None - } - - /** - * Returns the contained exception of this Future if it exists. - */ - final def exception: Option[Throwable] = value match { - case Some(Left(e)) ⇒ Some(e) - case _ ⇒ None - } - /** * When this Future is completed, apply the provided function to the * Future. If the Future has already been completed, this will apply - * immediately. Will not be called in case of a timeout, which also holds if - * corresponding Promise is attempted to complete after expiry. Multiple + * immediately. Multiple * callbacks may be registered; there is no guarantee that they will be * executed in a particular order. */ - def onComplete(func: Future[T] ⇒ Unit): this.type + def onComplete(func: Either[Throwable, T] ⇒ Unit): this.type /** * When the future is completed with a valid result, apply the provided * PartialFunction to the result. See `onComplete` for more details. *
-   *   future onResult {
+   *   future onSuccess {
    *     case Foo ⇒ target ! "foo"
    *     case Bar ⇒ target ! "bar"
    *   }
    * 
*/ - final def onResult(pf: PartialFunction[T, Unit]): this.type = onComplete { - _.value match { - case Some(Right(r)) if pf isDefinedAt r ⇒ pf(r) - case _ ⇒ - } + final def onSuccess[U](pf: PartialFunction[T, U]): this.type = onComplete { + case Right(r) if pf isDefinedAt r ⇒ pf(r) + case _ ⇒ } /** * When the future is completed with an exception, apply the provided * PartialFunction to the exception. See `onComplete` for more details. *
-   *   future onException {
+   *   future onFailure {
    *     case NumberFormatException ⇒ target ! "wrong format"
    *   }
    * 
*/ - final def onException(pf: PartialFunction[Throwable, Unit]): this.type = onComplete { - _.value match { - case Some(Left(ex)) if pf isDefinedAt ex ⇒ pf(ex) - case _ ⇒ - } + final def onFailure[U](pf: PartialFunction[Throwable, U]): this.type = onComplete { + case Left(ex) if pf isDefinedAt ex ⇒ pf(ex) + case _ ⇒ } - def onTimeout(func: Future[T] ⇒ Unit): this.type + /** + * Returns a failure projection of this Future + * If `this` becomes completed with a failure, that failure will be the success of the returned Future + * If `this` becomes completed with a result, then the returned future will fail with a NoSuchElementException + */ + final def failed: Future[Throwable] = { + val p = Promise[Throwable]() + this.onComplete { + case Left(t) ⇒ p success t + case Right(r) ⇒ p failure new NoSuchElementException("Future.failed not completed with a throwable. Instead completed with: " + r) + } + p + } - def orElse[A >: T](fallback: ⇒ A): Future[A] + /** + * Creates a Future that will be the result of the first completed Future of this and the Future that was passed into this. + * This is semantically the same as: Future.firstCompletedOf(Seq(this, that)) + */ + //FIXME implement as The result of any of the Futures, or if oth failed, the first failure + def orElse[A >: T](that: Future[A]): Future[A] = Future.firstCompletedOf(List(this, that)) //TODO Optimize /** * Creates a new Future that will handle any matching Throwable that this @@ -597,13 +408,11 @@ sealed trait Future[+T] extends japi.Future[T] { * Future(6 / 2) recover { case e: ArithmeticException ⇒ 0 } // result: 3 * */ - final def recover[A >: T](pf: PartialFunction[Throwable, A])(implicit timeout: Timeout): Future[A] = { - val future = new DefaultPromise[A](timeout) + final def recover[A >: T](pf: PartialFunction[Throwable, A]): Future[A] = { + val future = Promise[A]() onComplete { - _.value.get match { - case Left(e) if pf isDefinedAt e ⇒ future.complete(try { Right(pf(e)) } catch { case x: Exception ⇒ Left(x) }) - case otherwise ⇒ future complete otherwise - } + case Left(e) if pf isDefinedAt e ⇒ future.complete(try { Right(pf(e)) } catch { case x: Exception ⇒ Left(x) }) + case otherwise ⇒ future complete otherwise } future } @@ -621,20 +430,18 @@ sealed trait Future[+T] extends japi.Future[T] { * } yield b + "-" + c * */ - final def map[A](f: T ⇒ A)(implicit timeout: Timeout): Future[A] = { - val future = new DefaultPromise[A](timeout) + final def map[A](f: T ⇒ A): Future[A] = { + val future = Promise[A]() onComplete { - _.value.get match { - case l: Left[_, _] ⇒ future complete l.asInstanceOf[Either[Throwable, A]] - case Right(res) ⇒ - future complete (try { - Right(f(res)) - } catch { - case e: Exception ⇒ - dispatcher.prerequisites.eventStream.publish(Error(e, "Future.map", e.getMessage)) - Left(e) - }) - } + case l: Left[_, _] ⇒ future complete l.asInstanceOf[Either[Throwable, A]] + case Right(res) ⇒ + future complete (try { + Right(f(res)) + } catch { + case e: Exception ⇒ + dispatcher.prerequisites.eventStream.publish(Error(e, "Future.map", e.getMessage)) + Left(e) + }) } future } @@ -643,18 +450,16 @@ sealed trait Future[+T] extends japi.Future[T] { * Creates a new Future[A] which is completed with this Future's result if * that conforms to A's erased type or a ClassCastException otherwise. */ - final def mapTo[A](implicit m: Manifest[A], timeout: Timeout = this.timeout): Future[A] = { - val fa = new DefaultPromise[A](timeout) - onComplete { ft ⇒ - fa complete (ft.value.get match { - case l: Left[_, _] ⇒ l.asInstanceOf[Either[Throwable, A]] - case Right(t) ⇒ - try { - Right(BoxedType(m.erasure).cast(t).asInstanceOf[A]) - } catch { - case e: ClassCastException ⇒ Left(e) - } - }) + final def mapTo[A](implicit m: Manifest[A]): Future[A] = { + val fa = Promise[A]() + onComplete { + case l: Left[_, _] ⇒ fa complete l.asInstanceOf[Either[Throwable, A]] + case Right(t) ⇒ + fa complete (try { + Right(BoxedType(m.erasure).cast(t).asInstanceOf[A]) + } catch { + case e: ClassCastException ⇒ Left(e) + }) } fa } @@ -673,137 +478,143 @@ sealed trait Future[+T] extends japi.Future[T] { * } yield b + "-" + c * */ - final def flatMap[A](f: T ⇒ Future[A])(implicit timeout: Timeout): Future[A] = { - val future = new DefaultPromise[A](timeout) + final def flatMap[A](f: T ⇒ Future[A]): Future[A] = { + val p = Promise[A]() onComplete { - _.value.get match { - case l: Left[_, _] ⇒ future complete l.asInstanceOf[Either[Throwable, A]] - case Right(r) ⇒ try { - future.completeWith(f(r)) + case l: Left[_, _] ⇒ p complete l.asInstanceOf[Either[Throwable, A]] + case Right(r) ⇒ + try { + p completeWith f(r) } catch { case e: Exception ⇒ + p complete Left(e) dispatcher.prerequisites.eventStream.publish(Error(e, "Future.flatMap", e.getMessage)) - future complete Left(e) } - } } - future + p } final def foreach(f: T ⇒ Unit): Unit = onComplete { - _.value.get match { - case Right(r) ⇒ f(r) - case _ ⇒ - } + case Right(r) ⇒ f(r) + case _ ⇒ } - final def withFilter(p: T ⇒ Boolean)(implicit timeout: Timeout) = new FutureWithFilter[T](this, p) + final def withFilter(p: T ⇒ Boolean) = new FutureWithFilter[T](this, p) - final class FutureWithFilter[+A](self: Future[A], p: A ⇒ Boolean)(implicit timeout: Timeout) { + final class FutureWithFilter[+A](self: Future[A], p: A ⇒ Boolean) { def foreach(f: A ⇒ Unit): Unit = self filter p foreach f def map[B](f: A ⇒ B): Future[B] = self filter p map f def flatMap[B](f: A ⇒ Future[B]): Future[B] = self filter p flatMap f def withFilter(q: A ⇒ Boolean): FutureWithFilter[A] = new FutureWithFilter[A](self, x ⇒ p(x) && q(x)) } - final def filter(p: T ⇒ Boolean)(implicit timeout: Timeout): Future[T] = { - val future = new DefaultPromise[T](timeout) + final def filter(pred: T ⇒ Boolean): Future[T] = { + val p = Promise[T]() onComplete { - _.value.get match { - case l: Left[_, _] ⇒ future complete l.asInstanceOf[Either[Throwable, T]] - case r @ Right(res) ⇒ future complete (try { - if (p(res)) r else Left(new MatchError(res)) - } catch { - case e: Exception ⇒ - dispatcher.prerequisites.eventStream.publish(Error(e, "Future.filter", e.getMessage)) - Left(e) - }) - } + case l: Left[_, _] ⇒ p complete l.asInstanceOf[Either[Throwable, T]] + case r @ Right(res) ⇒ p complete (try { + if (pred(res)) r else Left(new MatchError(res)) + } catch { + case e: Exception ⇒ + dispatcher.prerequisites.eventStream.publish(Error(e, "Future.filter", e.getMessage)) + Left(e) + }) } - future - } - - /** - * Returns the current result, throws the exception if one has been raised, else returns None - */ - final def resultOrException: Option[T] = value match { - case Some(Left(e)) ⇒ throw e - case Some(Right(r)) ⇒ Some(r) - case _ ⇒ None + p } } object Promise { + /** + * Creates a non-completed Promise + * + * Scala API + */ + def apply[A]()(implicit dispatcher: MessageDispatcher): Promise[A] = new DefaultPromise[A]() /** - * Creates a non-completed, new, Promise with the supplied timeout in milliseconds + * Creates an already completed Promise with the specified exception */ - def apply[A](timeout: Timeout)(implicit dispatcher: MessageDispatcher): Promise[A] = new DefaultPromise[A](timeout) + def failed[T](exception: Throwable)(implicit dispatcher: MessageDispatcher): Promise[T] = new KeptPromise[T](Left(exception)) /** - * Creates a non-completed, new, Promise with the default timeout (akka.actor.timeout in conf) + * Creates an already completed Promise with the specified result */ - def apply[A]()(implicit dispatcher: MessageDispatcher, timeout: Timeout): Promise[A] = apply(timeout) + def successful[T](result: T)(implicit dispatcher: MessageDispatcher): Promise[T] = new KeptPromise[T](Right(result)) } /** * Essentially this is the Promise (or write-side) of a Future (read-side). */ trait Promise[T] extends Future[T] { - /** - * Completes this Future with the specified result, if not already completed. - * @return this - */ - def complete(value: Either[Throwable, T]): this.type /** - * Completes this Future with the specified result, if not already completed. - * @return this + * Returns the Future associated with this Promise */ - final def completeWithResult(result: T): this.type = complete(Right(result)) + def future: Future[T] = this /** - * Completes this Future with the specified exception, if not already completed. - * @return this + * Completes this Promise with the specified result, if not already completed. + * @return whether this call completed the Promise */ - final def completeWithException(exception: Throwable): this.type = complete(Left(exception)) + def tryComplete(value: Either[Throwable, T]): Boolean /** - * Completes this Future with the specified other Future, when that Future is completed, - * unless this Future has already been completed. + * Completes this Promise with the specified result, if not already completed. + * @return this + */ + final def complete(value: Either[Throwable, T]): this.type = { tryComplete(value); this } + + /** + * Completes this Promise with the specified result, if not already completed. + * @return this + */ + final def success(result: T): this.type = complete(Right(result)) + + /** + * Completes this Promise with the specified exception, if not already completed. + * @return this + */ + final def failure(exception: Throwable): this.type = complete(Left(exception)) + + /** + * Completes this Promise with the specified other Future, when that Future is completed, + * unless this Promise has already been completed. * @return this. */ final def completeWith(other: Future[T]): this.type = { - other onComplete { f ⇒ complete(f.value.get) } + other onComplete { complete(_) } this } final def <<(value: T): Future[T] @cps[Future[Any]] = shift { cont: (Future[T] ⇒ Future[Any]) ⇒ cont(complete(Right(value))) } final def <<(other: Future[T]): Future[T] @cps[Future[Any]] = shift { cont: (Future[T] ⇒ Future[Any]) ⇒ - val fr = new DefaultPromise[Any](this.timeout) - this completeWith other onComplete { f ⇒ + val fr = Promise[Any]() + val thisPromise = this + thisPromise completeWith other onComplete { v ⇒ try { - fr completeWith cont(f) + fr completeWith cont(thisPromise) } catch { case e: Exception ⇒ dispatcher.prerequisites.eventStream.publish(Error(e, "Promise.completeWith", e.getMessage)) - fr completeWithException e + fr failure e } } fr } final def <<(stream: PromiseStreamOut[T]): Future[T] @cps[Future[Any]] = shift { cont: (Future[T] ⇒ Future[Any]) ⇒ - val fr = new DefaultPromise[Any](this.timeout) - stream.dequeue(this).onComplete { f ⇒ + val fr = Promise[Any]() + val f = stream.dequeue(this) + f.onComplete { _ ⇒ try { fr completeWith cont(f) } catch { case e: Exception ⇒ dispatcher.prerequisites.eventStream.publish(Error(e, "Promise.completeWith", e.getMessage)) - fr completeWithException e + fr failure e } } fr @@ -819,7 +630,7 @@ private[dispatch] object DefaultPromise { */ sealed trait FState[+T] { def value: Option[Either[Throwable, T]] } - case class Pending[T](listeners: List[Future[T] ⇒ Unit] = Nil) extends FState[T] { + case class Pending[T](listeners: List[Either[Throwable, T] ⇒ Unit] = Nil) extends FState[T] { def value: Option[Either[Throwable, T]] = None } case class Success[T](value: Option[Either[Throwable, T]] = None) extends FState[T] { @@ -828,94 +639,68 @@ private[dispatch] object DefaultPromise { case class Failure[T](value: Option[Either[Throwable, T]] = None) extends FState[T] { def exception: Throwable = value.get.left.get } - case object Expired extends FState[Nothing] { - def value: Option[Either[Throwable, Nothing]] = None - } private val emptyPendingValue = Pending[Nothing](Nil) } /** * The default concrete Future implementation. */ -class DefaultPromise[T](val timeout: Timeout)(implicit val dispatcher: MessageDispatcher) extends AbstractPromise with Promise[T] { +class DefaultPromise[T](implicit val dispatcher: MessageDispatcher) extends AbstractPromise with Promise[T] { self ⇒ - import DefaultPromise.{ FState, Success, Failure, Pending, Expired } + import DefaultPromise.{ FState, Success, Failure, Pending } - def this()(implicit dispatcher: MessageDispatcher, timeout: Timeout) = this(timeout) + protected final def tryAwait(atMost: Duration): Boolean = { + Future.blocking - def this(timeout: Long)(implicit dispatcher: MessageDispatcher) = this(Timeout(timeout)) + @tailrec + def awaitUnsafe(waitTimeNanos: Long): Boolean = { + if (value.isEmpty && waitTimeNanos > 0) { + val ms = NANOSECONDS.toMillis(waitTimeNanos) + val ns = (waitTimeNanos % 1000000l).toInt //As per object.wait spec + val start = System.nanoTime() + try { synchronized { if (value.isEmpty) wait(ms, ns) } } catch { case e: InterruptedException ⇒ } - def this(timeout: Long, timeunit: TimeUnit)(implicit dispatcher: MessageDispatcher) = this(Timeout(timeout, timeunit)) - - private val _startTimeInNanos = currentTimeInNanos - - @tailrec - private def awaitUnsafe(waitTimeNanos: Long): Boolean = { - if (value.isEmpty && waitTimeNanos > 0) { - val ms = NANOSECONDS.toMillis(waitTimeNanos) - val ns = (waitTimeNanos % 1000000l).toInt //As per object.wait spec - val start = currentTimeInNanos - try { synchronized { if (value.isEmpty) wait(ms, ns) } } catch { case e: InterruptedException ⇒ } - - awaitUnsafe(waitTimeNanos - (currentTimeInNanos - start)) - } else { - value.isDefined + awaitUnsafe(waitTimeNanos - (System.nanoTime() - start)) + } else + value.isDefined } + awaitUnsafe(if (atMost.isFinite) atMost.toNanos else Long.MaxValue) } - def await(atMost: Duration): this.type = if (value.isDefined) this else { - Future.blocking() + def ready(atMost: Duration)(implicit permit: CanAwait): this.type = + if (value.isDefined || tryAwait(atMost)) this + else throw new TimeoutException("Futures timed out after [" + atMost.toMillis + "] milliseconds") - val waitNanos = - if (timeout.duration.isFinite && atMost.isFinite) - atMost.toNanos min timeLeft() - else if (atMost.isFinite) - atMost.toNanos - else if (timeout.duration.isFinite) - timeLeft() - else Long.MaxValue //If both are infinite, use Long.MaxValue - - if (awaitUnsafe(waitNanos)) this - else throw new FutureTimeoutException("Futures timed out after [" + NANOSECONDS.toMillis(waitNanos) + "] milliseconds") - } - - def await = await(timeout.duration) - - def isExpired: Boolean = if (timeout.duration.isFinite) timeLeft() <= 0 else false + def result(atMost: Duration)(implicit permit: CanAwait): T = + ready(atMost).value.get match { + case Left(e) ⇒ throw e + case Right(r) ⇒ r + } def value: Option[Either[Throwable, T]] = getState.value @inline - protected final def updateState(oldState: FState[T], newState: FState[T]): Boolean = - AbstractPromise.updater.asInstanceOf[AtomicReferenceFieldUpdater[AbstractPromise, FState[T]]].compareAndSet(this, oldState, newState) + private[this] final def updater = AbstractPromise.updater.asInstanceOf[AtomicReferenceFieldUpdater[AbstractPromise, FState[T]]] @inline - protected final def getState: FState[T] = { + protected final def updateState(oldState: FState[T], newState: FState[T]): Boolean = updater.compareAndSet(this, oldState, newState) - @tailrec - def read(): FState[T] = { - val cur = AbstractPromise.updater.asInstanceOf[AtomicReferenceFieldUpdater[AbstractPromise, FState[T]]].get(this) - if (cur.isInstanceOf[Pending[_]] && isExpired) { - if (updateState(cur, Expired)) Expired else read() - } else cur - } + @inline + protected final def getState: FState[T] = updater.get(this) - read() - } - - def complete(value: Either[Throwable, T]): this.type = { - val callbacks = { + def tryComplete(value: Either[Throwable, T]): Boolean = { + val callbacks: List[Either[Throwable, T] ⇒ Unit] = { try { @tailrec - def tryComplete: List[Future[T] ⇒ Unit] = { + def tryComplete: List[Either[Throwable, T] ⇒ Unit] = { val cur = getState cur match { case Pending(listeners) ⇒ if (updateState(cur, if (value.isLeft) Failure(Some(value)) else Success(Some(value)))) listeners else tryComplete - case _ ⇒ Nil + case _ ⇒ null } } tryComplete @@ -924,120 +709,55 @@ class DefaultPromise[T](val timeout: Timeout)(implicit val dispatcher: MessageDi } } - if (callbacks.nonEmpty) Future.dispatchTask(() ⇒ callbacks foreach notifyCompleted) - - this + callbacks match { + case null ⇒ false + case cs if cs.isEmpty ⇒ true + case cs ⇒ Future.dispatchTask(() ⇒ cs.foreach(f ⇒ notifyCompleted(f, value))); true + } } - def onComplete(func: Future[T] ⇒ Unit): this.type = { + def onComplete(func: Either[Throwable, T] ⇒ Unit): this.type = { @tailrec //Returns whether the future has already been completed or not def tryAddCallback(): Boolean = { val cur = getState cur match { case _: Success[_] | _: Failure[_] ⇒ true - case Expired ⇒ false case p: Pending[_] ⇒ val pt = p.asInstanceOf[Pending[T]] - if (updateState(pt, pt.copy(listeners = func :: pt.listeners))) false - else tryAddCallback() + if (updateState(pt, pt.copy(listeners = func :: pt.listeners))) false else tryAddCallback() } } - if (tryAddCallback()) Future.dispatchTask(() ⇒ notifyCompleted(func)) + if (tryAddCallback()) { + val result = value.get + Future.dispatchTask(() ⇒ notifyCompleted(func, result)) + } this } - def onTimeout(func: Future[T] ⇒ Unit): this.type = { - val runNow = - if (!timeout.duration.isFinite) false //Not possible - else if (value.isEmpty) { - if (!isExpired) { - val runnable = new Runnable { - def run() { - if (!isCompleted) { - if (!isExpired) - try dispatcher.prerequisites.scheduler.scheduleOnce(Duration(timeLeftNoinline(), TimeUnit.NANOSECONDS), this) - catch { - case _: IllegalStateException ⇒ func(DefaultPromise.this) - } - else func(DefaultPromise.this) - } - } - } - val timeoutFuture = dispatcher.prerequisites.scheduler.scheduleOnce(Duration(timeLeft(), NANOSECONDS), runnable) - onComplete(_ ⇒ timeoutFuture.cancel()) - false - } else true - } else false - - if (runNow) Future.dispatchTask(() ⇒ notifyCompleted(func)) - - this + private final def notifyCompleted(func: Either[Throwable, T] ⇒ Unit, result: Either[Throwable, T]) { + try { func(result) } catch { case e ⇒ dispatcher.prerequisites.eventStream.publish(Error(e, "Future", "Future onComplete-callback raised an exception")) } } - - final def orElse[A >: T](fallback: ⇒ A): Future[A] = - if (timeout.duration.isFinite) { - getState match { - case _: Success[_] | _: Failure[_] ⇒ this - case Expired ⇒ Future[A](fallback, timeout) - case _: Pending[_] ⇒ - val promise = new DefaultPromise[A](Timeout.never) //TODO FIXME We can't have infinite timeout here, doesn't make sense. - promise completeWith this - val runnable = new Runnable { - def run() { - if (!isCompleted) { - val done = - if (!isExpired) - try { - dispatcher.prerequisites.scheduler.scheduleOnce(Duration(timeLeftNoinline(), TimeUnit.NANOSECONDS), this) - true - } catch { - case _: IllegalStateException ⇒ false - } - else false - if (!done) - promise complete (try { Right(fallback) } catch { case e ⇒ Left(e) }) // FIXME catching all and continue isn't good for OOME, ticket #1418 - } - } - } - dispatcher.prerequisites.scheduler.scheduleOnce(Duration(timeLeft(), NANOSECONDS), runnable) - promise - } - } else this - - private def notifyCompleted(func: Future[T] ⇒ Unit) { - // FIXME catching all and continue isn't good for OOME, ticket #1418 - try { func(this) } catch { case e ⇒ dispatcher.prerequisites.eventStream.publish(Error(e, "Future", "Future onComplete-callback raised an exception")) } //TODO catch, everything? Really? - } - - @inline - private def currentTimeInNanos: Long = MILLISECONDS.toNanos(System.currentTimeMillis) //TODO Switch to math.abs(System.nanoTime)? - //TODO: the danger of Math.abs is that it could break the ordering of time. So I would not recommend an abs. - @inline - private def timeLeft(): Long = timeoutInNanos - (currentTimeInNanos - _startTimeInNanos) - - private def timeLeftNoinline(): Long = timeLeft() } /** * An already completed Future is seeded with it's result at creation, is useful for when you are participating in * a Future-composition but you already have a value to contribute. */ -sealed class KeptPromise[T](suppliedValue: Either[Throwable, T])(implicit val dispatcher: MessageDispatcher) extends Promise[T] { +final class KeptPromise[T](suppliedValue: Either[Throwable, T])(implicit val dispatcher: MessageDispatcher) extends Promise[T] { val value = Some(suppliedValue) - def complete(value: Either[Throwable, T]): this.type = this - def onComplete(func: Future[T] ⇒ Unit): this.type = { - Future dispatchTask (() ⇒ func(this)) + def tryComplete(value: Either[Throwable, T]): Boolean = true + def onComplete(func: Either[Throwable, T] ⇒ Unit): this.type = { + val completedAs = value.get + Future dispatchTask (() ⇒ func(completedAs)) this } - def await(atMost: Duration): this.type = this - def await: this.type = this - def isExpired: Boolean = true - def timeout: Timeout = Timeout.zero - - final def onTimeout(func: Future[T] ⇒ Unit): this.type = this - final def orElse[A >: T](fallback: ⇒ A): Future[A] = this + def ready(atMost: Duration)(implicit permit: CanAwait): this.type = this + def result(atMost: Duration)(implicit permit: CanAwait): T = value.get match { + case Left(e) ⇒ throw e + case Right(r) ⇒ r + } } diff --git a/akka-actor/src/main/scala/akka/dispatch/PromiseStream.scala b/akka-actor/src/main/scala/akka/dispatch/PromiseStream.scala index 4356cbaff3..4ec0aaf300 100644 --- a/akka-actor/src/main/scala/akka/dispatch/PromiseStream.scala +++ b/akka-actor/src/main/scala/akka/dispatch/PromiseStream.scala @@ -166,7 +166,7 @@ class PromiseStream[A](implicit val dispatcher: MessageDispatcher, val timeout: } else enqueue(elem) } else { if (_pendOut.compareAndSet(po, po.tail)) { - po.head completeWithResult elem + po.head success elem if (!po.head.isCompleted) enqueue(elem) } else enqueue(elem) } @@ -183,11 +183,11 @@ class PromiseStream[A](implicit val dispatcher: MessageDispatcher, val timeout: if (eo eq null) dequeue() else { if (eo.nonEmpty) { - if (_elemOut.compareAndSet(eo, eo.tail)) new KeptPromise(Right(eo.head)) + if (_elemOut.compareAndSet(eo, eo.tail)) Promise.successful(eo.head) else dequeue() - } else dequeue(Promise[A](timeout)) + } else dequeue(Promise[A]) } - } else dequeue(Promise[A](timeout)) + } else dequeue(Promise[A]) @tailrec final def dequeue(promise: Promise[A]): Future[A] = _state.get match { @@ -227,7 +227,7 @@ class PromiseStream[A](implicit val dispatcher: MessageDispatcher, val timeout: } else dequeue(promise) } else { if (_elemOut.compareAndSet(eo, eo.tail)) { - promise completeWithResult eo.head + promise success eo.head } else dequeue(promise) } } diff --git a/akka-actor/src/main/scala/akka/dispatch/japi/Future.scala b/akka-actor/src/main/scala/akka/dispatch/japi/Future.scala index e923dd6c18..64852912fe 100644 --- a/akka-actor/src/main/scala/akka/dispatch/japi/Future.scala +++ b/akka-actor/src/main/scala/akka/dispatch/japi/Future.scala @@ -3,27 +3,52 @@ */ package akka.dispatch.japi -import akka.japi.{ Procedure, Function ⇒ JFunc, Option ⇒ JOption } import akka.actor.Timeout +import akka.japi.{ Procedure2, Procedure, Function ⇒ JFunc, Option ⇒ JOption } /* Java API */ trait Future[+T] { self: akka.dispatch.Future[T] ⇒ - private[japi] final def onTimeout[A >: T](proc: Procedure[akka.dispatch.Future[A]]): this.type = self.onTimeout(proc(_)) - private[japi] final def onResult[A >: T](proc: Procedure[A]): this.type = self.onResult({ case r ⇒ proc(r.asInstanceOf[A]) }: PartialFunction[T, Unit]) - private[japi] final def onException(proc: Procedure[Throwable]): this.type = self.onException({ case t: Throwable ⇒ proc(t) }: PartialFunction[Throwable, Unit]) - private[japi] final def onComplete[A >: T](proc: Procedure[akka.dispatch.Future[A]]): this.type = self.onComplete(proc(_)) - private[japi] final def map[A >: T, B](f: JFunc[A, B], timeout: Timeout): akka.dispatch.Future[B] = { - implicit val t = timeout - self.map(f(_)) - } - private[japi] final def flatMap[A >: T, B](f: JFunc[A, akka.dispatch.Future[B]], timeout: Timeout): akka.dispatch.Future[B] = { - implicit val t = timeout - self.flatMap(f(_)) - } + /** + * Asynchronously called when this Future gets a successful result + */ + private[japi] final def onSuccess[A >: T](proc: Procedure[A]): this.type = self.onSuccess({ case r ⇒ proc(r.asInstanceOf[A]) }: PartialFunction[T, Unit]) + + /** + * Asynchronously called when this Future gets a failed result + */ + private[japi] final def onFailure(proc: Procedure[Throwable]): this.type = self.onFailure({ case t: Throwable ⇒ proc(t) }: PartialFunction[Throwable, Unit]) + + /** + * Asynchronously called when this future is completed with either a failed or a successful result + * In case of a success, the first parameter (Throwable) will be null + * In case of a failure, the second parameter (T) will be null + * For no reason will both be null or neither be null + */ + private[japi] final def onComplete[A >: T](proc: Procedure2[Throwable, A]): this.type = self.onComplete(_.fold(t ⇒ proc(t, null.asInstanceOf[T]), r ⇒ proc(null, r))) + + /** + * Asynchronously applies the provided function to the (if any) successful result of this Future + * Any failure of this Future will be propagated to the Future returned by this method. + */ + private[japi] final def map[A >: T, B](f: JFunc[A, B]): akka.dispatch.Future[B] = self.map(f(_)) + + /** + * Asynchronously applies the provided function to the (if any) successful result of this Future and flattens it. + * Any failure of this Future will be propagated to the Future returned by this method. + */ + private[japi] final def flatMap[A >: T, B](f: JFunc[A, akka.dispatch.Future[B]]): akka.dispatch.Future[B] = self.flatMap(f(_)) + + /** + * Asynchronously applies the provided Procedure to the (if any) successful result of this Future + * Provided Procedure will not be called in case of no-result or in case of failed result + */ private[japi] final def foreach[A >: T](proc: Procedure[A]): Unit = self.foreach(proc(_)) - private[japi] final def filter[A >: T](p: JFunc[A, java.lang.Boolean], timeout: Timeout): akka.dispatch.Future[A] = { - implicit val t = timeout + + /** + * Returns a new Future whose successful result will be the successful result of this Future if that result conforms to the provided predicate + * Any failure of this Future will be propagated to the Future returned by this method. + */ + private[japi] final def filter[A >: T](p: JFunc[A, java.lang.Boolean]): akka.dispatch.Future[A] = self.filter((a: Any) ⇒ p(a.asInstanceOf[A])).asInstanceOf[akka.dispatch.Future[A]] - } } diff --git a/akka-actor/src/main/scala/akka/event/Logging.scala b/akka-actor/src/main/scala/akka/event/Logging.scala index bde3bd725a..016d977d40 100644 --- a/akka-actor/src/main/scala/akka/event/Logging.scala +++ b/akka-actor/src/main/scala/akka/event/Logging.scala @@ -11,10 +11,11 @@ import akka.config.ConfigurationException import akka.util.ReentrantGuard import akka.util.duration._ import akka.actor.Timeout -import akka.dispatch.FutureTimeoutException import java.util.concurrent.atomic.AtomicInteger import akka.actor.ActorRefProvider import scala.util.control.NoStackTrace +import java.util.concurrent.TimeoutException +import akka.dispatch.Await object LoggingBus { implicit def fromActorSystem(system: ActorSystem): LoggingBus = system.eventStream @@ -149,8 +150,8 @@ trait LoggingBus extends ActorEventBus { val name = "log" + Extension(system).id() + "-" + simpleName(clazz) val actor = system.systemActorOf(Props(clazz), name) implicit val timeout = Timeout(3 seconds) - val response = try actor ? InitializeLogger(this) get catch { - case _: FutureTimeoutException ⇒ + val response = try Await.result(actor ? InitializeLogger(this), timeout.duration) catch { + case _: TimeoutException ⇒ publish(Warning(simpleName(this), "Logger " + name + " did not respond within " + timeout + " to InitializeLogger(bus)")) } if (response != LoggerInitialized) diff --git a/akka-actor/src/main/scala/akka/util/cps/package.scala b/akka-actor/src/main/scala/akka/util/cps/package.scala index 6e88ff9cfe..7cbf60aaf2 100644 --- a/akka-actor/src/main/scala/akka/util/cps/package.scala +++ b/akka-actor/src/main/scala/akka/util/cps/package.scala @@ -42,7 +42,7 @@ package cps { if (test) Future(reify(block) flatMap (_ ⇒ reify(whileC(test)(block))) foreach c) else - Promise() completeWithResult (shiftUnitR[Unit, Future[Any]](()) foreach c) + Promise() success (shiftUnitR[Unit, Future[Any]](()) foreach c) } def repeatC[U](times: Int)(block: ⇒ U @cps[Future[Any]])(implicit dispatcher: MessageDispatcher, timeout: Timeout): Unit @cps[Future[Any]] = @@ -50,7 +50,7 @@ package cps { if (times > 0) Future(reify(block) flatMap (_ ⇒ reify(repeatC(times - 1)(block))) foreach c) else - Promise() completeWithResult (shiftUnitR[Unit, Future[Any]](()) foreach c) + Promise() success (shiftUnitR[Unit, Future[Any]](()) foreach c) } } diff --git a/akka-camel-typed/src/test/scala/akka/camel/TypedConsumerPublishRequestorTest.scala b/akka-camel-typed/src/test/scala/akka/camel/TypedConsumerPublishRequestorTest.scala index 358bedc070..322a0412c5 100644 --- a/akka-camel-typed/src/test/scala/akka/camel/TypedConsumerPublishRequestorTest.scala +++ b/akka-camel-typed/src/test/scala/akka/camel/TypedConsumerPublishRequestorTest.scala @@ -4,10 +4,11 @@ import java.util.concurrent.{ CountDownLatch, TimeUnit } import org.junit.{ Before, After, Test } import org.scalatest.junit.JUnitSuite - +import akka.util.duration._ import akka.actor._ import akka.actor.Actor._ import akka.camel.TypedCamelTestSupport.{ SetExpectedMessageCount ⇒ SetExpectedTestMessageCount, _ } +import akka.dispatch.Await class TypedConsumerPublishRequestorTest extends JUnitSuite { import TypedConsumerPublishRequestorTest._ @@ -39,10 +40,10 @@ class TypedConsumerPublishRequestorTest extends JUnitSuite { @Test def shouldReceiveOneConsumerMethodRegisteredEvent = { Actor.registry.addListener(requestor) - val latch = (publisher ? SetExpectedTestMessageCount(1)).as[CountDownLatch].get + val latch = Await.result((publisher ? SetExpectedTestMessageCount(1)).mapTo[CountDownLatch], 3 seconds) val obj = TypedActor.typedActorOf(classOf[SampleTypedSingleConsumer], classOf[SampleTypedSingleConsumerImpl], Props()) assert(latch.await(5000, TimeUnit.MILLISECONDS)) - val event = (publisher ? GetRetainedMessage).as[ConsumerMethodRegistered].get + val event = Await.result((publisher ? GetRetainedMessage).mapTo[ConsumerMethodRegistered], 3 seconds) assert(event.endpointUri === "direct:foo") assert(event.typedActor === obj) assert(event.methodName === "foo") @@ -50,21 +51,21 @@ class TypedConsumerPublishRequestorTest extends JUnitSuite { @Test def shouldReceiveOneConsumerMethodUnregisteredEvent = { - val latch = (publisher ? SetExpectedTestMessageCount(1)).as[CountDownLatch].get + val latch = Await.result((publisher ? SetExpectedTestMessageCount(1)).mapTo[CountDownLatch], 3 seconds) Actor.registry.addListener(requestor) val obj = TypedActor.typedActorOf(classOf[SampleTypedSingleConsumer], classOf[SampleTypedSingleConsumerImpl], Props()) assert(latch.await(5000, TimeUnit.MILLISECONDS)) - val ignorableEvent = (publisher ? GetRetainedMessage).as[ConsumerMethodRegistered].get + val ignorableEvent = Await.result((publisher ? GetRetainedMessage).mapTo[ConsumerMethodRegistered], 3 seconds) - val latch2 = (publisher ? SetExpectedTestMessageCount(1)).as[CountDownLatch].get + val latch2 = Await.result((publisher ? SetExpectedTestMessageCount(1)).mapTo[CountDownLatch], 3 seconds) TypedActor.stop(obj) assert(latch2.await(5000, TimeUnit.MILLISECONDS)) - val event = (publisher ? GetRetainedMessage).as[ConsumerMethodUnregistered].get + val event = Await.result((publisher ? GetRetainedMessage).mapTo[ConsumerMethodUnregistered], 3 seconds) assert(event.endpointUri === "direct:foo") assert(event.typedActor === obj) @@ -74,23 +75,23 @@ class TypedConsumerPublishRequestorTest extends JUnitSuite { @Test def shouldReceiveThreeConsumerMethodRegisteredEvents = { Actor.registry.addListener(requestor) - val latch = (publisher ? SetExpectedTestMessageCount(3)).as[CountDownLatch].get + val latch = Await.result((publisher ? SetExpectedTestMessageCount(3)).mapTo[CountDownLatch], 3 seconds) val obj = TypedActor.typedActorOf(classOf[SampleTypedConsumer], classOf[SampleTypedConsumerImpl], Props()) assert(latch.await(5000, TimeUnit.MILLISECONDS)) val request = GetRetainedMessages(_.isInstanceOf[ConsumerMethodRegistered]) - val events = (publisher ? request).as[List[ConsumerMethodRegistered]].get + val events = Await.result((publisher ? request).mapTo[List[ConsumerMethodRegistered]], 3 seconds) assert(events.map(_.method.getName).sortWith(_ < _) === List("m2", "m3", "m4")) } @Test def shouldReceiveThreeConsumerMethodUnregisteredEvents = { val obj = TypedActor.typedActorOf(classOf[SampleTypedConsumer], classOf[SampleTypedConsumerImpl], Props()) - val latch = (publisher ? SetExpectedTestMessageCount(3)).as[CountDownLatch].get + val latch = Await.result((publisher ? SetExpectedTestMessageCount(3)).mapTo[CountDownLatch], 3 seconds) Actor.registry.addListener(requestor) TypedActor.stop(obj) assert(latch.await(5000, TimeUnit.MILLISECONDS)) val request = GetRetainedMessages(_.isInstanceOf[ConsumerMethodUnregistered]) - val events = (publisher ? request).as[List[ConsumerMethodUnregistered]].get + val events = Await.result((publisher ? request).mapTo[List[ConsumerMethodUnregistered]], 3 seconds) assert(events.map(_.method.getName).sortWith(_ < _) === List("m2", "m3", "m4")) } } diff --git a/akka-camel/src/main/scala/akka/camel/CamelService.scala b/akka-camel/src/main/scala/akka/camel/CamelService.scala index eb3c8e4ae1..0b8a2aece0 100644 --- a/akka-camel/src/main/scala/akka/camel/CamelService.scala +++ b/akka-camel/src/main/scala/akka/camel/CamelService.scala @@ -14,6 +14,7 @@ import akka.japi.{ SideEffect, Option ⇒ JOption } import akka.util.Bootable import TypedCamelAccess._ +import akka.dispatch.Await /** * Publishes consumer actors at their Camel endpoints. Consumer actors are published asynchronously when @@ -164,7 +165,7 @@ trait CamelService extends Bootable { * activations that occurred in the past are not considered. */ private def expectEndpointActivationCount(count: Int): CountDownLatch = - (activationTracker ? SetExpectedActivationCount(count)).as[CountDownLatch].get + Await.result((activationTracker ? SetExpectedActivationCount(count)).mapTo[CountDownLatch], 3 seconds) /** * Sets an expectation on the number of upcoming endpoint de-activations and returns @@ -172,7 +173,7 @@ trait CamelService extends Bootable { * de-activations that occurred in the past are not considered. */ private def expectEndpointDeactivationCount(count: Int): CountDownLatch = - (activationTracker ? SetExpectedDeactivationCount(count)).as[CountDownLatch].get + Await.result((activationTracker ? SetExpectedDeactivationCount(count)).mapTo[CountDownLatch], 3 seconds) private[camel] def registerPublishRequestor: Unit = Actor.registry.addListener(publishRequestor) diff --git a/akka-camel/src/main/scala/akka/camel/component/ActorComponent.scala b/akka-camel/src/main/scala/akka/camel/component/ActorComponent.scala index c4ec7dcf31..c0d0281ab3 100644 --- a/akka-camel/src/main/scala/akka/camel/component/ActorComponent.scala +++ b/akka-camel/src/main/scala/akka/camel/component/ActorComponent.scala @@ -172,7 +172,7 @@ class ActorProducer(val ep: ActorEndpoint) extends DefaultProducer(ep) with Asyn private def sendSync(exchange: Exchange) = { val actor = target(exchange) - val result: Any = try { (actor ? requestFor(exchange)).as[Any] } catch { case e ⇒ Some(Failure(e)) } + val result: Any = try { Some(Await.result((actor ? requestFor(exchange), 5 seconds)) } catch { case e ⇒ Some(Failure(e)) } result match { case Some(Ack) ⇒ { /* no response message to set */ } @@ -294,7 +294,7 @@ private[akka] class AsyncCallbackAdapter(exchange: Exchange, callback: AsyncCall } def ?(message: Any)(implicit timeout: Timeout): Future[Any] = - new KeptPromise[Any](Left(new UnsupportedOperationException("Ask/? is not supported for %s".format(getClass.getName)))) + Promise.failed(new UnsupportedOperationException("Ask/? is not supported for %s".format(getClass.getName))) def restart(reason: Throwable): Unit = unsupported private def unsupported = throw new UnsupportedOperationException("Not supported for %s" format classOf[AsyncCallbackAdapter].getName) diff --git a/akka-camel/src/test/scala/akka/camel/ConsumerPublishRequestorTest.scala b/akka-camel/src/test/scala/akka/camel/ConsumerPublishRequestorTest.scala index f77cec4c0b..1c1fb273fb 100644 --- a/akka-camel/src/test/scala/akka/camel/ConsumerPublishRequestorTest.scala +++ b/akka-camel/src/test/scala/akka/camel/ConsumerPublishRequestorTest.scala @@ -8,6 +8,7 @@ import org.scalatest.junit.JUnitSuite import akka.actor._ import akka.actor.Actor._ import akka.camel.CamelTestSupport.{ SetExpectedMessageCount ⇒ SetExpectedTestMessageCount, _ } +import akka.dispatch.Await class ConsumerPublishRequestorTest extends JUnitSuite { import ConsumerPublishRequestorTest._ @@ -35,19 +36,19 @@ class ConsumerPublishRequestorTest extends JUnitSuite { @Test def shouldReceiveOneConsumerRegisteredEvent = { - val latch = (publisher ? SetExpectedTestMessageCount(1)).as[CountDownLatch].get + val latch = Await.result((publisher ? SetExpectedTestMessageCount(1)).mapTo[CountDownLatch], 5 seconds) requestor ! ActorRegistered(consumer.address, consumer) assert(latch.await(5000, TimeUnit.MILLISECONDS)) - assert((publisher ? GetRetainedMessage).get === + assert(Await.result(publisher ? GetRetainedMessage, 5 seconds) === ConsumerActorRegistered(consumer, consumer.underlyingActorInstance.asInstanceOf[Consumer])) } @Test def shouldReceiveOneConsumerUnregisteredEvent = { - val latch = (publisher ? SetExpectedTestMessageCount(1)).as[CountDownLatch].get + val latch = Await.result((publisher ? SetExpectedTestMessageCount(1)).mapTo[CountDownLatch], 5 seconds) requestor ! ActorUnregistered(consumer.address, consumer) assert(latch.await(5000, TimeUnit.MILLISECONDS)) - assert((publisher ? GetRetainedMessage).get === + assert(Await.result(publisher ? GetRetainedMessage, 5 seconds) === ConsumerActorUnregistered(consumer, consumer.underlyingActorInstance.asInstanceOf[Consumer])) } } diff --git a/akka-cluster/src/main/scala/akka/cluster/Cluster.scala b/akka-cluster/src/main/scala/akka/cluster/Cluster.scala index 5a3f115ef8..505474213f 100644 --- a/akka-cluster/src/main/scala/akka/cluster/Cluster.scala +++ b/akka-cluster/src/main/scala/akka/cluster/Cluster.scala @@ -33,7 +33,6 @@ import Status._ import DeploymentConfig._ import akka.event.EventHandler -import akka.dispatch.{ Dispatchers, Future, PinnedDispatcher } import akka.config.Config import akka.config.Config._ @@ -52,6 +51,7 @@ import RemoteSystemDaemonMessageType._ import com.eaio.uuid.UUID import com.google.protobuf.ByteString +import akka.dispatch.{Await, Dispatchers, Future, PinnedDispatcher} // FIXME add watch for each node that when the entry for the node is removed then the node shuts itself down @@ -1150,22 +1150,17 @@ class DefaultClusterNode private[akka] ( connection ! command } else { try { - (connection ? (command, remoteDaemonAckTimeout)).as[Status] match { - - case Some(Success(status)) ⇒ + Await.result(connection ? (command, remoteDaemonAckTimeout), 10 seconds).asInstanceOf[Status] match { + case Success(status) ⇒ EventHandler.debug(this, "Remote command sent to [%s] successfully received".format(status)) - - case Some(Failure(cause)) ⇒ + case Failure(cause) ⇒ EventHandler.error(cause, this, cause.toString) throw cause - - case None ⇒ - val error = new ClusterException( - "Remote command to [%s] timed out".format(connection.address)) - EventHandler.error(error, this, error.toString) - throw error } } catch { + case e: TimeoutException => + EventHandler.error(e, this, "Remote command to [%s] timed out".format(connection.address)) + throw e case e: Exception ⇒ EventHandler.error(e, this, "Could not send remote command to [%s] due to: %s".format(connection.address, e.toString)) throw e diff --git a/akka-cluster/src/main/scala/akka/cluster/TransactionLog.scala b/akka-cluster/src/main/scala/akka/cluster/TransactionLog.scala index 7d593437ae..8aa1727ca9 100644 --- a/akka-cluster/src/main/scala/akka/cluster/TransactionLog.scala +++ b/akka-cluster/src/main/scala/akka/cluster/TransactionLog.scala @@ -195,7 +195,7 @@ class TransactionLog private ( EventHandler.debug(this, "Reading entries [%s -> %s] for log [%s]".format(from, to, logId)) if (isAsync) { - val future = new DefaultPromise[Vector[Array[Byte]]](timeout) + val future = Promise[Vector[Array[Byte]]]() ledger.asyncReadEntries( from, to, new AsyncCallback.ReadCallback { @@ -203,8 +203,8 @@ class TransactionLog private ( val future = ctx.asInstanceOf[Promise[Vector[Array[Byte]]]] val entries = toByteArrays(enumeration) - if (returnCode == BKException.Code.OK) future.completeWithResult(entries) - else future.completeWithException(BKException.create(returnCode)) + if (returnCode == BKException.Code.OK) future.success(entries) + else future.failure(BKException.create(returnCode)) } }, future) @@ -457,7 +457,7 @@ object TransactionLog { } } - val future = new DefaultPromise[LedgerHandle](timeout) + val future = Promise[LedgerHandle]() if (isAsync) { bookieClient.asyncCreateLedger( ensembleSize, quorumSize, digestType, password, @@ -467,8 +467,8 @@ object TransactionLog { ledgerHandle: LedgerHandle, ctx: AnyRef) { val future = ctx.asInstanceOf[Promise[LedgerHandle]] - if (returnCode == BKException.Code.OK) future.completeWithResult(ledgerHandle) - else future.completeWithException(BKException.create(returnCode)) + if (returnCode == BKException.Code.OK) future.success(ledgerHandle) + else future.failure(BKException.create(returnCode)) } }, future) @@ -519,14 +519,14 @@ object TransactionLog { val ledger = try { if (isAsync) { - val future = new DefaultPromise[LedgerHandle](timeout) + val future = Promise[LedgerHandle]() bookieClient.asyncOpenLedger( logId, digestType, password, new AsyncCallback.OpenCallback { def openComplete(returnCode: Int, ledgerHandle: LedgerHandle, ctx: AnyRef) { val future = ctx.asInstanceOf[Promise[LedgerHandle]] - if (returnCode == BKException.Code.OK) future.completeWithResult(ledgerHandle) - else future.completeWithException(BKException.create(returnCode)) + if (returnCode == BKException.Code.OK) future.success(ledgerHandle) + else future.failure(BKException.create(returnCode)) } }, future) @@ -542,10 +542,10 @@ object TransactionLog { } private[akka] def await[T](future: Promise[T]): T = { - future.await - if (future.result.isDefined) future.result.get - else if (future.exception.isDefined) handleError(future.exception.get) - else handleError(new ReplicationException("No result from async read of entries for transaction log")) + future.await.value.get match { + case Right(result) => result + case Left(throwable) => handleError(throwable) + } } private[akka] def handleError(e: Throwable): Nothing = { diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/metrics/local/LocalMetricsMultiJvmSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/metrics/local/LocalMetricsMultiJvmSpec.scala index 456fd4f65a..50b7741758 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/metrics/local/LocalMetricsMultiJvmSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/metrics/local/LocalMetricsMultiJvmSpec.scala @@ -73,7 +73,7 @@ class LocalMetricsMultiJvmNode1 extends MasterClusterTestNode { } "allow to track JVM state and bind handles through MetricsAlterationMonitors" in { - val monitorReponse = new DefaultPromise[String] + val monitorReponse = Promise[String]() node.metricsManager.addMonitor(new LocalMetricsAlterationMonitor { @@ -81,11 +81,11 @@ class LocalMetricsMultiJvmNode1 extends MasterClusterTestNode { def reactsOn(metrics: NodeMetrics) = metrics.usedHeapMemory > 1 - def react(metrics: NodeMetrics) = monitorReponse.completeWithResult("Too much memory is used!") + def react(metrics: NodeMetrics) = monitorReponse.success("Too much memory is used!") }) - monitorReponse.get must be("Too much memory is used!") + Await.result(monitorReponse, 5 seconds) must be("Too much memory is used!") } diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/direct/failover/DirectRoutingFailoverMultiJvmSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/direct/failover/DirectRoutingFailoverMultiJvmSpec.scala index 260a365019..6bc1653836 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/direct/failover/DirectRoutingFailoverMultiJvmSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/direct/failover/DirectRoutingFailoverMultiJvmSpec.scala @@ -11,6 +11,7 @@ import akka.testkit.{ EventFilter, TestEvent } import java.net.ConnectException import java.nio.channels.NotYetConnectedException import akka.cluster.LocalCluster +import akka.dispatch.Await object DirectRoutingFailoverMultiJvmSpec { @@ -48,7 +49,7 @@ class DirectRoutingFailoverMultiJvmNode1 extends MasterClusterTestNode { } LocalCluster.barrier("verify-actor", NrOfNodes) { - (actor ? "identify").get must equal("node2") + Await.result(actor ? "identify", timeout.duration) must equal("node2") } val timer = Timer(30.seconds, true) diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/random/failover/RandomFailoverMultiJvmSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/random/failover/RandomFailoverMultiJvmSpec.scala index 2842c55a97..cbdc42dbe9 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/random/failover/RandomFailoverMultiJvmSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/random/failover/RandomFailoverMultiJvmSpec.scala @@ -11,6 +11,7 @@ import java.util.{ Collections, Set ⇒ JSet } import java.net.ConnectException import java.nio.channels.NotYetConnectedException import akka.cluster.LocalCluster._ +import akka.dispatch.Await object RandomFailoverMultiJvmSpec { @@ -91,7 +92,7 @@ class RandomFailoverMultiJvmNode1 extends MasterClusterTestNode { def identifyConnections(actor: ActorRef): JSet[String] = { val set = new java.util.HashSet[String] for (i ← 0 until 100) { // we should get hits from both nodes in 100 attempts, if not then not very random - val value = (actor ? "identify").get.asInstanceOf[String] + val value = Await.result(actor ? "identify", timeout.duration).asInstanceOf[String] set.add(value) } set diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/random/replicationfactor_3/Random3ReplicasMultiJvmSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/random/replicationfactor_3/Random3ReplicasMultiJvmSpec.scala index edb000b566..cfe98d5680 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/random/replicationfactor_3/Random3ReplicasMultiJvmSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/random/replicationfactor_3/Random3ReplicasMultiJvmSpec.scala @@ -9,6 +9,7 @@ import akka.actor._ import akka.config.Config import Cluster._ import akka.cluster.LocalCluster._ +import akka.dispatch.Await /** * When a MultiJvmNode is started, will it automatically be part of the cluster (so will it automatically be eligible @@ -78,7 +79,7 @@ class Random3ReplicasMultiJvmNode2 extends ClusterTestNode { } for (i ← 0 until 1000) { - count((hello ? "Hello").as[String].getOrElse(fail("Should have recieved reply from a node"))) + count(Await.result((hello ? "Hello").mapTo[String], 10 seconds)) } val repliesNode1 = replies("World from node [node1]") diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/roundrobin/failover/RoundRobinFailoverMultiJvmSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/roundrobin/failover/RoundRobinFailoverMultiJvmSpec.scala index 63cd6c6313..1b97ef1075 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/roundrobin/failover/RoundRobinFailoverMultiJvmSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/roundrobin/failover/RoundRobinFailoverMultiJvmSpec.scala @@ -12,6 +12,7 @@ import java.net.ConnectException import java.nio.channels.NotYetConnectedException import java.lang.Thread import akka.cluster.LocalCluster._ +import akka.dispatch.Await object RoundRobinFailoverMultiJvmSpec { @@ -94,7 +95,7 @@ class RoundRobinFailoverMultiJvmNode1 extends MasterClusterTestNode { def identifyConnections(actor: ActorRef): JSet[String] = { val set = new java.util.HashSet[String] for (i ← 0 until 100) { - val value = (actor ? "identify").get.asInstanceOf[String] + val value = Await.result(actor ? "identify", timeout.duration).asInstanceOf[String] set.add(value) } set diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/roundrobin/replicationfactor_2/RoundRobin2ReplicasMultiJvmSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/roundrobin/replicationfactor_2/RoundRobin2ReplicasMultiJvmSpec.scala index a99dbbbae9..1803ec2c83 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/roundrobin/replicationfactor_2/RoundRobin2ReplicasMultiJvmSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/roundrobin/replicationfactor_2/RoundRobin2ReplicasMultiJvmSpec.scala @@ -20,6 +20,7 @@ import akka.cluster.LocalCluster._ import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.ConcurrentHashMap +import akka.dispatch.Await /** * When a MultiJvmNode is started, will it automatically be part of the cluster (so will it automatically be eligible @@ -107,14 +108,8 @@ class RoundRobin2ReplicasMultiJvmNode2 extends ClusterTestNode { implicit val timeout = Timeout(Duration(20, "seconds")) - count((hello ? "Hello").as[String].getOrElse(fail("Should have recieved reply from node1"))) - count((hello ? "Hello").as[String].getOrElse(fail("Should have recieved reply from node2"))) - count((hello ? "Hello").as[String].getOrElse(fail("Should have recieved reply from node1"))) - count((hello ? "Hello").as[String].getOrElse(fail("Should have recieved reply from node2"))) - count((hello ? "Hello").as[String].getOrElse(fail("Should have recieved reply from node1"))) - count((hello ? "Hello").as[String].getOrElse(fail("Should have recieved reply from node2"))) - count((hello ? "Hello").as[String].getOrElse(fail("Should have recieved reply from node1"))) - count((hello ? "Hello").as[String].getOrElse(fail("Should have recieved reply from node2"))) + for(i <- 1 to 8) + count(Await.result((hello ? "Hello").mapTo[String], timeout.duration)) replies.get("World from node [node1]").get must equal(4) replies.get("World from node [node2]").get must equal(4) diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/scattergather/failover/ScatterGatherFailoverMultiJvmSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/scattergather/failover/ScatterGatherFailoverMultiJvmSpec.scala index 90f9e0aa56..e8cc4f7d68 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/scattergather/failover/ScatterGatherFailoverMultiJvmSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/routing/scattergather/failover/ScatterGatherFailoverMultiJvmSpec.scala @@ -11,6 +11,7 @@ import java.nio.channels.NotYetConnectedException import java.lang.Thread import akka.routing.Routing.Broadcast import akka.cluster.LocalCluster._ +import akka.dispatch.Await object ScatterGatherFailoverMultiJvmSpec { @@ -84,7 +85,7 @@ class ScatterGatherFailoverMultiJvmNode1 extends MasterClusterTestNode { def identifyConnections(actor: ActorRef): JSet[String] = { val set = new java.util.HashSet[String] for (i ← 0 until NrOfNodes * 2) { - val value = (actor ? "foo").get.asInstanceOf[String] + val value = Await.result(actor ? "foo", timeout.duration).asInstanceOf[String] set.add(value) } set diff --git a/akka-cluster/src/test/scala/akka/cluster/sample/ComputeGridSample.scala b/akka-cluster/src/test/scala/akka/cluster/sample/ComputeGridSample.scala index 7a3a9ca606..cb57df1718 100644 --- a/akka-cluster/src/test/scala/akka/cluster/sample/ComputeGridSample.scala +++ b/akka-cluster/src/test/scala/akka/cluster/sample/ComputeGridSample.scala @@ -46,7 +46,7 @@ object ComputeGridSample { val fun = () ⇒ "AKKA ROCKS" val futures = local send (fun, 2) // send and invoke function on to two cluster nodes and get result - val result = Futures.fold("")(futures)(_ + " - " + _).await.resultOrException + val result = Await.sync(Futures.fold("")(futures)(_ + " - " + _), timeout) println("===================>>> Cluster says [" + result + "]") local.stop @@ -80,8 +80,8 @@ object ComputeGridSample { val future2 = local send (fun, 2, 1) head // send and invoke function on one cluster node and get result // grab the result from the first one that returns - val result = Futures.firstCompletedOf(List(future1, future2)).await.resultOrException - println("===================>>> Cluster says [" + result.get + "]") + val result = Await.sync(Futures.firstCompletedOf(List(future1, future2)), timeout) + println("===================>>> Cluster says [" + result + "]") local.stop remote1.stop diff --git a/akka-docs/.history b/akka-docs/.history new file mode 100644 index 0000000000..a3abe50906 --- /dev/null +++ b/akka-docs/.history @@ -0,0 +1 @@ +exit diff --git a/akka-docs/general/jmm.rst b/akka-docs/general/jmm.rst index ecb6dad6f1..23871449ef 100644 --- a/akka-docs/general/jmm.rst +++ b/akka-docs/general/jmm.rst @@ -81,7 +81,7 @@ Since Akka runs on the JVM there are still some rules to be followed. // Very bad, shared mutable state, // will break your application in weird ways Future { state = NewState } - anotherActor ? message onResult { r => state = r } + anotherActor ? message onSuccess { r => state = r } // Very bad, "sender" changes for every message, // shared mutable state bug diff --git a/akka-docs/intro/getting-started-first-java.rst b/akka-docs/intro/getting-started-first-java.rst index 6d429b160d..73969c1128 100644 --- a/akka-docs/intro/getting-started-first-java.rst +++ b/akka-docs/intro/getting-started-first-java.rst @@ -360,7 +360,7 @@ One thing to note is that we used two different versions of the ``actorOf`` meth The actor's life-cycle is: -- Created & Started -- ``Actor.actorOf(Props[MyActor]`` -- can receive messages +- Created & Started -- ``Actor.actorOf(Props[MyActor])`` -- can receive messages - Stopped -- ``actorRef.stop()`` -- can **not** receive messages Once the actor has been stopped it is dead and can not be started again. diff --git a/akka-docs/java/code/akka/docs/actor/UntypedActorTestBase.java b/akka-docs/java/code/akka/docs/actor/UntypedActorTestBase.java index 922f4ed0e6..6039286598 100644 --- a/akka-docs/java/code/akka/docs/actor/UntypedActorTestBase.java +++ b/akka-docs/java/code/akka/docs/actor/UntypedActorTestBase.java @@ -9,6 +9,8 @@ import akka.actor.Props; //#import-future import akka.dispatch.Future; +import akka.dispatch.Await; +import akka.util.Duration; //#import-future @@ -28,8 +30,9 @@ import akka.actor.UntypedActorFactory; import akka.dispatch.MessageDispatcher; import org.junit.Test; - import scala.Option; +import java.lang.Object; +import java.util.concurrent.TimeUnit; import static org.junit.Assert.*; @@ -93,17 +96,8 @@ public class UntypedActorTestBase { })); //#using-ask - Future future = myActor.ask("Hello", 1000); - future.await(); - if (future.isCompleted()) { - Option resultOption = future.result(); - if (resultOption.isDefined()) { - Object result = resultOption.get(); - // ... - } else { - //... whatever - } - } + Future future = myActor.ask("Hello", 1000); + Object result = Await.result(future, Duration.create(1, TimeUnit.SECONDS)); //#using-ask system.shutdown(); } diff --git a/akka-docs/scala/actors.rst b/akka-docs/scala/actors.rst index 618d2618c9..2d11ea4894 100644 --- a/akka-docs/scala/actors.rst +++ b/akka-docs/scala/actors.rst @@ -312,7 +312,8 @@ Gives you a way to avoid blocking. .. warning:: - When using future callbacks, inside actors you need to carefully avoid closing over + When using future callbacks, such as ``onComplete``, ``onSuccess``, and ``onFailure``, + inside actors you need to carefully avoid closing over the containing actor’s reference, 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 diff --git a/akka-docs/scala/code/ActorDocSpec.scala b/akka-docs/scala/code/ActorDocSpec.scala index a08aa93593..68733d2009 100644 --- a/akka-docs/scala/code/ActorDocSpec.scala +++ b/akka-docs/scala/code/ActorDocSpec.scala @@ -4,6 +4,8 @@ package akka.docs.actor import akka.actor.Actor import akka.actor.Props import akka.event.Logging +import akka.dispatch.Future + //#imports1 //#imports2 @@ -207,11 +209,9 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) { val myActor = system.actorOf(Props(new MyActor)) implicit val timeout = system.settings.ActorTimeout val future = myActor ? "hello" - future.as[String] match { - case Some(answer) ⇒ //... - case None ⇒ //... - } - val result: Option[Int] = for (x ← (myActor ? 3).as[Int]) yield { 2 * x } + for (x ← future) println(x) //Prints "hello" + + val result: Future[Int] = for (x ← (myActor ? 3).mapTo[Int]) yield { 2 * x } //#using-ask system.stop(myActor) diff --git a/akka-durable-mailboxes/akka-mongo-mailbox/src/main/scala/akka/actor/mailbox/MongoBasedMailbox.scala b/akka-durable-mailboxes/akka-mongo-mailbox/src/main/scala/akka/actor/mailbox/MongoBasedMailbox.scala index d010a1ef6a..6e1c28219d 100644 --- a/akka-durable-mailboxes/akka-mongo-mailbox/src/main/scala/akka/actor/mailbox/MongoBasedMailbox.scala +++ b/akka-durable-mailboxes/akka-mongo-mailbox/src/main/scala/akka/actor/mailbox/MongoBasedMailbox.scala @@ -8,10 +8,10 @@ import com.mongodb.async._ import com.mongodb.async.futures.RequestFutures import org.bson.collection._ import akka.actor.ActorCell -import akka.dispatch.Envelope import akka.event.Logging -import akka.dispatch.DefaultPromise import akka.actor.ActorRef +import akka.dispatch.{ Await, Promise, Envelope, DefaultPromise } +import java.util.concurrent.TimeoutException class MongoBasedMailboxException(message: String) extends AkkaException(message) @@ -43,15 +43,14 @@ class MongoBasedMailbox(val owner: ActorCell) extends DurableMailbox(owner) { /* TODO - Test if a BSON serializer is registered for the message and only if not, use toByteString? */ val durableMessage = MongoDurableMessage(ownerPathString, envelope.message, envelope.sender) // todo - do we need to filter the actor name at all for safe collection naming? - val result = new DefaultPromise[Boolean](settings.WriteTimeout)(dispatcher) + val result = Promise[Boolean]()(dispatcher) mongo.insert(durableMessage, false)(RequestFutures.write { wr: Either[Throwable, (Option[AnyRef], WriteResult)] ⇒ wr match { - case Right((oid, wr)) ⇒ result.completeWithResult(true) - case Left(t) ⇒ result.completeWithException(t) + case Right((oid, wr)) ⇒ result.success(true) + case Left(t) ⇒ result.failure(t) } }) - - result.as[Boolean].orNull + Await.ready(result, settings.WriteTimeout) } def dequeue(): Envelope = withErrorHandling { @@ -62,29 +61,27 @@ class MongoBasedMailbox(val owner: ActorCell) extends DurableMailbox(owner) { * TODO - Should we have a specific query in place? Which way do we sort? * TODO - Error handling version! */ - val envelopePromise = new DefaultPromise[Envelope](settings.ReadTimeout)(dispatcher) + val envelopePromise = Promise[Envelope]()(dispatcher) mongo.findAndRemove(Document.empty) { doc: Option[MongoDurableMessage] ⇒ doc match { case Some(msg) ⇒ { log.debug("DEQUEUING message in mongo-based mailbox [{}]", msg) - envelopePromise.completeWithResult(msg.envelope()) + envelopePromise.success(msg.envelope()) log.debug("DEQUEUING messageInvocation in mongo-based mailbox [{}]", envelopePromise) } case None ⇒ - { - log.info("No matching document found. Not an error, just an empty queue.") - envelopePromise.completeWithResult(null) - } + log.info("No matching document found. Not an error, just an empty queue.") + envelopePromise.success(null) () } } - envelopePromise.as[Envelope].orNull + try { Await.result(envelopePromise, settings.ReadTimeout) } catch { case _: TimeoutException ⇒ null } } def numberOfMessages: Int = { - val count = new DefaultPromise[Int](settings.ReadTimeout)(dispatcher) - mongo.count()(count.completeWithResult) - count.as[Int].getOrElse(-1) + val count = Promise[Int]()(dispatcher) + mongo.count()(count.success) + try { Await.result(count, settings.ReadTimeout).asInstanceOf[Int] } catch { case _: Exception ⇒ -1 } } //TODO review find other solution, this will be very expensive diff --git a/akka-remote/src/main/scala/akka/remote/Gossiper.scala b/akka-remote/src/main/scala/akka/remote/Gossiper.scala index 0b8044f9c4..121ead58bc 100644 --- a/akka-remote/src/main/scala/akka/remote/Gossiper.scala +++ b/akka-remote/src/main/scala/akka/remote/Gossiper.scala @@ -22,6 +22,8 @@ import scala.collection.immutable.Map import scala.annotation.tailrec import com.google.protobuf.ByteString +import java.util.concurrent.TimeoutException +import akka.dispatch.Await /** * Interface for node membership change listener. @@ -250,18 +252,13 @@ class Gossiper(remote: Remote, system: ActorSystemImpl) { throw new IllegalStateException("Connection for [" + peer + "] is not set up")) try { - (connection ? (toRemoteMessage(newGossip), remoteSettings.RemoteSystemDaemonAckTimeout)).as[Status] match { - case Some(Success(receiver)) ⇒ - log.debug("Gossip sent to [{}] was successfully received", receiver) - - case Some(Failure(cause)) ⇒ - log.error(cause, cause.toString) - - case None ⇒ - val error = new RemoteException("Gossip to [%s] timed out".format(connection.path)) - log.error(error, error.toString) + val t = remoteSettings.RemoteSystemDaemonAckTimeout + Await.result(connection ? (toRemoteMessage(newGossip), t), t) match { + case Success(receiver) ⇒ log.debug("Gossip sent to [{}] was successfully received", receiver) + case Failure(cause) ⇒ log.error(cause, cause.toString) } } catch { + case e: TimeoutException ⇒ log.error(e, "Gossip to [%s] timed out".format(connection.path)) case e: Exception ⇒ log.error(e, "Could not gossip to [{}] due to: {}", connection.path, e.toString) } diff --git a/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala b/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala index 92582c4168..5a8afd5a5b 100644 --- a/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala +++ b/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala @@ -12,9 +12,9 @@ import akka.remote.RemoteProtocol._ import akka.remote.RemoteProtocol.RemoteSystemDaemonMessageType._ import com.google.protobuf.ByteString import akka.event.EventStream -import akka.serialization.SerializationExtension -import akka.serialization.Serialization +import akka.dispatch.Promise import akka.config.ConfigurationException +import java.util.concurrent.{ TimeoutException } /** * Remote ActorRefProvider. Starts up actor on remote node and creates a RemoteActorRef representing it. @@ -199,7 +199,7 @@ private[akka] class RemoteActorRef private[akka] ( a.result case None ⇒ this.!(message)(null) - new DefaultPromise[Any](0)(provider.dispatcher) + Promise[Any]()(provider.dispatcher) } } diff --git a/akka-remote/src/multi-jvm/scala/akka/remote/direct_routed/DirectRoutedRemoteActorMultiJvmSpec.scala b/akka-remote/src/multi-jvm/scala/akka/remote/direct_routed/DirectRoutedRemoteActorMultiJvmSpec.scala index 0a6098f27d..d789069522 100644 --- a/akka-remote/src/multi-jvm/scala/akka/remote/direct_routed/DirectRoutedRemoteActorMultiJvmSpec.scala +++ b/akka-remote/src/multi-jvm/scala/akka/remote/direct_routed/DirectRoutedRemoteActorMultiJvmSpec.scala @@ -4,6 +4,7 @@ import akka.remote._ import akka.routing._ import akka.actor.{ Actor, Props } import akka.testkit._ +import akka.dispatch.Await object DirectRoutedRemoteActorMultiJvmSpec { val NrOfNodes = 2 @@ -42,8 +43,7 @@ class DirectRoutedRemoteActorMultiJvmNode2 extends AkkaRemoteSpec with DefaultTi val actor = system.actorOf(Props[SomeActor], "service-hello") actor.isInstanceOf[RemoteActorRef] must be(true) - val result = (actor ? "identify").get - result must equal("node1") + Await.result(actor ? "identify", timeout.duration) must equal("node1") barrier("done") } diff --git a/akka-remote/src/multi-jvm/scala/akka/remote/new_remote_actor/NewRemoteActorMultiJvmSpec.scala b/akka-remote/src/multi-jvm/scala/akka/remote/new_remote_actor/NewRemoteActorMultiJvmSpec.scala index 1e8c45112e..ae34fbd440 100644 --- a/akka-remote/src/multi-jvm/scala/akka/remote/new_remote_actor/NewRemoteActorMultiJvmSpec.scala +++ b/akka-remote/src/multi-jvm/scala/akka/remote/new_remote_actor/NewRemoteActorMultiJvmSpec.scala @@ -3,6 +3,7 @@ package akka.remote.new_remote_actor import akka.actor.{ Actor, Props } import akka.remote._ import akka.testkit.DefaultTimeout +import akka.dispatch.Await object NewRemoteActorMultiJvmSpec { val NrOfNodes = 2 @@ -40,8 +41,7 @@ class NewRemoteActorMultiJvmNode2 extends AkkaRemoteSpec with DefaultTimeout { barrier("start") val actor = system.actorOf(Props[SomeActor], "service-hello") - val result = (actor ? "identify").get - result must equal("node1") + Await.result(actor ? "identify", timeout.duration) must equal("node1") barrier("done") } diff --git a/akka-remote/src/multi-jvm/scala/akka/remote/random_routed/RandomRoutedRemoteActorMultiJvmSpec.scala b/akka-remote/src/multi-jvm/scala/akka/remote/random_routed/RandomRoutedRemoteActorMultiJvmSpec.scala index 87a3177b3b..9d20907089 100644 --- a/akka-remote/src/multi-jvm/scala/akka/remote/random_routed/RandomRoutedRemoteActorMultiJvmSpec.scala +++ b/akka-remote/src/multi-jvm/scala/akka/remote/random_routed/RandomRoutedRemoteActorMultiJvmSpec.scala @@ -4,6 +4,7 @@ import akka.actor.{ Actor, Props } import akka.remote._ import akka.routing._ import akka.testkit.DefaultTimeout +import akka.dispatch.Await object RandomRoutedRemoteActorMultiJvmSpec { val NrOfNodes = 4 @@ -74,7 +75,7 @@ class RandomRoutedRemoteActorMultiJvmNode4 extends AkkaRemoteSpec with DefaultTi for (i ← 0 until iterationCount) { for (k ← 0 until connectionCount) { - val nodeName = (actor ? "hit").as[String].getOrElse(fail("No id returned by actor")) + val nodeName = Await.result(actor ? "hit", timeout.duration).toString replies = replies + (nodeName -> (replies(nodeName) + 1)) } } diff --git a/akka-remote/src/multi-jvm/scala/akka/remote/round_robin_routed/RoundRobinRoutedRemoteActorMultiJvmSpec.scala b/akka-remote/src/multi-jvm/scala/akka/remote/round_robin_routed/RoundRobinRoutedRemoteActorMultiJvmSpec.scala index 29e57d4209..0caf841953 100644 --- a/akka-remote/src/multi-jvm/scala/akka/remote/round_robin_routed/RoundRobinRoutedRemoteActorMultiJvmSpec.scala +++ b/akka-remote/src/multi-jvm/scala/akka/remote/round_robin_routed/RoundRobinRoutedRemoteActorMultiJvmSpec.scala @@ -4,6 +4,7 @@ import akka.actor.{ Actor, Props } import akka.remote._ import akka.routing._ import akka.testkit.DefaultTimeout +import akka.dispatch.Await object RoundRobinRoutedRemoteActorMultiJvmSpec { val NrOfNodes = 4 @@ -74,7 +75,7 @@ class RoundRobinRoutedRemoteActorMultiJvmNode4 extends AkkaRemoteSpec with Defau for (i ← 0 until iterationCount) { for (k ← 0 until connectionCount) { - val nodeName = (actor ? "hit").as[String].getOrElse(fail("No id returned by actor")) + val nodeName = Await.result(actor ? "hit", timeout.duration).toString replies = replies + (nodeName -> (replies(nodeName) + 1)) } } diff --git a/akka-remote/src/test/scala/akka/remote/RemoteCommunicationSpec.scala b/akka-remote/src/test/scala/akka/remote/RemoteCommunicationSpec.scala index d7827134bc..dd62ae48e2 100644 --- a/akka-remote/src/test/scala/akka/remote/RemoteCommunicationSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/RemoteCommunicationSpec.scala @@ -6,6 +6,7 @@ package akka.remote import akka.testkit._ import akka.actor._ import com.typesafe.config._ +import akka.dispatch.Await object RemoteCommunicationSpec { class Echo extends Actor { @@ -80,7 +81,7 @@ akka { } "support ask" in { - (here ? "ping").get match { + Await.result(here ? "ping", timeout.duration) match { case ("pong", s: AskActorRef) ⇒ // good case m ⇒ fail(m + " was not (pong, AskActorRef)") } @@ -124,8 +125,8 @@ akka { myref ! 43 expectMsg(43) lastSender must be theSameInstanceAs remref - (l ? "child/..").as[ActorRef].get must be theSameInstanceAs l - (system.actorFor(system / "looker" / "child") ? "..").as[ActorRef].get must be theSameInstanceAs l + Await.result(l ? "child/..", timeout.duration).asInstanceOf[AnyRef] must be theSameInstanceAs l + Await.result(system.actorFor(system / "looker" / "child") ? "..", timeout.duration).asInstanceOf[AnyRef] must be theSameInstanceAs l } } diff --git a/akka-spring/src/test/scala/TypedActorSpringFeatureTest.scala b/akka-spring/src/test/scala/TypedActorSpringFeatureTest.scala index f2cc5a288d..1fa4874408 100644 --- a/akka-spring/src/test/scala/TypedActorSpringFeatureTest.scala +++ b/akka-spring/src/test/scala/TypedActorSpringFeatureTest.scala @@ -4,7 +4,6 @@ package akka.spring import foo.{ PingActor, IMyPojo, MyPojo } -import akka.dispatch.FutureTimeoutException import org.scalatest.matchers.ShouldMatchers import org.scalatest.junit.JUnitRunner import org.junit.runner.RunWith @@ -14,10 +13,10 @@ import org.springframework.context.ApplicationContext import org.springframework.context.support.ClassPathXmlApplicationContext import org.springframework.core.io.{ ClassPathResource, Resource } import org.scalatest.{ BeforeAndAfterAll, FeatureSpec } -import java.util.concurrent.CountDownLatch import akka.remote.netty.NettyRemoteSupport import akka.actor._ import akka.actor.Actor._ +import java.util.concurrent.{TimeoutException, CountDownLatch} object RemoteTypedActorLog { import java.util.concurrent.{ LinkedBlockingQueue, TimeUnit, BlockingQueue } @@ -89,9 +88,9 @@ class TypedActorSpringFeatureTest extends FeatureSpec with ShouldMatchers with B assert(MyPojo.lastOneWayMessage === "hello 1") } - scenario("FutureTimeoutException when timed out") { + scenario("TimeoutException when timed out") { val myPojo = getTypedActorFromContext("/typed-actor-config.xml", "simple-typed-actor") - evaluating { myPojo.longRunning() } should produce[FutureTimeoutException] + evaluating { myPojo.longRunning() } should produce[TimeoutException] } scenario("typed-actor with timeout") { diff --git a/akka-stm/src/main/scala/akka/agent/Agent.scala b/akka-stm/src/main/scala/akka/agent/Agent.scala index 3fd6c02f7d..25849c31f3 100644 --- a/akka-stm/src/main/scala/akka/agent/Agent.scala +++ b/akka-stm/src/main/scala/akka/agent/Agent.scala @@ -8,7 +8,7 @@ import akka.actor.ActorSystem import akka.actor._ import akka.stm._ import akka.japi.{ Function ⇒ JFunc, Procedure ⇒ JProc } -import akka.dispatch.{ PinnedDispatcher, UnboundedMailbox, DefaultPromise, Dispatchers, Future } +import akka.dispatch._ /** * Used internally to send functions. @@ -123,7 +123,7 @@ class Agent[T](initialValue: T, system: ActorSystem) { def alter(f: T ⇒ T)(timeout: Timeout): Future[T] = { def dispatch = updater.?(Update(f), timeout).asInstanceOf[Future[T]] if (Stm.activeTransaction) { - val result = new DefaultPromise[T](timeout)(system.dispatcher) + val result = Promise[T]()(system.dispatcher) get //Join xa deferred { result completeWith dispatch } //Attach deferred-block to current transaction result @@ -134,7 +134,7 @@ class Agent[T](initialValue: T, system: ActorSystem) { * Dispatch a new value for the internal state. Behaves the same * as sending a function (x => newValue). */ - def send(newValue: T): Unit = send(x ⇒ newValue) + def send(newValue: T): Unit = send(_ ⇒ newValue) /** * Dispatch a new value for the internal state. Behaves the same @@ -166,7 +166,7 @@ class Agent[T](initialValue: T, system: ActorSystem) { * still be executed in order. */ def alterOff(f: T ⇒ T)(timeout: Timeout): Future[T] = { - val result = new DefaultPromise[T](timeout)(system.dispatcher) + val result = Promise[T]()(system.dispatcher) send((value: T) ⇒ { suspend() val pinnedDispatcher = new PinnedDispatcher(system.dispatcherFactory.prerequisites, null, "agent-alter-off", UnboundedMailbox(), system.settings.ActorTimeout.duration) @@ -186,7 +186,7 @@ class Agent[T](initialValue: T, system: ActorSystem) { /** * Gets this agent's value after all currently queued updates have completed. */ - def await(implicit timeout: Timeout): T = future.await.result.get + def await(implicit timeout: Timeout): T = Await.result(future, timeout.duration) /** * Map this agent to a new agent, applying the function to the internal state. diff --git a/akka-stm/src/test/java/akka/transactor/example/UntypedCoordinatedExample.java b/akka-stm/src/test/java/akka/transactor/example/UntypedCoordinatedExample.java index 4e72bea237..d5b236694f 100644 --- a/akka-stm/src/test/java/akka/transactor/example/UntypedCoordinatedExample.java +++ b/akka-stm/src/test/java/akka/transactor/example/UntypedCoordinatedExample.java @@ -3,46 +3,37 @@ package akka.transactor.example; import akka.actor.ActorSystem; import akka.actor.ActorRef; import akka.actor.Props; +import akka.dispatch.Await; import akka.dispatch.Future; import akka.testkit.AkkaSpec; import akka.transactor.Coordinated; +import akka.util.Duration; +import java.util.concurrent.TimeUnit; + public class UntypedCoordinatedExample { public static void main(String[] args) throws InterruptedException { - ActorSystem application = ActorSystem.create("UntypedCoordinatedExample", AkkaSpec.testConf()); + ActorSystem app = ActorSystem.create("UntypedCoordinatedExample", AkkaSpec.testConf()); - ActorRef counter1 = application.actorOf(new Props().withCreator(UntypedCoordinatedCounter.class)); - ActorRef counter2 = application.actorOf(new Props().withCreator(UntypedCoordinatedCounter.class)); + ActorRef counter1 = app.actorOf(new Props().withCreator(UntypedCoordinatedCounter.class)); + ActorRef counter2 = app.actorOf(new Props().withCreator(UntypedCoordinatedCounter.class)); counter1.tell(new Coordinated(new Increment(counter2))); Thread.sleep(3000); long timeout = 5000; + Duration d = Duration.create(timeout, TimeUnit.MILLISECONDS); - Future future1 = counter1.ask("GetCount", timeout); - Future future2 = counter2.ask("GetCount", timeout); + Future future1 = counter1.ask("GetCount", timeout); + Future future2 = counter2.ask("GetCount", timeout); - future1.await(); - if (future1.isCompleted()) { - if (future1.result().isDefined()) { - int result = (Integer) future1.result().get(); - System.out.println("counter 1: " + result); - } - } + int count1 = (Integer) Await.result(future1, d); + System.out.println("counter 1: " + count1); + int count2 = (Integer) Await.result(future2, d); + System.out.println("counter 1: " + count2); - future2.await(); - if (future2.isCompleted()) { - if (future2.result().isDefined()) { - int result = (Integer) future2.result().get(); - System.out.println("counter 2: " + result); - } - } - - application.stop(counter1); - application.stop(counter2); - - application.shutdown(); + app.shutdown(); } } diff --git a/akka-stm/src/test/java/akka/transactor/example/UntypedTransactorExample.java b/akka-stm/src/test/java/akka/transactor/example/UntypedTransactorExample.java index d5b0a2d691..8a63415c27 100644 --- a/akka-stm/src/test/java/akka/transactor/example/UntypedTransactorExample.java +++ b/akka-stm/src/test/java/akka/transactor/example/UntypedTransactorExample.java @@ -3,45 +3,36 @@ package akka.transactor.example; import akka.actor.ActorSystem; import akka.actor.ActorRef; import akka.actor.Props; +import akka.dispatch.Await; import akka.dispatch.Future; import akka.testkit.AkkaSpec; +import akka.util.Duration; + +import java.util.concurrent.TimeUnit; public class UntypedTransactorExample { public static void main(String[] args) throws InterruptedException { - ActorSystem application = ActorSystem.create("UntypedTransactorExample", AkkaSpec.testConf()); + ActorSystem app = ActorSystem.create("UntypedTransactorExample", AkkaSpec.testConf()); - ActorRef counter1 = application.actorOf(new Props().withCreator(UntypedCounter.class)); - ActorRef counter2 = application.actorOf(new Props().withCreator(UntypedCounter.class)); + ActorRef counter1 = app.actorOf(new Props().withCreator(UntypedCounter.class)); + ActorRef counter2 = app.actorOf(new Props().withCreator(UntypedCounter.class)); counter1.tell(new Increment(counter2)); Thread.sleep(3000); long timeout = 5000; + Duration d = Duration.create(timeout, TimeUnit.MILLISECONDS); - Future future1 = counter1.ask("GetCount", timeout); - Future future2 = counter2.ask("GetCount", timeout); + Future future1 = counter1.ask("GetCount", timeout); + Future future2 = counter2.ask("GetCount", timeout); - future1.await(); - if (future1.isCompleted()) { - if (future1.result().isDefined()) { - int result = (Integer) future1.result().get(); - System.out.println("counter 1: " + result); - } - } + int count1 = (Integer) Await.result(future1, d); + System.out.println("counter 1: " + count1); + int count2 = (Integer) Await.result(future2, d); + System.out.println("counter 1: " + count2); - future2.await(); - if (future2.isCompleted()) { - if (future2.result().isDefined()) { - int result = (Integer) future2.result().get(); - System.out.println("counter 2: " + result); - } - } - - application.stop(counter1); - application.stop(counter2); - - application.shutdown(); + app.shutdown(); } } diff --git a/akka-stm/src/test/java/akka/transactor/test/UntypedCoordinatedIncrementTest.java b/akka-stm/src/test/java/akka/transactor/test/UntypedCoordinatedIncrementTest.java index f2df33a260..e09d15b74d 100644 --- a/akka-stm/src/test/java/akka/transactor/test/UntypedCoordinatedIncrementTest.java +++ b/akka-stm/src/test/java/akka/transactor/test/UntypedCoordinatedIncrementTest.java @@ -2,6 +2,8 @@ package akka.transactor.test; import static org.junit.Assert.*; +import akka.dispatch.Await; +import akka.util.Duration; import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -10,7 +12,6 @@ import org.junit.Before; import akka.actor.ActorSystem; import akka.transactor.Coordinated; -import akka.actor.Actors; import akka.actor.ActorRef; import akka.actor.Props; import akka.actor.UntypedActor; @@ -28,7 +29,6 @@ import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import scala.Option; import scala.collection.JavaConverters; import scala.collection.Seq; @@ -81,8 +81,8 @@ public class UntypedCoordinatedIncrementTest { } catch (InterruptedException exception) { } for (ActorRef counter : counters) { - Future future = counter.ask("GetCount", askTimeout); - assertEquals(1, ((Integer) future.get()).intValue()); + Future future = counter.ask("GetCount", askTimeout); + assertEquals(1, ((Integer) Await.result(future, Duration.create(timeout, TimeUnit.SECONDS))).intValue()); } } @@ -102,8 +102,8 @@ public class UntypedCoordinatedIncrementTest { } catch (InterruptedException exception) { } for (ActorRef counter : counters) { - Future future = counter.ask("GetCount", askTimeout); - assertEquals(0, ((Integer) future.get()).intValue()); + Futurefuture = counter.ask("GetCount", askTimeout); + assertEquals(0,((Integer) Await.result(future, Duration.create(timeout, TimeUnit.SECONDS))).intValue()); } } diff --git a/akka-stm/src/test/java/akka/transactor/test/UntypedTransactorTest.java b/akka-stm/src/test/java/akka/transactor/test/UntypedTransactorTest.java index 7436bbb132..db5528f10c 100644 --- a/akka-stm/src/test/java/akka/transactor/test/UntypedTransactorTest.java +++ b/akka-stm/src/test/java/akka/transactor/test/UntypedTransactorTest.java @@ -2,6 +2,8 @@ package akka.transactor.test; import static org.junit.Assert.*; +import akka.dispatch.Await; +import akka.util.Duration; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -9,7 +11,6 @@ import org.junit.Before; import akka.actor.ActorSystem; import akka.actor.ActorRef; -import akka.actor.Actors; import akka.actor.Props; import akka.actor.UntypedActor; import akka.actor.UntypedActorFactory; @@ -25,7 +26,6 @@ import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import scala.Option; import scala.collection.JavaConverters; import scala.collection.Seq; import akka.testkit.AkkaSpec; @@ -77,16 +77,9 @@ public class UntypedTransactorTest { } catch (InterruptedException exception) { } for (ActorRef counter : counters) { - Future future = counter.ask("GetCount", askTimeout); - future.await(); - if (future.isCompleted()) { - Option resultOption = future.result(); - if (resultOption.isDefined()) { - Object result = resultOption.get(); - int count = (Integer) result; - assertEquals(1, count); - } - } + Future future = counter.ask("GetCount", askTimeout); + int count = (Integer) Await.result(future, Duration.create(askTimeout, TimeUnit.MILLISECONDS)); + assertEquals(1, count); } } @@ -106,16 +99,9 @@ public class UntypedTransactorTest { } catch (InterruptedException exception) { } for (ActorRef counter : counters) { - Future future = counter.ask("GetCount", askTimeout); - future.await(); - if (future.isCompleted()) { - Option resultOption = future.result(); - if (resultOption.isDefined()) { - Object result = resultOption.get(); - int count = (Integer) result; - assertEquals(0, count); - } - } + Future future = counter.ask("GetCount", askTimeout); + int count = (Integer) Await.result(future, Duration.create(askTimeout, TimeUnit.MILLISECONDS)); + assertEquals(0, count); } } diff --git a/akka-stm/src/test/scala/akka/agent/test/AgentSpec.scala b/akka-stm/src/test/scala/akka/agent/test/AgentSpec.scala index 9ef95594be..901e45cd8a 100644 --- a/akka-stm/src/test/scala/akka/agent/test/AgentSpec.scala +++ b/akka-stm/src/test/scala/akka/agent/test/AgentSpec.scala @@ -11,6 +11,7 @@ import akka.util.duration._ import java.util.concurrent.CountDownLatch import akka.testkit.AkkaSpec import akka.testkit._ +import akka.dispatch.Await class CountDownFunction[A](num: Int = 1) extends Function1[A, A] { val latch = new CountDownLatch(num) @@ -35,7 +36,7 @@ class AgentSpec extends AkkaSpec { countDown.await(5 seconds) agent() must be("abcd") - agent.close + agent.close() } "maintain order between send and sendOff" in { @@ -51,7 +52,7 @@ class AgentSpec extends AkkaSpec { countDown.await(5 seconds) agent() must be("abcd") - agent.close + agent.close() } "maintain order between alter and alterOff" in { @@ -62,13 +63,13 @@ class AgentSpec extends AkkaSpec { val r2 = agent.alterOff((s: String) ⇒ { Thread.sleep(2000); s + "c" })(5000) val r3 = agent.alter(_ + "d")(5000) - r1.await.resultOrException.get must be === "ab" - r2.await.resultOrException.get must be === "abc" - r3.await.resultOrException.get must be === "abcd" + Await.result(r1, 5 seconds) must be === "ab" + Await.result(r2, 5 seconds) must be === "abc" + Await.result(r3, 5 seconds) must be === "abcd" agent() must be("abcd") - agent.close + agent.close() } "be immediately readable" in { @@ -90,14 +91,14 @@ class AgentSpec extends AkkaSpec { read must be(5) agent() must be(10) - agent.close + agent.close() } "be readable within a transaction" in { val agent = Agent(5) val value = atomic { agent() } value must be(5) - agent.close + agent.close() } "dispatch sends in successful transactions" in { @@ -112,7 +113,7 @@ class AgentSpec extends AkkaSpec { countDown.await(5 seconds) agent() must be(10) - agent.close + agent.close() } "not dispatch sends in aborted transactions" in { @@ -132,7 +133,7 @@ class AgentSpec extends AkkaSpec { countDown.await(5 seconds) agent() must be(5) - agent.close + agent.close() } "be able to return a 'queued' future" in { @@ -140,11 +141,9 @@ class AgentSpec extends AkkaSpec { agent send (_ + "b") agent send (_ + "c") - val future = agent.future + Await.result(agent.future, timeout.duration) must be("abc") - future.await.result.get must be("abc") - - agent.close + agent.close() } "be able to await the value after updates have completed" in { @@ -154,7 +153,7 @@ class AgentSpec extends AkkaSpec { agent.await must be("abc") - agent.close + agent.close() } "be able to be mapped" in { @@ -164,8 +163,8 @@ class AgentSpec extends AkkaSpec { agent1() must be(5) agent2() must be(10) - agent1.close - agent2.close + agent1.close() + agent2.close() } "be able to be used in a 'foreach' for comprehension" in { @@ -178,7 +177,7 @@ class AgentSpec extends AkkaSpec { result must be(3) - agent.close + agent.close() } "be able to be used in a 'map' for comprehension" in { @@ -188,8 +187,8 @@ class AgentSpec extends AkkaSpec { agent1() must be(5) agent2() must be(10) - agent1.close - agent2.close + agent1.close() + agent2.close() } "be able to be used in a 'flatMap' for comprehension" in { @@ -205,9 +204,9 @@ class AgentSpec extends AkkaSpec { agent2() must be(2) agent3() must be(3) - agent1.close - agent2.close - agent3.close + agent1.close() + agent2.close() + agent3.close() } } } diff --git a/akka-stm/src/test/scala/akka/transactor/test/CoordinatedIncrementSpec.scala b/akka-stm/src/test/scala/akka/transactor/test/CoordinatedIncrementSpec.scala index c2298c9229..d3a23a8191 100644 --- a/akka-stm/src/test/scala/akka/transactor/test/CoordinatedIncrementSpec.scala +++ b/akka-stm/src/test/scala/akka/transactor/test/CoordinatedIncrementSpec.scala @@ -7,6 +7,7 @@ import akka.actor._ import akka.stm.{ Ref, TransactionFactory } import akka.util.duration._ import akka.testkit._ +import akka.dispatch.Await object CoordinatedIncrement { case class Increment(friends: Seq[ActorRef]) @@ -72,7 +73,7 @@ class CoordinatedIncrementSpec extends AkkaSpec with BeforeAndAfterAll { counters(0) ! coordinated(Increment(counters.tail)) coordinated.await for (counter ← counters) { - (counter ? GetCount).as[Int].get must be === 1 + Await.result((counter ? GetCount).mapTo[Int], timeout.duration) must be === 1 } counters foreach (system.stop(_)) system.stop(failer) @@ -89,7 +90,7 @@ class CoordinatedIncrementSpec extends AkkaSpec with BeforeAndAfterAll { counters(0) ! Coordinated(Increment(counters.tail :+ failer)) coordinated.await for (counter ← counters) { - (counter ? GetCount).as[Int].get must be === 0 + Await.result(counter ? GetCount, timeout.duration) must be === 0 } counters foreach (system.stop(_)) system.stop(failer) diff --git a/akka-stm/src/test/scala/akka/transactor/test/FickleFriendsSpec.scala b/akka-stm/src/test/scala/akka/transactor/test/FickleFriendsSpec.scala index 42fe5dbc5a..7fdc55f91d 100644 --- a/akka-stm/src/test/scala/akka/transactor/test/FickleFriendsSpec.scala +++ b/akka-stm/src/test/scala/akka/transactor/test/FickleFriendsSpec.scala @@ -11,6 +11,7 @@ import akka.testkit._ import scala.util.Random.{ nextInt ⇒ random } import java.util.concurrent.CountDownLatch import akka.testkit.TestEvent.Mute +import akka.dispatch.Await object FickleFriends { case class FriendlyIncrement(friends: Seq[ActorRef], latch: CountDownLatch) @@ -119,9 +120,9 @@ class FickleFriendsSpec extends AkkaSpec with BeforeAndAfterAll { val latch = new CountDownLatch(1) coordinator ! FriendlyIncrement(counters, latch) latch.await // this could take a while - (coordinator ? GetCount).as[Int].get must be === 1 + Await.result(coordinator ? GetCount, timeout.duration) must be === 1 for (counter ← counters) { - (counter ? GetCount).as[Int].get must be === 1 + Await.result(counter ? GetCount, timeout.duration) must be === 1 } counters foreach (system.stop(_)) system.stop(coordinator) diff --git a/akka-stm/src/test/scala/akka/transactor/test/TransactorSpec.scala b/akka-stm/src/test/scala/akka/transactor/test/TransactorSpec.scala index d19abee2b0..f82f224870 100644 --- a/akka-stm/src/test/scala/akka/transactor/test/TransactorSpec.scala +++ b/akka-stm/src/test/scala/akka/transactor/test/TransactorSpec.scala @@ -8,6 +8,7 @@ import akka.actor._ import akka.stm._ import akka.util.duration._ import akka.testkit._ +import akka.dispatch.Await object TransactorIncrement { case class Increment(friends: Seq[ActorRef], latch: TestLatch) @@ -95,7 +96,7 @@ class TransactorSpec extends AkkaSpec { counters(0) ! Increment(counters.tail, incrementLatch) incrementLatch.await for (counter ← counters) { - (counter ? GetCount).as[Int].get must be === 1 + Await.result(counter ? GetCount, timeout.duration) must be === 1 } counters foreach (system.stop(_)) system.stop(failer) @@ -112,7 +113,7 @@ class TransactorSpec extends AkkaSpec { counters(0) ! Increment(counters.tail :+ failer, failLatch) failLatch.await for (counter ← counters) { - (counter ? GetCount).as[Int].get must be === 0 + Await.result(counter ? GetCount, timeout.duration) must be === 0 } counters foreach (system.stop(_)) system.stop(failer) diff --git a/akka-testkit/src/main/scala/akka/testkit/TestActorRef.scala b/akka-testkit/src/main/scala/akka/testkit/TestActorRef.scala index 71a5e9fc22..aca5524674 100644 --- a/akka-testkit/src/main/scala/akka/testkit/TestActorRef.scala +++ b/akka-testkit/src/main/scala/akka/testkit/TestActorRef.scala @@ -11,8 +11,8 @@ import akka.actor.Props._ import akka.actor.ActorSystem import java.util.concurrent.atomic.AtomicLong import akka.event.EventStream -import akka.dispatch.{ DefaultDispatcherPrerequisites, DispatcherPrerequisites, Mailbox, Envelope } import scala.collection.immutable.Stack +import akka.dispatch._ /** * This special ActorRef is exclusively for use during unit testing in a single-threaded environment. Therefore, it @@ -69,8 +69,10 @@ class TestActorRef[T <: Actor]( // volatile mailbox read to bring in actor field if (isTerminated) throw new IllegalActorStateException("underlying actor is terminated") underlying.actor.asInstanceOf[T] match { - case null ⇒ ?(InternalGetActor)(underlying.system.settings.ActorTimeout).get.asInstanceOf[T] - case ref ⇒ ref + case null ⇒ + val t = underlying.system.settings.ActorTimeout + Await.result(?(InternalGetActor)(t), t.duration).asInstanceOf[T] + case ref ⇒ ref } } diff --git a/akka-testkit/src/main/scala/akka/testkit/TestKit.scala b/akka-testkit/src/main/scala/akka/testkit/TestKit.scala index d87a313589..96b0cb151e 100644 --- a/akka-testkit/src/main/scala/akka/testkit/TestKit.scala +++ b/akka-testkit/src/main/scala/akka/testkit/TestKit.scala @@ -165,7 +165,7 @@ class TestKit(_system: ActorSystem) { def msgAvailable = !queue.isEmpty /** - * Block until the given condition evaluates to `true` or the timeout + * Await until the given condition evaluates to `true` or the timeout * expires, whichever comes first. * * If no timeout is given, take it from the innermost enclosing `within` @@ -560,7 +560,7 @@ object TestKit { private[testkit] val testActorId = new AtomicInteger(0) /** - * Block until the given condition evaluates to `true` or the timeout + * Await until the given condition evaluates to `true` or the timeout * expires, whichever comes first. * * If no timeout is given, take it from the innermost enclosing `within` diff --git a/akka-testkit/src/test/scala/akka/testkit/AkkaSpec.scala b/akka-testkit/src/test/scala/akka/testkit/AkkaSpec.scala index bba22d7f76..baab14b9cb 100644 --- a/akka-testkit/src/test/scala/akka/testkit/AkkaSpec.scala +++ b/akka-testkit/src/test/scala/akka/testkit/AkkaSpec.scala @@ -7,16 +7,15 @@ import org.scalatest.{ WordSpec, BeforeAndAfterAll, Tag } import org.scalatest.matchers.MustMatchers import akka.actor.{ ActorSystem, ActorSystemImpl } import akka.actor.{ Actor, ActorRef, Props } -import akka.dispatch.MessageDispatcher import akka.event.{ Logging, LoggingAdapter } import akka.util.duration._ -import akka.dispatch.FutureTimeoutException import com.typesafe.config.Config import com.typesafe.config.ConfigFactory import akka.actor.PoisonPill -import java.util.concurrent.LinkedBlockingQueue import akka.actor.CreateChild import akka.actor.DeadLetter +import java.util.concurrent.TimeoutException +import akka.dispatch.{ Await, MessageDispatcher } object TimingTest extends Tag("timing") @@ -65,8 +64,8 @@ abstract class AkkaSpec(_system: ActorSystem) final override def afterAll { system.shutdown() - try system.asInstanceOf[ActorSystemImpl].terminationFuture.await(5 seconds) catch { - case _: FutureTimeoutException ⇒ system.log.warning("Failed to stop [{}] within 5 seconds", system.name) + try Await.ready(system.asInstanceOf[ActorSystemImpl].terminationFuture, 5 seconds) catch { + case _: TimeoutException ⇒ system.log.warning("Failed to stop [{}] within 5 seconds", system.name) } atTermination() } @@ -141,7 +140,7 @@ class AkkaSpecSpec extends WordSpec with MustMatchers { system.registerOnTermination(latch.countDown()) system.shutdown() latch.await(2 seconds) - (davyJones ? "Die!").get must be === "finally gone" + Await.result(davyJones ? "Die!", timeout.duration) must be === "finally gone" // this will typically also contain log messages which were sent after the logger shutdown locker must contain(DeadLetter(42, davyJones, probe.ref)) diff --git a/akka-testkit/src/test/scala/akka/testkit/TestActorRefSpec.scala b/akka-testkit/src/test/scala/akka/testkit/TestActorRefSpec.scala index e9ecf69cc6..6fbe81a0cc 100644 --- a/akka-testkit/src/test/scala/akka/testkit/TestActorRefSpec.scala +++ b/akka-testkit/src/test/scala/akka/testkit/TestActorRefSpec.scala @@ -7,7 +7,7 @@ import org.scalatest.matchers.MustMatchers import org.scalatest.{ BeforeAndAfterEach, WordSpec } import akka.actor._ import akka.event.Logging.Warning -import akka.dispatch.{ Future, Promise } +import akka.dispatch.{ Future, Promise, Await } import akka.util.duration._ import akka.actor.ActorSystem @@ -57,7 +57,7 @@ object TestActorRefSpec { class WorkerActor() extends TActor { def receiveT = { case "work" ⇒ sender ! "workDone"; context.stop(self) - case replyTo: Promise[Any] ⇒ replyTo.completeWithResult("complexReply") + case replyTo: Promise[Any] ⇒ replyTo.success("complexReply") case replyTo: ActorRef ⇒ replyTo ! "complexReply" } } @@ -110,7 +110,7 @@ class TestActorRefSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTime def receive = { case _ ⇒ sender ! nested } })) a must not be (null) - val nested = (a ? "any").as[ActorRef].get + val nested = Await.result((a ? "any").mapTo[ActorRef], timeout.duration) nested must not be (null) a must not be theSameInstanceAs(nested) } @@ -121,7 +121,7 @@ class TestActorRefSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTime def receive = { case _ ⇒ sender ! nested } })) a must not be (null) - val nested = (a ? "any").as[ActorRef].get + val nested = Await.result((a ? "any").mapTo[ActorRef], timeout.duration) nested must not be (null) a must not be theSameInstanceAs(nested) } @@ -195,7 +195,7 @@ class TestActorRefSpec extends AkkaSpec with BeforeAndAfterEach with DefaultTime val f = a ? "work" // CallingThreadDispatcher means that there is no delay f must be('completed) - f.as[String] must equal(Some("workDone")) + Await.result(f, timeout.duration) must equal("workDone") } } diff --git a/akka-testkit/src/test/scala/akka/testkit/TestProbeSpec.scala b/akka-testkit/src/test/scala/akka/testkit/TestProbeSpec.scala index 5e2d775195..4723070299 100644 --- a/akka-testkit/src/test/scala/akka/testkit/TestProbeSpec.scala +++ b/akka-testkit/src/test/scala/akka/testkit/TestProbeSpec.scala @@ -4,8 +4,8 @@ import org.scalatest.WordSpec import org.scalatest.matchers.MustMatchers import org.scalatest.{ BeforeAndAfterEach, WordSpec } import akka.actor._ -import akka.dispatch.Future import akka.util.duration._ +import akka.dispatch.{ Await, Future } @org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) class TestProbeSpec extends AkkaSpec with DefaultTimeout { @@ -18,7 +18,7 @@ class TestProbeSpec extends AkkaSpec with DefaultTimeout { tk.expectMsg(0 millis, "hello") // TestActor runs on CallingThreadDispatcher tk.lastMessage.sender ! "world" future must be('completed) - future.get must equal("world") + Await.result(future, timeout.duration) must equal("world") } "reply to messages" in {