Merge remote-tracking branch 'origin/master' into wip-2.10.0-RC1-∂π

- currently cheating: uses zeroMQ artifacts for scala 2.10M7
- fixed a bunch of more wrong references to scala.concurrent.util
This commit is contained in:
Roland 2012-10-15 16:18:52 +02:00
commit bff79c2f94
47 changed files with 1036 additions and 287 deletions

View file

@ -14,7 +14,7 @@ import akka.actor.Terminated;
import akka.actor.UntypedActor;
import scala.concurrent.Await;
import static akka.pattern.Patterns.ask;
import scala.concurrent.util.Duration;
import scala.concurrent.duration.Duration;
import akka.testkit.AkkaSpec;
import akka.testkit.TestProbe;
@ -41,7 +41,7 @@ public class FaultHandlingTestBase {
//#strategy
private static SupervisorStrategy strategy =
new OneForOneStrategy(10, Duration.parse("1 minute"),
new OneForOneStrategy(10, Duration.create("1 minute"),
new Function<Throwable, Directive>() {
@Override
public Directive apply(Throwable t) {
@ -81,7 +81,7 @@ public class FaultHandlingTestBase {
//#strategy2
private static SupervisorStrategy strategy = new OneForOneStrategy(10,
Duration.parse("1 minute"),
Duration.create("1 minute"),
new Function<Throwable, Directive>() {
@Override
public Directive apply(Throwable t) {

View file

@ -6,18 +6,23 @@ package docs.actor;
//#receive-timeout
import akka.actor.ReceiveTimeout;
import akka.actor.UntypedActor;
import scala.concurrent.util.Duration;
import scala.concurrent.duration.Duration;
public class MyReceivedTimeoutUntypedActor extends UntypedActor {
public MyReceivedTimeoutUntypedActor() {
getContext().setReceiveTimeout(Duration.parse("30 seconds"));
// To set an initial delay
getContext().setReceiveTimeout(Duration.create("30 seconds"));
}
public void onReceive(Object message) {
if (message.equals("Hello")) {
// To set in a response to a message
getContext().setReceiveTimeout(Duration.create("10 seconds"));
getSender().tell("Hello world", getSelf());
} else if (message == ReceiveTimeout.getInstance()) {
// To turn it off
getContext().setReceiveTimeout(Duration.Undefined());
throw new RuntimeException("received timeout");
} else {
unhandled(message);

View file

@ -5,7 +5,7 @@ package docs.actor;
//#imports1
import akka.actor.Props;
import scala.concurrent.util.Duration;
import scala.concurrent.duration.Duration;
import java.util.concurrent.TimeUnit;
//#imports1

View file

@ -11,7 +11,7 @@ import akka.japi.*;
import akka.dispatch.Futures;
import scala.concurrent.Await;
import scala.concurrent.Future;
import scala.concurrent.util.Duration;
import scala.concurrent.duration.Duration;
import java.util.concurrent.TimeUnit;
//#imports

View file

@ -14,7 +14,7 @@ import scala.concurrent.Future;
import akka.dispatch.Futures;
import akka.dispatch.Mapper;
import scala.concurrent.Await;
import scala.concurrent.util.Duration;
import scala.concurrent.duration.Duration;
import akka.util.Timeout;
//#import-future
@ -35,7 +35,7 @@ import akka.actor.Terminated;
import static akka.pattern.Patterns.gracefulStop;
import scala.concurrent.Future;
import scala.concurrent.Await;
import scala.concurrent.util.Duration;
import scala.concurrent.duration.Duration;
import akka.pattern.AskTimeoutException;
//#import-gracefulStop
@ -44,7 +44,7 @@ import static akka.pattern.Patterns.ask;
import static akka.pattern.Patterns.pipe;
import scala.concurrent.Future;
import akka.dispatch.Futures;
import scala.concurrent.util.Duration;
import scala.concurrent.duration.Duration;
import akka.util.Timeout;
import java.util.concurrent.TimeUnit;
import java.util.ArrayList;
@ -192,7 +192,7 @@ public class UntypedActorDocTestBase {
ActorSystem system = ActorSystem.create("MySystem");
ActorRef myActor = system.actorOf(new Props(WatchActor.class));
Future<Object> future = Patterns.ask(myActor, "kill", 1000);
assert Await.result(future, Duration.parse("1 second")).equals("finished");
assert Await.result(future, Duration.create("1 second")).equals("finished");
system.shutdown();
}

View file

@ -13,7 +13,7 @@ import java.util.Map;
import akka.actor.*;
import akka.dispatch.Mapper;
import akka.japi.Function;
import scala.concurrent.util.Duration;
import scala.concurrent.duration.Duration;
import akka.util.Timeout;
import akka.event.Logging;
import akka.event.LoggingAdapter;
@ -62,7 +62,7 @@ public class FaultHandlingDocSample {
public void preStart() {
// If we don't get any progress within 15 seconds then the service
// is unavailable
getContext().setReceiveTimeout(Duration.parse("15 seconds"));
getContext().setReceiveTimeout(Duration.create("15 seconds"));
}
public void onReceive(Object msg) {
@ -237,7 +237,7 @@ public class FaultHandlingDocSample {
// Restart the storage child when StorageException is thrown.
// After 3 restarts within 5 seconds it will be stopped.
private static SupervisorStrategy strategy = new OneForOneStrategy(3,
Duration.parse("5 seconds"), new Function<Throwable, Directive>() {
Duration.create("5 seconds"), new Function<Throwable, Directive>() {
@Override
public Directive apply(Throwable t) {
if (t instanceof StorageException) {

View file

@ -8,8 +8,8 @@ package docs.camel;
import akka.camel.javaapi.UntypedConsumerActor;
import akka.util.Timeout;
import scala.concurrent.Future;
import scala.concurrent.util.Duration;
import scala.concurrent.util.FiniteDuration;
import scala.concurrent.duration.Duration;
import scala.concurrent.duration.FiniteDuration;
import static java.util.concurrent.TimeUnit.SECONDS;
//#CamelActivation

View file

@ -2,8 +2,8 @@ package docs.camel;
//#Consumer4
import akka.camel.CamelMessage;
import akka.camel.javaapi.UntypedConsumerActor;
import scala.concurrent.util.Duration;
import scala.concurrent.util.FiniteDuration;
import scala.concurrent.duration.Duration;
import scala.concurrent.duration.FiniteDuration;
import java.util.concurrent.TimeUnit;

View file

@ -9,7 +9,7 @@ import akka.actor.AbstractExtensionId;
import akka.actor.ExtensionIdProvider;
import akka.actor.ActorSystem;
import akka.actor.ExtendedActorSystem;
import scala.concurrent.util.Duration;
import scala.concurrent.duration.Duration;
import com.typesafe.config.Config;
import java.util.concurrent.TimeUnit;

View file

@ -12,7 +12,7 @@ import akka.util.Timeout;
//#imports1
//#imports2
import scala.concurrent.util.Duration;
import scala.concurrent.duration.Duration;
import akka.japi.Function;
import java.util.concurrent.Callable;
import static akka.dispatch.Futures.future;
@ -113,7 +113,7 @@ public class FutureDocTestBase {
return "Hello" + "World";
}
}, system.dispatcher());
String result = (String) Await.result(f, Duration.create(1, SECONDS));
String result = (String) Await.result(f, Duration.create(5, SECONDS));
//#future-eval
assertEquals("HelloWorld", result);
}
@ -135,7 +135,7 @@ public class FutureDocTestBase {
}
}, ec);
int result = Await.result(f2, Duration.create(1, SECONDS));
int result = Await.result(f2, Duration.create(5, SECONDS));
assertEquals(10, result);
//#map
}
@ -159,7 +159,7 @@ public class FutureDocTestBase {
}, ec);
//#map2
int result = Await.result(f2, Duration.create(1, SECONDS));
int result = Await.result(f2, Duration.create(5, SECONDS));
assertEquals(10, result);
}
@ -183,7 +183,7 @@ public class FutureDocTestBase {
}, ec);
//#map3
int result = Await.result(f2, Duration.create(1, SECONDS));
int result = Await.result(f2, Duration.create(5, SECONDS));
assertEquals(10, result);
}
@ -209,7 +209,7 @@ public class FutureDocTestBase {
}, ec);
//#flat-map
int result = Await.result(f2, Duration.create(1, SECONDS));
int result = Await.result(f2, Duration.create(5, SECONDS));
assertEquals(10, result);
}
@ -238,7 +238,7 @@ public class FutureDocTestBase {
}
}, ec);
long result = Await.result(futureSum, Duration.create(1, SECONDS));
long result = Await.result(futureSum, Duration.create(5, SECONDS));
//#sequence
assertEquals(3L, result);
}
@ -262,7 +262,7 @@ public class FutureDocTestBase {
}, ec);
//Returns the sequence of strings as upper case
Iterable<String> result = Await.result(futureResult, Duration.create(1, SECONDS));
Iterable<String> result = Await.result(futureResult, Duration.create(5, SECONDS));
assertEquals(Arrays.asList("A", "B", "C"), result);
//#traverse
}
@ -286,7 +286,7 @@ public class FutureDocTestBase {
return r + t; //Just concatenate
}
}, ec);
String result = Await.result(resultFuture, Duration.create(1, SECONDS));
String result = Await.result(resultFuture, Duration.create(5, SECONDS));
//#fold
assertEquals("ab", result);
@ -310,7 +310,7 @@ public class FutureDocTestBase {
}
}, ec);
Object result = Await.result(resultFuture, Duration.create(1, SECONDS));
Object result = Await.result(resultFuture, Duration.create(5, SECONDS));
//#reduce
assertEquals("ab", result);
@ -326,10 +326,10 @@ public class FutureDocTestBase {
Future<String> otherFuture = Futures.failed(
new IllegalArgumentException("Bang!"));
//#failed
Object result = Await.result(future, Duration.create(1, SECONDS));
Object result = Await.result(future, Duration.create(5, SECONDS));
assertEquals("Yay!", result);
Throwable result2 = Await.result(otherFuture.failed(),
Duration.create(1, SECONDS));
Duration.create(5, SECONDS));
assertEquals("Bang!", result2.getMessage());
}
@ -399,7 +399,7 @@ public class FutureDocTestBase {
throw problem;
}
}, ec);
int result = Await.result(future, Duration.create(1, SECONDS));
int result = Await.result(future, Duration.create(5, SECONDS));
assertEquals(result, 0);
//#recover
}
@ -425,7 +425,7 @@ public class FutureDocTestBase {
throw problem;
}
}, ec);
int result = Await.result(future, Duration.create(1, SECONDS));
int result = Await.result(future, Duration.create(5, SECONDS));
assertEquals(result, 0);
//#try-recover
}
@ -497,7 +497,7 @@ public class FutureDocTestBase {
}
}, ec);
String result = Await.result(future3, Duration.create(1, SECONDS));
String result = Await.result(future3, Duration.create(5, SECONDS));
assertEquals("foo bar", result);
//#zip
}
@ -509,7 +509,7 @@ public class FutureDocTestBase {
Future<String> future3 = Futures.successful("bar");
// Will have "bar" in this case
Future<String> future4 = future1.fallbackTo(future2).fallbackTo(future3);
String result = Await.result(future4, Duration.create(1, SECONDS));
String result = Await.result(future4, Duration.create(5, SECONDS));
assertEquals("bar", result);
//#fallback-to
}

View file

@ -19,7 +19,7 @@ import org.junit.Test;
import scala.concurrent.Await;
import scala.concurrent.Future;
import scala.concurrent.util.Duration;
import scala.concurrent.duration.Duration;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.OneForOneStrategy;
@ -68,7 +68,7 @@ public class CustomRouterDocTestBase {
public void demonstrateSupervisor() {
//#supervision
final SupervisorStrategy strategy =
new OneForOneStrategy(5, Duration.parse("1 minute"),
new OneForOneStrategy(5, Duration.create("1 minute"),
new Class<?>[] { Exception.class });
final ActorRef router = system.actorOf(new Props(MyActor.class)
.withRouter(new RoundRobinRouter(5).withSupervisorStrategy(strategy)));

View file

@ -11,7 +11,7 @@ import akka.routing.SmallestMailboxRouter;
import akka.actor.UntypedActor;
import akka.actor.ActorRef;
import akka.actor.Props;
import scala.concurrent.util.Duration;
import scala.concurrent.duration.Duration;
import akka.util.Timeout;
import scala.concurrent.Future;
import scala.concurrent.Await;

View file

@ -0,0 +1,191 @@
/**
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.pattern;
import akka.actor.*;
import akka.testkit.*;
import akka.testkit.TestEvent.Mute;
import akka.testkit.TestEvent.UnMute;
import org.junit.*;
import scala.concurrent.duration.Duration;
import scala.concurrent.duration.FiniteDuration;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
public class SchedulerPatternTest {
static ActorSystem system;
@BeforeClass
public static void setUp() {
system = ActorSystem.create("SchedulerPatternTest", AkkaSpec.testConf());
}
@AfterClass
public static void tearDown() {
system.shutdown();
}
static
//#schedule-constructor
public class ScheduleInConstructor extends UntypedActor {
private final Cancellable tick = getContext().system().scheduler().schedule(
Duration.create(500, TimeUnit.MILLISECONDS),
Duration.create(1000, TimeUnit.MILLISECONDS),
getSelf(), "tick", getContext().dispatcher());
//#schedule-constructor
// this variable and constructor is declared here to not show up in the docs
final ActorRef target;
public ScheduleInConstructor(ActorRef target) {
this.target = target;
}
//#schedule-constructor
@Override
public void postStop() {
tick.cancel();
}
@Override
public void onReceive(Object message) throws Exception {
if (message.equals("tick")) {
// do something useful here
//#schedule-constructor
target.tell(message, getSelf());
//#schedule-constructor
}
//#schedule-constructor
else if (message.equals("restart")) {
throw new ArithmeticException();
}
//#schedule-constructor
else {
unhandled(message);
}
}
}
//#schedule-constructor
static
//#schedule-receive
public class ScheduleInReceive extends UntypedActor {
//#schedule-receive
// this variable and constructor is declared here to not show up in the docs
final ActorRef target;
public ScheduleInReceive(ActorRef target) {
this.target = target;
}
//#schedule-receive
@Override
public void preStart() {
getContext().system().scheduler().scheduleOnce(
Duration.create(500, TimeUnit.MILLISECONDS),
getSelf(), "tick", getContext().dispatcher());
}
// override postRestart so we don't call preStart and schedule a new message
@Override
public void postRestart(Throwable reason) {
}
@Override
public void onReceive(Object message) throws Exception {
if (message.equals("tick")) {
// send another periodic tick after the specified delay
getContext().system().scheduler().scheduleOnce(
Duration.create(1000, TimeUnit.MILLISECONDS),
getSelf(), "tick", getContext().dispatcher());
// do something useful here
//#schedule-receive
target.tell(message, getSelf());
//#schedule-receive
}
//#schedule-receive
else if (message.equals("restart")) {
throw new ArithmeticException();
}
//#schedule-receive
else {
unhandled(message);
}
}
}
//#schedule-receive
@Test
@Ignore // no way to tag this as timing sensitive
public void scheduleInConstructor() {
new TestSchedule(system) {{
final JavaTestKit probe = new JavaTestKit(system);
final Props props = new Props(new UntypedActorFactory() {
public UntypedActor create() {
return new ScheduleInConstructor(probe.getRef());
}
});
testSchedule(probe, props, duration("3000 millis"), duration("2000 millis"));
}};
}
@Test
@Ignore // no way to tag this as timing sensitive
public void scheduleInReceive() {
new TestSchedule(system) {{
final JavaTestKit probe = new JavaTestKit(system);
final Props props = new Props(new UntypedActorFactory() {
public UntypedActor create() {
return new ScheduleInReceive(probe.getRef());
}
});
testSchedule(probe, props, duration("3000 millis"), duration("2500 millis"));
}};
}
public static class TestSchedule extends JavaTestKit {
private ActorSystem system;
public TestSchedule(ActorSystem system) {
super(system);
this.system = system;
}
public void testSchedule(final JavaTestKit probe, Props props,
FiniteDuration startDuration,
FiniteDuration afterRestartDuration) {
Iterable<akka.testkit.EventFilter> filter =
Arrays.asList(new akka.testkit.EventFilter[]{
(akka.testkit.EventFilter) new ErrorFilter(ArithmeticException.class)});
try {
system.eventStream().publish(new Mute(filter));
final ActorRef actor = system.actorOf(props);
new Within(startDuration) {
protected void run() {
probe.expectMsgEquals("tick");
probe.expectMsgEquals("tick");
probe.expectMsgEquals("tick");
}
};
actor.tell("restart", getRef());
new Within(afterRestartDuration) {
protected void run() {
probe.expectMsgEquals("tick");
probe.expectMsgEquals("tick");
}
};
system.stop(actor);
}
finally {
system.eventStream().publish(new UnMute(filter));
}
}
}
}

View file

@ -26,7 +26,7 @@ import akka.testkit.TestActor;
import akka.testkit.TestActor.AutoPilot;
import akka.testkit.TestActorRef;
import akka.testkit.JavaTestKit;
import scala.concurrent.util.Duration;
import scala.concurrent.duration.Duration;
public class TestKitDocTest {

View file

@ -14,7 +14,7 @@ import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.actor.UntypedActor;
import akka.testkit.JavaTestKit;
import scala.concurrent.util.Duration;
import scala.concurrent.duration.Duration;
public class TestKitSampleTest {

View file

@ -30,7 +30,7 @@ import akka.actor.UntypedActor;
import akka.actor.Props;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import scala.concurrent.util.Duration;
import scala.concurrent.duration.Duration;
import akka.serialization.SerializationExtension;
import akka.serialization.Serialization;
import java.io.Serializable;

View file

@ -17,6 +17,37 @@ sense to add to the ``akka.pattern`` package for creating an `OTP-like library
You might find some of the patterns described in the Scala chapter of
:ref:`howto-scala` useful even though the example code is written in Scala.
Scheduling Periodic Messages
============================
This pattern describes how to schedule periodic messages to yourself in two different
ways.
The first way is to set up periodic message scheduling in the constructor of the actor,
and cancel that scheduled sending in ``postStop`` or else we might have multiple registered
message sends to the same actor.
.. note::
With this approach the scheduled periodic message send will be restarted with the actor on restarts.
This also means that the time period that elapses between two tick messages during a restart may drift
off based on when you restart the scheduled message sends relative to the time that the last message was
sent, and how long the initial delay is. Worst case scenario is ``interval`` plus ``initialDelay``.
.. includecode:: code/docs/pattern/SchedulerPatternTest.java#schedule-constructor
The second variant sets up an initial one shot message send in the ``preStart`` method
of the actor, and the then the actor when it receives this message sets up a new one shot
message send. You also have to override ``postRestart`` so we don't call ``preStart``
and schedule the initial message send again.
.. note::
With this approach we won't fill up the mailbox with tick messages if the actor is
under pressure, but only schedule a new tick message when we have seen the previous one.
.. includecode:: code/docs/pattern/SchedulerPatternTest.java#schedule-receive
Template Pattern
================
@ -33,4 +64,3 @@ This is an especially nice pattern, since it does even come with some empty exam
Spread the word: this is the easiest way to get famous!
Please keep this pattern at the end of this file.

View file

@ -194,8 +194,7 @@ It has one single dependency; the slf4j-api jar. In runtime you also need a SLF4
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.4</version>
<scope>runtime</scope>
<version>1.0.7</version>
</dependency>
You need to enable the Slf4jEventHandler in the 'event-handlers' element in

View file

@ -431,13 +431,20 @@ defaults to a 'dead-letter' actor ref.
getSender().tell(result); // will have dead-letter actor as default
}
Initial receive timeout
=======================
Receive timeout
===============
A timeout mechanism can be used to receive a message when no initial message is
received within a certain time. To receive this timeout you have to set the
``receiveTimeout`` property and declare handing for the ReceiveTimeout
message.
The `UntypedActorContext` :meth:`setReceiveTimeout` defines the inactivity timeout after which
the sending of a `ReceiveTimeout` message is triggered.
When specified, the receive function should be able to handle an `akka.actor.ReceiveTimeout` message.
1 millisecond is the minimum supported timeout.
Please note that the receive timeout might fire and enqueue the `ReceiveTimeout` message right after
another message was enqueued; hence it is **not guaranteed** that upon reception of the receive
timeout there must have been an idle period beforehand as configured via this method.
Once set, the receive timeout stays in effect (i.e. continues firing repeatedly after inactivity
periods). Pass in `Duration.Undefined` to switch off this feature.
.. includecode:: code/docs/actor/MyReceivedTimeoutUntypedActor.java#receive-timeout