improve AbstractActor, #21717
* Receive class that wraps PartialFunction, to avoid
scary scala types
* move AbstractActorContext to AbstractActor.ActorContext
* converting docs, many, many UntypedActor
* removing UntypedActor docs
* add unit test for ReceiveBuilder
* MiMa filters
* consistent use of getContext(), self(), sender()
* rename cross references
* migration guide
* skip samples for now
* improve match type safetyi, add matchUnchecked
* the `? extends P` caused code like this to compile:
`match(String.class, (Integer i) -> {})`
* added matchUnchecked, since it can still be useful (um, convenient)
to be able to do:
`matchUnchecked(List.class, (List<String> list) -> {})`
* eleminate some scala.Option
* preRestart
* findChild
* ActorIdentity.getActorRef
This commit is contained in:
parent
3617fe8b41
commit
4bd6b7aab1
157 changed files with 3290 additions and 8882 deletions
|
|
@ -8,7 +8,7 @@ import org.junit.BeforeClass;
|
|||
import org.junit.Test;
|
||||
|
||||
import akka.actor.ActorSystem;
|
||||
import akka.actor.UntypedActor;
|
||||
import akka.actor.AbstractActor;
|
||||
//#imports
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -24,65 +24,63 @@ import akka.util.ByteString;
|
|||
|
||||
public class IODocTest {
|
||||
|
||||
static public class Demo extends UntypedActor {
|
||||
static public class Demo extends AbstractActor {
|
||||
ActorRef connectionActor = null;
|
||||
ActorRef listener = getSelf();
|
||||
ActorRef listener = self();
|
||||
|
||||
@Override
|
||||
public void onReceive(Object msg) {
|
||||
if ("connect".equals(msg)) {
|
||||
//#manager
|
||||
final ActorRef tcp = Tcp.get(system).manager();
|
||||
//#manager
|
||||
//#connect
|
||||
final InetSocketAddress remoteAddr = new InetSocketAddress("127.0.0.1",
|
||||
12345);
|
||||
tcp.tell(TcpMessage.connect(remoteAddr), getSelf());
|
||||
//#connect
|
||||
//#connect-with-options
|
||||
final InetSocketAddress localAddr = new InetSocketAddress("127.0.0.1",
|
||||
1234);
|
||||
final List<Inet.SocketOption> options = new ArrayList<Inet.SocketOption>();
|
||||
options.add(TcpSO.keepAlive(true));
|
||||
tcp.tell(TcpMessage.connect(remoteAddr, localAddr, options, null, false), getSelf());
|
||||
//#connect-with-options
|
||||
} else
|
||||
//#connected
|
||||
if (msg instanceof Tcp.Connected) {
|
||||
final Tcp.Connected conn = (Tcp.Connected) msg;
|
||||
connectionActor = getSender();
|
||||
connectionActor.tell(TcpMessage.register(listener), getSelf());
|
||||
}
|
||||
//#connected
|
||||
else
|
||||
//#received
|
||||
if (msg instanceof Tcp.Received) {
|
||||
final Tcp.Received recv = (Tcp.Received) msg;
|
||||
final ByteString data = recv.data();
|
||||
// and do something with the received data ...
|
||||
} else if (msg instanceof Tcp.CommandFailed) {
|
||||
final Tcp.CommandFailed failed = (Tcp.CommandFailed) msg;
|
||||
final Tcp.Command command = failed.cmd();
|
||||
// react to failed connect, bind, write, etc.
|
||||
} else if (msg instanceof Tcp.ConnectionClosed) {
|
||||
final Tcp.ConnectionClosed closed = (Tcp.ConnectionClosed) msg;
|
||||
if (closed.isAborted()) {
|
||||
// handle close reasons like this
|
||||
}
|
||||
}
|
||||
//#received
|
||||
else
|
||||
if ("bind".equals(msg)) {
|
||||
final ActorRef handler = getSelf();
|
||||
//#bind
|
||||
final ActorRef tcp = Tcp.get(system).manager();
|
||||
final InetSocketAddress localAddr = new InetSocketAddress("127.0.0.1",
|
||||
1234);
|
||||
final List<Inet.SocketOption> options = new ArrayList<Inet.SocketOption>();
|
||||
options.add(TcpSO.reuseAddress(true));
|
||||
tcp.tell(TcpMessage.bind(handler, localAddr, 10, options, false), getSelf());
|
||||
//#bind
|
||||
}
|
||||
public Receive createReceive() {
|
||||
return receiveBuilder()
|
||||
.matchEquals("connect", msg -> {
|
||||
//#manager
|
||||
final ActorRef tcp = Tcp.get(system).manager();
|
||||
//#manager
|
||||
//#connect
|
||||
final InetSocketAddress remoteAddr = new InetSocketAddress("127.0.0.1",
|
||||
12345);
|
||||
tcp.tell(TcpMessage.connect(remoteAddr), self());
|
||||
//#connect
|
||||
//#connect-with-options
|
||||
final InetSocketAddress localAddr = new InetSocketAddress("127.0.0.1",
|
||||
1234);
|
||||
final List<Inet.SocketOption> options = new ArrayList<Inet.SocketOption>();
|
||||
options.add(TcpSO.keepAlive(true));
|
||||
tcp.tell(TcpMessage.connect(remoteAddr, localAddr, options, null, false), self());
|
||||
//#connect-with-options
|
||||
})
|
||||
//#connected
|
||||
.match(Tcp.Connected.class, conn -> {
|
||||
connectionActor = sender();
|
||||
connectionActor.tell(TcpMessage.register(listener), self());
|
||||
})
|
||||
//#connected
|
||||
//#received
|
||||
.match(Tcp.Received.class, recv -> {
|
||||
final ByteString data = recv.data();
|
||||
// and do something with the received data ...
|
||||
})
|
||||
.match(Tcp.CommandFailed.class, failed -> {
|
||||
final Tcp.Command command = failed.cmd();
|
||||
// react to failed connect, bind, write, etc.
|
||||
})
|
||||
.match(Tcp.ConnectionClosed.class, closed -> {
|
||||
if (closed.isAborted()) {
|
||||
// handle close reasons like this
|
||||
}
|
||||
})
|
||||
//#received
|
||||
.matchEquals("bind", msg -> {
|
||||
final ActorRef handler = self();
|
||||
//#bind
|
||||
final ActorRef tcp = Tcp.get(system).manager();
|
||||
final InetSocketAddress localAddr = new InetSocketAddress("127.0.0.1",
|
||||
1234);
|
||||
final List<Inet.SocketOption> options = new ArrayList<Inet.SocketOption>();
|
||||
options.add(TcpSO.reuseAddress(true));
|
||||
tcp.tell(TcpMessage.bind(handler, localAddr, 10, options, false), self());
|
||||
//#bind
|
||||
})
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,14 +25,14 @@ public class JavaReadBackPressure {
|
|||
//#pull-accepting
|
||||
public void onReceive(Object message) throws Exception {
|
||||
if (message instanceof Tcp.Bound) {
|
||||
listener = getSender();
|
||||
listener = sender();
|
||||
// Accept connections one by one
|
||||
listener.tell(TcpMessage.resumeAccepting(1), getSelf());
|
||||
listener.tell(TcpMessage.resumeAccepting(1), self());
|
||||
} else if (message instanceof Tcp.Connected) {
|
||||
ActorRef handler = getContext().actorOf(Props.create(PullEcho.class, getSender()));
|
||||
getSender().tell(TcpMessage.register(handler), getSelf());
|
||||
ActorRef handler = getContext().actorOf(Props.create(PullEcho.class, sender()));
|
||||
sender().tell(TcpMessage.register(handler), self());
|
||||
// Resume accepting connections
|
||||
listener.tell(TcpMessage.resumeAccepting(1), getSelf());
|
||||
listener.tell(TcpMessage.resumeAccepting(1), self());
|
||||
}
|
||||
}
|
||||
//#pull-accepting
|
||||
|
|
@ -43,8 +43,8 @@ public class JavaReadBackPressure {
|
|||
tcp = Tcp.get(getContext().system()).manager();
|
||||
final List<Inet.SocketOption> options = new ArrayList<Inet.SocketOption>();
|
||||
tcp.tell(
|
||||
TcpMessage.bind(getSelf(), new InetSocketAddress("localhost", 0), 100, options, true),
|
||||
getSelf()
|
||||
TcpMessage.bind(self(), new InetSocketAddress("localhost", 0), 100, options, true),
|
||||
self()
|
||||
);
|
||||
//#pull-mode-bind
|
||||
}
|
||||
|
|
@ -54,7 +54,7 @@ public class JavaReadBackPressure {
|
|||
final List<Inet.SocketOption> options = new ArrayList<Inet.SocketOption>();
|
||||
tcp.tell(
|
||||
TcpMessage.connect(new InetSocketAddress("localhost", 3000), null, options, null, true),
|
||||
getSelf()
|
||||
self()
|
||||
);
|
||||
//#pull-mode-connect
|
||||
}
|
||||
|
|
@ -73,16 +73,16 @@ public class JavaReadBackPressure {
|
|||
//#pull-reading-echo
|
||||
@Override
|
||||
public void preStart() throws Exception {
|
||||
connection.tell(TcpMessage.resumeReading(), getSelf());
|
||||
connection.tell(TcpMessage.resumeReading(), self());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Object message) throws Exception {
|
||||
if (message instanceof Tcp.Received) {
|
||||
ByteString data = ((Tcp.Received) message).data();
|
||||
connection.tell(TcpMessage.write(data, new Ack()), getSelf());
|
||||
connection.tell(TcpMessage.write(data, new Ack()), self());
|
||||
} else if (message instanceof Ack) {
|
||||
connection.tell(TcpMessage.resumeReading(), getSelf());
|
||||
connection.tell(TcpMessage.resumeReading(), self());
|
||||
}
|
||||
}
|
||||
//#pull-reading-echo
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ public class JavaUdpMulticast {
|
|||
final ActorRef mgr = Udp.get(getContext().system()).getManager();
|
||||
// listen for datagrams on this address
|
||||
InetSocketAddress endpoint = new InetSocketAddress(port);
|
||||
mgr.tell(UdpMessage.bind(getSelf(), endpoint, options), getSelf());
|
||||
mgr.tell(UdpMessage.bind(self(), endpoint, options), self());
|
||||
//#bind
|
||||
}
|
||||
|
||||
|
|
@ -82,12 +82,12 @@ public class JavaUdpMulticast {
|
|||
if (msg instanceof Udp.Bound) {
|
||||
final Udp.Bound b = (Udp.Bound) msg;
|
||||
log.info("Bound to {}", b.localAddress());
|
||||
sink.tell(b, getSelf());
|
||||
sink.tell(b, self());
|
||||
} else if (msg instanceof Udp.Received) {
|
||||
final Udp.Received r = (Udp.Received) msg;
|
||||
final String txt = r.data().decodeString("utf-8");
|
||||
log.info("Received '{}' from {}", txt, r.sender());
|
||||
sink.tell(txt, getSelf());
|
||||
sink.tell(txt, self());
|
||||
} else unhandled(msg);
|
||||
}
|
||||
}
|
||||
|
|
@ -110,7 +110,7 @@ public class JavaUdpMulticast {
|
|||
options.add(new Inet6ProtocolFamily());
|
||||
|
||||
final ActorRef mgr = Udp.get(getContext().system()).getManager();
|
||||
mgr.tell(UdpMessage.simpleSender(options), getSelf());
|
||||
mgr.tell(UdpMessage.simpleSender(options), self());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -118,7 +118,7 @@ public class JavaUdpMulticast {
|
|||
if (msg instanceof Udp.SimpleSenderReady) {
|
||||
InetSocketAddress remote = new InetSocketAddress(group + "%" + iface, port);
|
||||
log.info("Sending message to " + remote);
|
||||
getSender().tell(UdpMessage.send(ByteString.fromString(message), remote), getSelf());
|
||||
sender().tell(UdpMessage.send(ByteString.fromString(message), remote), self());
|
||||
} else unhandled(msg);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ public class UdpConnectedDocTest {
|
|||
|
||||
static public class Demo extends UntypedActor {
|
||||
ActorRef connectionActor = null;
|
||||
ActorRef handler = getSelf();
|
||||
ActorSystem system = context().system();
|
||||
ActorRef handler = self();
|
||||
ActorSystem system = getContext().system();
|
||||
|
||||
@Override
|
||||
public void onReceive(Object msg) {
|
||||
|
|
@ -38,7 +38,7 @@ public class UdpConnectedDocTest {
|
|||
//#connect
|
||||
final InetSocketAddress remoteAddr =
|
||||
new InetSocketAddress("127.0.0.1", 12345);
|
||||
udp.tell(UdpConnectedMessage.connect(handler, remoteAddr), getSelf());
|
||||
udp.tell(UdpConnectedMessage.connect(handler, remoteAddr), self());
|
||||
//#connect
|
||||
//#connect-with-options
|
||||
final InetSocketAddress localAddr =
|
||||
|
|
@ -46,13 +46,13 @@ public class UdpConnectedDocTest {
|
|||
final List<Inet.SocketOption> options =
|
||||
new ArrayList<Inet.SocketOption>();
|
||||
options.add(UdpSO.broadcast(true));
|
||||
udp.tell(UdpConnectedMessage.connect(handler, remoteAddr, localAddr, options), getSelf());
|
||||
udp.tell(UdpConnectedMessage.connect(handler, remoteAddr, localAddr, options), self());
|
||||
//#connect-with-options
|
||||
} else
|
||||
//#connected
|
||||
if (msg instanceof UdpConnected.Connected) {
|
||||
final UdpConnected.Connected conn = (UdpConnected.Connected) msg;
|
||||
connectionActor = getSender(); // Save the worker ref for later use
|
||||
connectionActor = sender(); // Save the worker ref for later use
|
||||
}
|
||||
//#connected
|
||||
else
|
||||
|
|
@ -73,7 +73,7 @@ public class UdpConnectedDocTest {
|
|||
if ("send".equals(msg)) {
|
||||
ByteString data = ByteString.empty();
|
||||
//#send
|
||||
connectionActor.tell(UdpConnectedMessage.send(data), getSelf());
|
||||
connectionActor.tell(UdpConnectedMessage.send(data), self());
|
||||
//#send
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,15 +29,15 @@ public class UdpDocTest {
|
|||
|
||||
// request creation of a SimpleSender
|
||||
final ActorRef mgr = Udp.get(getContext().system()).getManager();
|
||||
mgr.tell(UdpMessage.simpleSender(), getSelf());
|
||||
mgr.tell(UdpMessage.simpleSender(), self());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Object msg) {
|
||||
if (msg instanceof Udp.SimpleSenderReady) {
|
||||
getContext().become(ready(getSender()));
|
||||
getContext().become(ready(sender()));
|
||||
//#sender
|
||||
getSender().tell(UdpMessage.send(ByteString.fromString("hello"), remote), getSelf());
|
||||
sender().tell(UdpMessage.send(ByteString.fromString("hello"), remote), self());
|
||||
//#sender
|
||||
} else unhandled(msg);
|
||||
}
|
||||
|
|
@ -48,10 +48,10 @@ public class UdpDocTest {
|
|||
public void apply(Object msg) throws Exception {
|
||||
if (msg instanceof String) {
|
||||
final String str = (String) msg;
|
||||
send.tell(UdpMessage.send(ByteString.fromString(str), remote), getSelf());
|
||||
send.tell(UdpMessage.send(ByteString.fromString(str), remote), self());
|
||||
//#sender
|
||||
if (str.equals("world")) {
|
||||
send.tell(PoisonPill.getInstance(), getSelf());
|
||||
send.tell(PoisonPill.getInstance(), self());
|
||||
}
|
||||
//#sender
|
||||
|
||||
|
|
@ -72,8 +72,8 @@ public class UdpDocTest {
|
|||
// request creation of a bound listen socket
|
||||
final ActorRef mgr = Udp.get(getContext().system()).getManager();
|
||||
mgr.tell(
|
||||
UdpMessage.bind(getSelf(), new InetSocketAddress("localhost", 0)),
|
||||
getSelf());
|
||||
UdpMessage.bind(self(), new InetSocketAddress("localhost", 0)),
|
||||
self());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -81,9 +81,9 @@ public class UdpDocTest {
|
|||
if (msg instanceof Udp.Bound) {
|
||||
final Udp.Bound b = (Udp.Bound) msg;
|
||||
//#listener
|
||||
nextActor.tell(b.localAddress(), getSender());
|
||||
nextActor.tell(b.localAddress(), sender());
|
||||
//#listener
|
||||
getContext().become(ready(getSender()));
|
||||
getContext().become(ready(sender()));
|
||||
} else unhandled(msg);
|
||||
}
|
||||
|
||||
|
|
@ -94,19 +94,19 @@ public class UdpDocTest {
|
|||
if (msg instanceof Udp.Received) {
|
||||
final Udp.Received r = (Udp.Received) msg;
|
||||
// echo server example: send back the data
|
||||
socket.tell(UdpMessage.send(r.data(), r.sender()), getSelf());
|
||||
socket.tell(UdpMessage.send(r.data(), r.sender()), self());
|
||||
// or do some processing and forward it on
|
||||
final Object processed = // parse data etc., e.g. using PipelineStage
|
||||
//#listener
|
||||
r.data().utf8String();
|
||||
//#listener
|
||||
nextActor.tell(processed, getSelf());
|
||||
nextActor.tell(processed, self());
|
||||
|
||||
} else if (msg.equals(UdpMessage.unbind())) {
|
||||
socket.tell(msg, getSelf());
|
||||
socket.tell(msg, self());
|
||||
|
||||
} else if (msg instanceof Udp.Unbound) {
|
||||
getContext().stop(getSelf());
|
||||
getContext().stop(self());
|
||||
|
||||
} else unhandled(msg);
|
||||
}
|
||||
|
|
@ -124,17 +124,17 @@ public class UdpDocTest {
|
|||
|
||||
// create a restricted a.k.a. “connected” socket
|
||||
final ActorRef mgr = UdpConnected.get(getContext().system()).getManager();
|
||||
mgr.tell(UdpConnectedMessage.connect(getSelf(), remote), getSelf());
|
||||
mgr.tell(UdpConnectedMessage.connect(self(), remote), self());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Object msg) {
|
||||
if (msg instanceof UdpConnected.Connected) {
|
||||
getContext().become(ready(getSender()));
|
||||
getContext().become(ready(sender()));
|
||||
//#connected
|
||||
getSender()
|
||||
sender()
|
||||
.tell(UdpConnectedMessage.send(ByteString.fromString("hello")),
|
||||
getSelf());
|
||||
self());
|
||||
//#connected
|
||||
} else unhandled(msg);
|
||||
}
|
||||
|
|
@ -150,7 +150,7 @@ public class UdpDocTest {
|
|||
if (r.data().utf8String().equals("hello")) {
|
||||
connection.tell(
|
||||
UdpConnectedMessage.send(ByteString.fromString("world")),
|
||||
getSelf());
|
||||
self());
|
||||
}
|
||||
// #connected
|
||||
|
||||
|
|
@ -158,13 +158,13 @@ public class UdpDocTest {
|
|||
final String str = (String) msg;
|
||||
connection
|
||||
.tell(UdpConnectedMessage.send(ByteString.fromString(str)),
|
||||
getSelf());
|
||||
self());
|
||||
|
||||
} else if (msg.equals(UdpConnectedMessage.disconnect())) {
|
||||
connection.tell(msg, getSelf());
|
||||
connection.tell(msg, self());
|
||||
|
||||
} else if (msg instanceof UdpConnected.Disconnected) {
|
||||
getContext().stop(getSelf());
|
||||
getContext().stop(self());
|
||||
|
||||
} else unhandled(msg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import java.util.LinkedList;
|
|||
import java.util.Queue;
|
||||
|
||||
import akka.actor.ActorRef;
|
||||
import akka.actor.UntypedActor;
|
||||
import akka.actor.AbstractActor;
|
||||
import akka.event.Logging;
|
||||
import akka.event.LoggingAdapter;
|
||||
import akka.io.Tcp.CommandFailed;
|
||||
|
|
@ -19,14 +19,13 @@ import akka.io.Tcp.Received;
|
|||
import akka.io.Tcp.Write;
|
||||
import akka.io.Tcp.WritingResumed;
|
||||
import akka.io.TcpMessage;
|
||||
import akka.japi.Procedure;
|
||||
import akka.util.ByteString;
|
||||
|
||||
//#echo-handler
|
||||
public class EchoHandler extends UntypedActor {
|
||||
public class EchoHandler extends AbstractActor {
|
||||
|
||||
final LoggingAdapter log = Logging
|
||||
.getLogger(getContext().system(), getSelf());
|
||||
.getLogger(getContext().system(), self());
|
||||
|
||||
final ActorRef connection;
|
||||
final InetSocketAddress remote;
|
||||
|
|
@ -35,6 +34,13 @@ public class EchoHandler extends UntypedActor {
|
|||
public static final long HIGH_WATERMARK = MAX_STORED * 5 / 10;
|
||||
public static final long LOW_WATERMARK = MAX_STORED * 2 / 10;
|
||||
|
||||
private long transferred;
|
||||
private int storageOffset = 0;
|
||||
private long stored = 0;
|
||||
private Queue<ByteString> storage = new LinkedList<ByteString>();
|
||||
|
||||
private boolean suspended = false;
|
||||
|
||||
private static class Ack implements Event {
|
||||
public final int ack;
|
||||
public Ack(int ack) {
|
||||
|
|
@ -45,6 +51,8 @@ public class EchoHandler extends UntypedActor {
|
|||
public EchoHandler(ActorRef connection, InetSocketAddress remote) {
|
||||
this.connection = connection;
|
||||
this.remote = remote;
|
||||
|
||||
writing = writing();
|
||||
|
||||
// sign death pact: this actor stops when the connection is closed
|
||||
getContext().watch(connection);
|
||||
|
|
@ -52,138 +60,136 @@ public class EchoHandler extends UntypedActor {
|
|||
// start out in optimistic write-through mode
|
||||
getContext().become(writing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Receive createReceive() {
|
||||
return writing;
|
||||
}
|
||||
|
||||
private final Procedure<Object> writing = new Procedure<Object>() {
|
||||
@Override
|
||||
public void apply(Object msg) throws Exception {
|
||||
if (msg instanceof Received) {
|
||||
final ByteString data = ((Received) msg).data();
|
||||
connection.tell(TcpMessage.write(data, new Ack(currentOffset())), getSelf());
|
||||
private final Receive writing;
|
||||
|
||||
private Receive writing() {
|
||||
return receiveBuilder()
|
||||
.match(Received.class, msg -> {
|
||||
final ByteString data = msg.data();
|
||||
connection.tell(TcpMessage.write(data, new Ack(currentOffset())), self());
|
||||
buffer(data);
|
||||
|
||||
} else if (msg instanceof Integer) {
|
||||
acknowledge((Integer) msg);
|
||||
|
||||
} else if (msg instanceof CommandFailed) {
|
||||
final Write w = (Write) ((CommandFailed) msg).cmd();
|
||||
connection.tell(TcpMessage.resumeWriting(), getSelf());
|
||||
})
|
||||
.match(Integer.class, msg -> {
|
||||
acknowledge(msg);
|
||||
})
|
||||
.match(CommandFailed.class, msg -> {
|
||||
final Write w = (Write) msg.cmd();
|
||||
connection.tell(TcpMessage.resumeWriting(), self());
|
||||
getContext().become(buffering((Ack) w.ack()));
|
||||
|
||||
} else if (msg instanceof ConnectionClosed) {
|
||||
final ConnectionClosed cl = (ConnectionClosed) msg;
|
||||
if (cl.isPeerClosed()) {
|
||||
})
|
||||
.match(ConnectionClosed.class, msg -> {
|
||||
if (msg.isPeerClosed()) {
|
||||
if (storage.isEmpty()) {
|
||||
getContext().stop(getSelf());
|
||||
getContext().stop(self());
|
||||
} else {
|
||||
getContext().become(closing);
|
||||
getContext().become(closing());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
//#buffering
|
||||
protected Procedure<Object> buffering(final Ack nack) {
|
||||
return new Procedure<Object>() {
|
||||
|
||||
final static class BufferingState {
|
||||
int toAck = 10;
|
||||
boolean peerClosed = false;
|
||||
}
|
||||
|
||||
protected Receive buffering(final Ack nack) {
|
||||
final BufferingState state = new BufferingState();
|
||||
|
||||
return receiveBuilder()
|
||||
.match(Received.class, msg -> {
|
||||
buffer(msg.data());
|
||||
|
||||
private int toAck = 10;
|
||||
private boolean peerClosed = false;
|
||||
})
|
||||
.match(WritingResumed.class, msg -> {
|
||||
writeFirst();
|
||||
|
||||
@Override
|
||||
public void apply(Object msg) throws Exception {
|
||||
if (msg instanceof Received) {
|
||||
buffer(((Received) msg).data());
|
||||
})
|
||||
.match(ConnectionClosed.class, msg -> {
|
||||
if (msg.isPeerClosed())
|
||||
state.peerClosed = true;
|
||||
else
|
||||
getContext().stop(self());
|
||||
|
||||
} else if (msg instanceof WritingResumed) {
|
||||
writeFirst();
|
||||
})
|
||||
.match(Integer.class, ack -> {
|
||||
acknowledge(ack);
|
||||
|
||||
} else if (msg instanceof ConnectionClosed) {
|
||||
if (((ConnectionClosed) msg).isPeerClosed())
|
||||
peerClosed = true;
|
||||
else
|
||||
getContext().stop(getSelf());
|
||||
if (ack >= nack.ack) {
|
||||
// otherwise it was the ack of the last successful write
|
||||
|
||||
} else if (msg instanceof Integer) {
|
||||
final int ack = (Integer) msg;
|
||||
acknowledge(ack);
|
||||
if (storage.isEmpty()) {
|
||||
if (state.peerClosed)
|
||||
getContext().stop(self());
|
||||
else
|
||||
getContext().become(writing);
|
||||
|
||||
if (ack >= nack.ack) {
|
||||
// otherwise it was the ack of the last successful write
|
||||
|
||||
if (storage.isEmpty()) {
|
||||
if (peerClosed)
|
||||
getContext().stop(getSelf());
|
||||
} else {
|
||||
if (state.toAck > 0) {
|
||||
// stay in ACK-based mode for a short while
|
||||
writeFirst();
|
||||
--state.toAck;
|
||||
} else {
|
||||
// then return to NACK-based again
|
||||
writeAll();
|
||||
if (state.peerClosed)
|
||||
getContext().become(closing());
|
||||
else
|
||||
getContext().become(writing);
|
||||
|
||||
} else {
|
||||
if (toAck > 0) {
|
||||
// stay in ACK-based mode for a short while
|
||||
writeFirst();
|
||||
--toAck;
|
||||
} else {
|
||||
// then return to NACK-based again
|
||||
writeAll();
|
||||
if (peerClosed)
|
||||
getContext().become(closing);
|
||||
else
|
||||
getContext().become(writing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
.build();
|
||||
}
|
||||
//#buffering
|
||||
|
||||
//#closing
|
||||
protected Procedure<Object> closing = new Procedure<Object>() {
|
||||
@Override
|
||||
public void apply(Object msg) throws Exception {
|
||||
if (msg instanceof CommandFailed) {
|
||||
protected Receive closing() {
|
||||
return receiveBuilder()
|
||||
.match(CommandFailed.class, msg -> {
|
||||
// the command can only have been a Write
|
||||
connection.tell(TcpMessage.resumeWriting(), getSelf());
|
||||
getContext().become(closeResend, false);
|
||||
} else if (msg instanceof Integer) {
|
||||
acknowledge((Integer) msg);
|
||||
connection.tell(TcpMessage.resumeWriting(), self());
|
||||
getContext().become(closeResend(), false);
|
||||
})
|
||||
.match(Integer.class, msg -> {
|
||||
acknowledge(msg);
|
||||
if (storage.isEmpty())
|
||||
getContext().stop(getSelf());
|
||||
}
|
||||
}
|
||||
};
|
||||
getContext().stop(self());
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
protected Procedure<Object> closeResend = new Procedure<Object>() {
|
||||
@Override
|
||||
public void apply(Object msg) throws Exception {
|
||||
if (msg instanceof WritingResumed) {
|
||||
protected Receive closeResend() {
|
||||
return receiveBuilder()
|
||||
.match(WritingResumed.class, msg -> {
|
||||
writeAll();
|
||||
getContext().unbecome();
|
||||
} else if (msg instanceof Integer) {
|
||||
acknowledge((Integer) msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
.match(Integer.class, msg -> {
|
||||
acknowledge(msg);
|
||||
})
|
||||
.build();
|
||||
}
|
||||
//#closing
|
||||
|
||||
//#storage-omitted
|
||||
@Override
|
||||
public void onReceive(Object msg) throws Exception {
|
||||
// this method is not used due to become()
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postStop() {
|
||||
log.info("transferred {} bytes from/to [{}]", transferred, remote);
|
||||
}
|
||||
|
||||
private long transferred;
|
||||
private int storageOffset = 0;
|
||||
private long stored = 0;
|
||||
private Queue<ByteString> storage = new LinkedList<ByteString>();
|
||||
|
||||
private boolean suspended = false;
|
||||
|
||||
//#helpers
|
||||
protected void buffer(ByteString data) {
|
||||
storage.add(data);
|
||||
|
|
@ -191,11 +197,11 @@ public class EchoHandler extends UntypedActor {
|
|||
|
||||
if (stored > MAX_STORED) {
|
||||
log.warning("drop connection to [{}] (buffer overrun)", remote);
|
||||
getContext().stop(getSelf());
|
||||
getContext().stop(self());
|
||||
|
||||
} else if (stored > HIGH_WATERMARK) {
|
||||
log.debug("suspending reading at {}", currentOffset());
|
||||
connection.tell(TcpMessage.suspendReading(), getSelf());
|
||||
connection.tell(TcpMessage.suspendReading(), self());
|
||||
suspended = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -211,7 +217,7 @@ public class EchoHandler extends UntypedActor {
|
|||
|
||||
if (suspended && stored < LOW_WATERMARK) {
|
||||
log.debug("resuming reading");
|
||||
connection.tell(TcpMessage.resumeReading(), getSelf());
|
||||
connection.tell(TcpMessage.resumeReading(), self());
|
||||
suspended = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -224,12 +230,12 @@ public class EchoHandler extends UntypedActor {
|
|||
protected void writeAll() {
|
||||
int i = 0;
|
||||
for (ByteString data : storage) {
|
||||
connection.tell(TcpMessage.write(data, new Ack(storageOffset + i++)), getSelf());
|
||||
connection.tell(TcpMessage.write(data, new Ack(storageOffset + i++)), self());
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeFirst() {
|
||||
connection.tell(TcpMessage.write(storage.peek(), new Ack(storageOffset)), getSelf());
|
||||
connection.tell(TcpMessage.write(storage.peek(), new Ack(storageOffset)), self());
|
||||
}
|
||||
|
||||
//#storage-omitted
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import java.net.InetSocketAddress;
|
|||
import akka.actor.ActorRef;
|
||||
import akka.actor.Props;
|
||||
import akka.actor.SupervisorStrategy;
|
||||
import akka.actor.UntypedActor;
|
||||
import akka.actor.AbstractActor;
|
||||
import akka.event.Logging;
|
||||
import akka.event.LoggingAdapter;
|
||||
import akka.io.Tcp;
|
||||
|
|
@ -19,10 +19,10 @@ import akka.io.Tcp.CommandFailed;
|
|||
import akka.io.Tcp.Connected;
|
||||
import akka.io.TcpMessage;
|
||||
|
||||
public class EchoManager extends UntypedActor {
|
||||
public class EchoManager extends AbstractActor {
|
||||
|
||||
final LoggingAdapter log = Logging
|
||||
.getLogger(getContext().system(), getSelf());
|
||||
.getLogger(getContext().system(), self());
|
||||
|
||||
final Class<?> handlerClass;
|
||||
|
||||
|
|
@ -41,41 +41,42 @@ public class EchoManager extends UntypedActor {
|
|||
final ActorRef tcpManager = Tcp.get(getContext().system()).manager();
|
||||
//#manager
|
||||
tcpManager.tell(
|
||||
TcpMessage.bind(getSelf(), new InetSocketAddress("localhost", 0), 100),
|
||||
getSelf());
|
||||
TcpMessage.bind(self(), new InetSocketAddress("localhost", 0), 100),
|
||||
self());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postRestart(Throwable arg0) throws Exception {
|
||||
// do not restart
|
||||
getContext().stop(getSelf());
|
||||
getContext().stop(self());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Object msg) throws Exception {
|
||||
if (msg instanceof Bound) {
|
||||
log.info("listening on [{}]", ((Bound) msg).localAddress());
|
||||
} else if (msg instanceof Tcp.CommandFailed) {
|
||||
final CommandFailed failed = (CommandFailed) msg;
|
||||
if (failed.cmd() instanceof Bind) {
|
||||
log.warning("cannot bind to [{}]", ((Bind) failed.cmd()).localAddress());
|
||||
getContext().stop(getSelf());
|
||||
} else {
|
||||
log.warning("unknown command failed [{}]", failed.cmd());
|
||||
}
|
||||
} else
|
||||
if (msg instanceof Connected) {
|
||||
final Connected conn = (Connected) msg;
|
||||
log.info("received connection from [{}]", conn.remoteAddress());
|
||||
final ActorRef connection = getSender();
|
||||
final ActorRef handler = getContext().actorOf(
|
||||
Props.create(handlerClass, connection, conn.remoteAddress()));
|
||||
//#echo-manager
|
||||
connection.tell(TcpMessage.register(handler,
|
||||
true, // <-- keepOpenOnPeerClosed flag
|
||||
true), getSelf());
|
||||
//#echo-manager
|
||||
}
|
||||
public Receive createReceive() {
|
||||
return receiveBuilder()
|
||||
.match(Bound.class, msg -> {
|
||||
log.info("listening on [{}]", msg.localAddress());
|
||||
})
|
||||
.match(Tcp.CommandFailed.class, failed -> {
|
||||
if (failed.cmd() instanceof Bind) {
|
||||
log.warning("cannot bind to [{}]", ((Bind) failed.cmd()).localAddress());
|
||||
getContext().stop(self());
|
||||
} else {
|
||||
log.warning("unknown command failed [{}]", failed.cmd());
|
||||
}
|
||||
})
|
||||
.match(Connected.class, conn -> {
|
||||
log.info("received connection from [{}]", conn.remoteAddress());
|
||||
final ActorRef connection = sender();
|
||||
final ActorRef handler = getContext().actorOf(
|
||||
Props.create(handlerClass, connection, conn.remoteAddress()));
|
||||
//#echo-manager
|
||||
connection.tell(TcpMessage.register(handler,
|
||||
true, // <-- keepOpenOnPeerClosed flag
|
||||
true), self());
|
||||
//#echo-manager
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import java.net.InetSocketAddress;
|
|||
import akka.actor.ActorRef;
|
||||
import akka.actor.ActorSystem;
|
||||
import akka.actor.Props;
|
||||
import akka.actor.UntypedActor;
|
||||
import akka.actor.AbstractActor;
|
||||
import akka.io.Tcp;
|
||||
import akka.io.Tcp.Bound;
|
||||
import akka.io.Tcp.CommandFailed;
|
||||
|
|
@ -34,7 +34,7 @@ public class IODocTest extends AbstractJavaTest {
|
|||
|
||||
static
|
||||
//#server
|
||||
public class Server extends UntypedActor {
|
||||
public class Server extends AbstractActor {
|
||||
|
||||
final ActorRef manager;
|
||||
|
||||
|
|
@ -49,25 +49,28 @@ public class IODocTest extends AbstractJavaTest {
|
|||
@Override
|
||||
public void preStart() throws Exception {
|
||||
final ActorRef tcp = Tcp.get(getContext().system()).manager();
|
||||
tcp.tell(TcpMessage.bind(getSelf(),
|
||||
new InetSocketAddress("localhost", 0), 100), getSelf());
|
||||
tcp.tell(TcpMessage.bind(self(),
|
||||
new InetSocketAddress("localhost", 0), 100), self());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Object msg) throws Exception {
|
||||
if (msg instanceof Bound) {
|
||||
manager.tell(msg, getSelf());
|
||||
|
||||
} else if (msg instanceof CommandFailed) {
|
||||
getContext().stop(getSelf());
|
||||
|
||||
} else if (msg instanceof Connected) {
|
||||
final Connected conn = (Connected) msg;
|
||||
manager.tell(conn, getSelf());
|
||||
final ActorRef handler = getContext().actorOf(
|
||||
Props.create(SimplisticHandler.class));
|
||||
getSender().tell(TcpMessage.register(handler), getSelf());
|
||||
}
|
||||
public Receive createReceive() {
|
||||
return receiveBuilder()
|
||||
.match(Bound.class, msg -> {
|
||||
manager.tell(msg, self());
|
||||
|
||||
})
|
||||
.match(CommandFailed.class, msg -> {
|
||||
getContext().stop(self());
|
||||
|
||||
})
|
||||
.match(Connected.class, conn -> {
|
||||
manager.tell(conn, self());
|
||||
final ActorRef handler = getContext().actorOf(
|
||||
Props.create(SimplisticHandler.class));
|
||||
sender().tell(TcpMessage.register(handler), self());
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -75,23 +78,26 @@ public class IODocTest extends AbstractJavaTest {
|
|||
|
||||
static
|
||||
//#simplistic-handler
|
||||
public class SimplisticHandler extends UntypedActor {
|
||||
public class SimplisticHandler extends AbstractActor {
|
||||
@Override
|
||||
public void onReceive(Object msg) throws Exception {
|
||||
if (msg instanceof Received) {
|
||||
final ByteString data = ((Received) msg).data();
|
||||
System.out.println(data);
|
||||
getSender().tell(TcpMessage.write(data), getSelf());
|
||||
} else if (msg instanceof ConnectionClosed) {
|
||||
getContext().stop(getSelf());
|
||||
}
|
||||
public Receive createReceive() {
|
||||
return receiveBuilder()
|
||||
.match(Received.class, msg -> {
|
||||
final ByteString data = msg.data();
|
||||
System.out.println(data);
|
||||
sender().tell(TcpMessage.write(data), self());
|
||||
})
|
||||
.match(ConnectionClosed.class, msg -> {
|
||||
getContext().stop(self());
|
||||
})
|
||||
.build();
|
||||
}
|
||||
}
|
||||
//#simplistic-handler
|
||||
|
||||
static
|
||||
//#client
|
||||
public class Client extends UntypedActor {
|
||||
public class Client extends AbstractActor {
|
||||
|
||||
final InetSocketAddress remote;
|
||||
final ActorRef listener;
|
||||
|
|
@ -105,44 +111,43 @@ public class IODocTest extends AbstractJavaTest {
|
|||
this.listener = listener;
|
||||
|
||||
final ActorRef tcp = Tcp.get(getContext().system()).manager();
|
||||
tcp.tell(TcpMessage.connect(remote), getSelf());
|
||||
tcp.tell(TcpMessage.connect(remote), self());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Object msg) throws Exception {
|
||||
if (msg instanceof CommandFailed) {
|
||||
listener.tell("failed", getSelf());
|
||||
getContext().stop(getSelf());
|
||||
|
||||
} else if (msg instanceof Connected) {
|
||||
listener.tell(msg, getSelf());
|
||||
getSender().tell(TcpMessage.register(getSelf()), getSelf());
|
||||
getContext().become(connected(getSender()));
|
||||
}
|
||||
public Receive createReceive() {
|
||||
return receiveBuilder()
|
||||
.match(CommandFailed.class, msg -> {
|
||||
listener.tell("failed", self());
|
||||
getContext().stop(self());
|
||||
|
||||
})
|
||||
.match(Connected.class, msg -> {
|
||||
listener.tell(msg, self());
|
||||
sender().tell(TcpMessage.register(self()), self());
|
||||
getContext().become(connected(sender()));
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
private Procedure<Object> connected(final ActorRef connection) {
|
||||
return new Procedure<Object>() {
|
||||
@Override
|
||||
public void apply(Object msg) throws Exception {
|
||||
|
||||
if (msg instanceof ByteString) {
|
||||
connection.tell(TcpMessage.write((ByteString) msg), getSelf());
|
||||
|
||||
} else if (msg instanceof CommandFailed) {
|
||||
// OS kernel socket buffer was full
|
||||
|
||||
} else if (msg instanceof Received) {
|
||||
listener.tell(((Received) msg).data(), getSelf());
|
||||
|
||||
} else if (msg.equals("close")) {
|
||||
connection.tell(TcpMessage.close(), getSelf());
|
||||
|
||||
} else if (msg instanceof ConnectionClosed) {
|
||||
getContext().stop(getSelf());
|
||||
}
|
||||
}
|
||||
};
|
||||
private Receive connected(final ActorRef connection) {
|
||||
return receiveBuilder()
|
||||
.match(ByteString.class, msg -> {
|
||||
connection.tell(TcpMessage.write((ByteString) msg), self());
|
||||
})
|
||||
.match(CommandFailed.class, msg -> {
|
||||
// OS kernel socket buffer was full
|
||||
})
|
||||
.match(Received.class, msg -> {
|
||||
listener.tell(msg.data(), self());
|
||||
})
|
||||
.matchEquals("close", msg -> {
|
||||
connection.tell(TcpMessage.close(), self());
|
||||
})
|
||||
.match(ConnectionClosed.class, msg -> {
|
||||
getContext().stop(self());
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import java.util.LinkedList;
|
|||
import java.util.Queue;
|
||||
|
||||
import akka.actor.ActorRef;
|
||||
import akka.actor.UntypedActor;
|
||||
import akka.actor.AbstractActor;
|
||||
import akka.event.Logging;
|
||||
import akka.event.LoggingAdapter;
|
||||
import akka.io.Tcp.ConnectionClosed;
|
||||
|
|
@ -20,10 +20,10 @@ import akka.japi.Procedure;
|
|||
import akka.util.ByteString;
|
||||
|
||||
//#simple-echo-handler
|
||||
public class SimpleEchoHandler extends UntypedActor {
|
||||
public class SimpleEchoHandler extends AbstractActor {
|
||||
|
||||
final LoggingAdapter log = Logging
|
||||
.getLogger(getContext().system(), getSelf());
|
||||
.getLogger(getContext().system(), self());
|
||||
|
||||
final ActorRef connection;
|
||||
final InetSocketAddress remote;
|
||||
|
|
@ -41,38 +41,42 @@ public class SimpleEchoHandler extends UntypedActor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Object msg) throws Exception {
|
||||
if (msg instanceof Received) {
|
||||
final ByteString data = ((Received) msg).data();
|
||||
buffer(data);
|
||||
connection.tell(TcpMessage.write(data, ACK), getSelf());
|
||||
// now switch behavior to “waiting for acknowledgement”
|
||||
getContext().become(buffering, false);
|
||||
|
||||
} else if (msg instanceof ConnectionClosed) {
|
||||
getContext().stop(getSelf());
|
||||
}
|
||||
public Receive createReceive() {
|
||||
return receiveBuilder()
|
||||
.match(Received.class, msg -> {
|
||||
final ByteString data = msg.data();
|
||||
buffer(data);
|
||||
connection.tell(TcpMessage.write(data, ACK), self());
|
||||
// now switch behavior to “waiting for acknowledgement”
|
||||
getContext().become(buffering(), false);
|
||||
|
||||
})
|
||||
.match(ConnectionClosed.class, msg -> {
|
||||
getContext().stop(self());
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
private final Procedure<Object> buffering = new Procedure<Object>() {
|
||||
@Override
|
||||
public void apply(Object msg) throws Exception {
|
||||
if (msg instanceof Received) {
|
||||
buffer(((Received) msg).data());
|
||||
private final Receive buffering() {
|
||||
return receiveBuilder()
|
||||
.match(Received.class, msg -> {
|
||||
buffer(msg.data());
|
||||
|
||||
} else if (msg == ACK) {
|
||||
})
|
||||
.match(Event.class, msg -> msg == ACK, msg -> {
|
||||
acknowledge();
|
||||
|
||||
} else if (msg instanceof ConnectionClosed) {
|
||||
if (((ConnectionClosed) msg).isPeerClosed()) {
|
||||
})
|
||||
.match(ConnectionClosed.class, msg -> {
|
||||
if (msg.isPeerClosed()) {
|
||||
closing = true;
|
||||
} else {
|
||||
// could also be ErrorClosed, in which case we just give up
|
||||
getContext().stop(getSelf());
|
||||
getContext().stop(self());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
//#storage-omitted
|
||||
public void postStop() {
|
||||
|
|
@ -95,11 +99,11 @@ public class SimpleEchoHandler extends UntypedActor {
|
|||
|
||||
if (stored > maxStored) {
|
||||
log.warning("drop connection to [{}] (buffer overrun)", remote);
|
||||
getContext().stop(getSelf());
|
||||
getContext().stop(self());
|
||||
|
||||
} else if (stored > highWatermark) {
|
||||
log.debug("suspending reading");
|
||||
connection.tell(TcpMessage.suspendReading(), getSelf());
|
||||
connection.tell(TcpMessage.suspendReading(), self());
|
||||
suspended = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -111,18 +115,18 @@ public class SimpleEchoHandler extends UntypedActor {
|
|||
|
||||
if (suspended && stored < lowWatermark) {
|
||||
log.debug("resuming reading");
|
||||
connection.tell(TcpMessage.resumeReading(), getSelf());
|
||||
connection.tell(TcpMessage.resumeReading(), self());
|
||||
suspended = false;
|
||||
}
|
||||
|
||||
if (storage.isEmpty()) {
|
||||
if (closing) {
|
||||
getContext().stop(getSelf());
|
||||
getContext().stop(self());
|
||||
} else {
|
||||
getContext().unbecome();
|
||||
}
|
||||
} else {
|
||||
connection.tell(TcpMessage.write(storage.peek(), ACK), getSelf());
|
||||
connection.tell(TcpMessage.write(storage.peek(), ACK), self());
|
||||
}
|
||||
}
|
||||
//#simple-helpers
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ import java.util.concurrent.CountDownLatch;
|
|||
|
||||
import akka.actor.ActorRef;
|
||||
import akka.actor.Terminated;
|
||||
import akka.actor.UntypedActor;
|
||||
import akka.actor.AbstractActor;
|
||||
|
||||
public class Watcher extends UntypedActor {
|
||||
public class Watcher extends AbstractActor {
|
||||
|
||||
static public class Watch {
|
||||
final ActorRef target;
|
||||
|
|
@ -22,13 +22,16 @@ public class Watcher extends UntypedActor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Object msg) throws Exception {
|
||||
if (msg instanceof Watch) {
|
||||
getContext().watch(((Watch) msg).target);
|
||||
} else if (msg instanceof Terminated) {
|
||||
latch.countDown();
|
||||
if (latch.getCount() == 0) getContext().stop(getSelf());
|
||||
}
|
||||
public Receive createReceive() {
|
||||
return receiveBuilder()
|
||||
.match(Watch.class, msg -> {
|
||||
getContext().watch(msg.target);
|
||||
})
|
||||
.match(Terminated.class, msg -> {
|
||||
latch.countDown();
|
||||
if (latch.getCount() == 0) getContext().stop(self());
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue