2018-10-29 17:19:37 +08:00
|
|
|
/*
|
2019-01-02 18:55:26 +08:00
|
|
|
* Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
|
2015-06-30 16:22:33 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package akka.cluster.client;
|
|
|
|
|
|
2016-05-04 04:50:16 -07:00
|
|
|
import akka.actor.*;
|
2015-06-30 16:22:33 +02:00
|
|
|
import com.typesafe.config.ConfigFactory;
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
import java.util.Set;
|
|
|
|
|
import org.junit.ClassRule;
|
|
|
|
|
import org.junit.Test;
|
|
|
|
|
|
|
|
|
|
import akka.testkit.AkkaJUnitActorSystemResource;
|
2016-04-06 01:23:21 +02:00
|
|
|
import org.scalatest.junit.JUnitSuite;
|
2015-06-30 16:22:33 +02:00
|
|
|
|
2016-04-06 01:23:21 +02:00
|
|
|
public class ClusterClientTest extends JUnitSuite {
|
2015-06-30 16:22:33 +02:00
|
|
|
|
|
|
|
|
@ClassRule
|
|
|
|
|
public static AkkaJUnitActorSystemResource actorSystemResource =
|
2019-01-12 04:00:53 +08:00
|
|
|
new AkkaJUnitActorSystemResource(
|
|
|
|
|
"DistributedPubSubMediatorTest",
|
|
|
|
|
ConfigFactory.parseString(
|
|
|
|
|
"akka.actor.provider = \"cluster\"\n"
|
|
|
|
|
+ "akka.remote.netty.tcp.port=0\n"
|
|
|
|
|
+ "akka.remote.artery.canonical.port=0"));
|
2015-06-30 16:22:33 +02:00
|
|
|
|
|
|
|
|
private final ActorSystem system = actorSystemResource.getSystem();
|
|
|
|
|
|
2019-01-12 04:00:53 +08:00
|
|
|
// #initialContacts
|
2015-06-30 16:22:33 +02:00
|
|
|
Set<ActorPath> initialContacts() {
|
2019-01-12 04:00:53 +08:00
|
|
|
return new HashSet<ActorPath>(
|
|
|
|
|
Arrays.asList(
|
|
|
|
|
ActorPaths.fromString("akka.tcp://OtherSys@host1:2552/system/receptionist"),
|
|
|
|
|
ActorPaths.fromString("akka.tcp://OtherSys@host2:2552/system/receptionist")));
|
2015-06-30 16:22:33 +02:00
|
|
|
}
|
2019-01-12 04:00:53 +08:00
|
|
|
// #initialContacts
|
2015-06-30 16:22:33 +02:00
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void demonstrateUsage() {
|
2019-01-12 04:00:53 +08:00
|
|
|
// #server
|
2015-06-30 16:22:33 +02:00
|
|
|
ActorRef serviceA = system.actorOf(Props.create(Service.class), "serviceA");
|
|
|
|
|
ClusterClientReceptionist.get(system).registerService(serviceA);
|
|
|
|
|
|
|
|
|
|
ActorRef serviceB = system.actorOf(Props.create(Service.class), "serviceB");
|
|
|
|
|
ClusterClientReceptionist.get(system).registerService(serviceB);
|
2019-01-12 04:00:53 +08:00
|
|
|
// #server
|
|
|
|
|
|
|
|
|
|
// #client
|
|
|
|
|
final ActorRef c =
|
|
|
|
|
system.actorOf(
|
|
|
|
|
ClusterClient.props(
|
|
|
|
|
ClusterClientSettings.create(system).withInitialContacts(initialContacts())),
|
|
|
|
|
"client");
|
2015-06-30 16:22:33 +02:00
|
|
|
c.tell(new ClusterClient.Send("/user/serviceA", "hello", true), ActorRef.noSender());
|
|
|
|
|
c.tell(new ClusterClient.SendToAll("/user/serviceB", "hi"), ActorRef.noSender());
|
2019-01-12 04:00:53 +08:00
|
|
|
// #client
|
2016-05-04 04:50:16 -07:00
|
|
|
|
|
|
|
|
system.actorOf(Props.create(ClientListener.class, c));
|
2019-01-12 04:00:53 +08:00
|
|
|
system.actorOf(
|
|
|
|
|
Props.create(
|
|
|
|
|
ReceptionistListener.class, ClusterClientReceptionist.get(system).underlying()));
|
2015-06-30 16:22:33 +02:00
|
|
|
}
|
|
|
|
|
|
2019-01-12 04:00:53 +08:00
|
|
|
public static class Service extends UntypedAbstractActor {
|
|
|
|
|
public void onReceive(Object msg) {}
|
2015-06-30 16:22:33 +02:00
|
|
|
}
|
2016-05-04 04:50:16 -07:00
|
|
|
|
2019-01-12 04:00:53 +08:00
|
|
|
// #clientEventsListener
|
|
|
|
|
public static class ClientListener extends AbstractActor {
|
2016-05-04 04:50:16 -07:00
|
|
|
private final ActorRef targetClient;
|
|
|
|
|
private final Set<ActorPath> contactPoints = new HashSet<>();
|
|
|
|
|
|
|
|
|
|
public ClientListener(ActorRef targetClient) {
|
|
|
|
|
this.targetClient = targetClient;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void preStart() {
|
|
|
|
|
targetClient.tell(SubscribeContactPoints.getInstance(), sender());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
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
2016-12-13 10:59:29 +01:00
|
|
|
public Receive createReceive() {
|
|
|
|
|
return receiveBuilder()
|
2019-01-12 04:00:53 +08:00
|
|
|
.match(
|
|
|
|
|
ContactPoints.class,
|
|
|
|
|
msg -> {
|
|
|
|
|
contactPoints.addAll(msg.getContactPoints());
|
|
|
|
|
// Now do something with an up-to-date "contactPoints"
|
|
|
|
|
})
|
|
|
|
|
.match(
|
|
|
|
|
ContactPointAdded.class,
|
|
|
|
|
msg -> {
|
|
|
|
|
contactPoints.add(msg.contactPoint());
|
|
|
|
|
// Now do something with an up-to-date "contactPoints"
|
|
|
|
|
})
|
|
|
|
|
.match(
|
|
|
|
|
ContactPointRemoved.class,
|
|
|
|
|
msg -> {
|
|
|
|
|
contactPoints.remove(msg.contactPoint());
|
|
|
|
|
// Now do something with an up-to-date "contactPoints"
|
|
|
|
|
})
|
|
|
|
|
.build();
|
2016-05-04 04:50:16 -07:00
|
|
|
}
|
|
|
|
|
}
|
2019-01-12 04:00:53 +08:00
|
|
|
// #clientEventsListener
|
2016-05-04 04:50:16 -07:00
|
|
|
|
2019-01-12 04:00:53 +08:00
|
|
|
// #receptionistEventsListener
|
|
|
|
|
public static class ReceptionistListener extends AbstractActor {
|
2016-05-04 04:50:16 -07:00
|
|
|
private final ActorRef targetReceptionist;
|
|
|
|
|
private final Set<ActorRef> clusterClients = new HashSet<>();
|
|
|
|
|
|
|
|
|
|
public ReceptionistListener(ActorRef targetReceptionist) {
|
|
|
|
|
this.targetReceptionist = targetReceptionist;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void preStart() {
|
|
|
|
|
targetReceptionist.tell(SubscribeClusterClients.getInstance(), sender());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
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
2016-12-13 10:59:29 +01:00
|
|
|
public Receive createReceive() {
|
|
|
|
|
return receiveBuilder()
|
2019-01-12 04:00:53 +08:00
|
|
|
.match(
|
|
|
|
|
ClusterClients.class,
|
|
|
|
|
msg -> {
|
|
|
|
|
clusterClients.addAll(msg.getClusterClients());
|
|
|
|
|
// Now do something with an up-to-date "clusterClients"
|
|
|
|
|
})
|
|
|
|
|
.match(
|
|
|
|
|
ClusterClientUp.class,
|
|
|
|
|
msg -> {
|
|
|
|
|
clusterClients.add(msg.clusterClient());
|
|
|
|
|
// Now do something with an up-to-date "clusterClients"
|
|
|
|
|
})
|
|
|
|
|
.match(
|
|
|
|
|
ClusterClientUnreachable.class,
|
|
|
|
|
msg -> {
|
|
|
|
|
clusterClients.remove(msg.clusterClient());
|
|
|
|
|
// Now do something with an up-to-date "clusterClients"
|
|
|
|
|
})
|
|
|
|
|
.build();
|
2016-05-04 04:50:16 -07:00
|
|
|
}
|
|
|
|
|
}
|
2019-01-12 04:00:53 +08:00
|
|
|
// #receptionistEventsListener
|
2016-05-04 04:50:16 -07:00
|
|
|
|
2015-06-30 16:22:33 +02:00
|
|
|
}
|