Add UID to RemoteActorRef, see #3072
* Sending to a previous incarnation of an actor shall fail, to make remote actors work the same way as local ones (in the sense that after Terminated() the ref is not working anymore) * Changed equality of ActorRef to take the uid into account * Parse uid fragment in RelativeActorPath and ActorPathExtractor * Handle uid in getChild and in RemoteSystemDaemon * Use toSerializationFormat and toSerializationFormatWithAddress in serialization * Replaced var uid in ActorCell and ChildRestartStats with constructor parameters (path) * Create the uid in one single place, in makeChild in parent * Handle ActorRef with and without uid in DeathWatch * Optimize ActorPath.toString and friends * Update documentation and migration guide
This commit is contained in:
parent
eb10fac787
commit
b738487dc8
37 changed files with 607 additions and 186 deletions
|
|
@ -119,14 +119,14 @@ class RemotingSpec extends AkkaSpec(RemotingSpec.cfg) with ImplicitSender with D
|
|||
test.local-address = "test://remote-sys@localhost:12346"
|
||||
}
|
||||
""").withFallback(system.settings.config).resolve()
|
||||
val other = ActorSystem("remote-sys", conf)
|
||||
val otherSystem = ActorSystem("remote-sys", conf)
|
||||
|
||||
for (
|
||||
(name, proto) ← Seq(
|
||||
"/gonk" -> "tcp",
|
||||
"/zagzag" -> "udp",
|
||||
"/roghtaar" -> "ssl.tcp")
|
||||
) deploy(system, Deploy(name, scope = RemoteScope(addr(other, proto))))
|
||||
) deploy(system, Deploy(name, scope = RemoteScope(addr(otherSystem, proto))))
|
||||
|
||||
def addr(sys: ActorSystem, proto: String) =
|
||||
sys.asInstanceOf[ExtendedActorSystem].provider.getExternalAddressFor(Address(s"akka.$proto", "", "", 0)).get
|
||||
|
|
@ -135,12 +135,12 @@ class RemotingSpec extends AkkaSpec(RemotingSpec.cfg) with ImplicitSender with D
|
|||
sys.asInstanceOf[ExtendedActorSystem].provider.asInstanceOf[RemoteActorRefProvider].deployer.deploy(d)
|
||||
}
|
||||
|
||||
val remote = other.actorOf(Props[Echo2], "echo")
|
||||
val remote = otherSystem.actorOf(Props[Echo2], "echo")
|
||||
|
||||
val here = system.actorFor("akka.test://remote-sys@localhost:12346/user/echo")
|
||||
|
||||
override def afterTermination() {
|
||||
other.shutdown()
|
||||
otherSystem.shutdown()
|
||||
AssociationRegistry.clear()
|
||||
}
|
||||
|
||||
|
|
@ -168,16 +168,16 @@ class RemotingSpec extends AkkaSpec(RemotingSpec.cfg) with ImplicitSender with D
|
|||
"send dead letters on remote if actor does not exist" in {
|
||||
EventFilter.warning(pattern = "dead.*buh", occurrences = 1).intercept {
|
||||
system.actorFor("akka.test://remote-sys@localhost:12346/does/not/exist") ! "buh"
|
||||
}(other)
|
||||
}(otherSystem)
|
||||
}
|
||||
|
||||
"not be exhausted by sending to broken connections" in {
|
||||
val tcpOnlyConfig = ConfigFactory.parseString("""akka.remote.enabled-transports = ["akka.remote.netty.tcp"]""").
|
||||
withFallback(other.settings.config)
|
||||
val moreSystems = Vector.fill(5)(ActorSystem(other.name, tcpOnlyConfig))
|
||||
withFallback(otherSystem.settings.config)
|
||||
val moreSystems = Vector.fill(5)(ActorSystem(otherSystem.name, tcpOnlyConfig))
|
||||
moreSystems foreach (_.actorOf(Props[Echo2], name = "echo"))
|
||||
val moreRefs = moreSystems map (sys ⇒ system.actorFor(RootActorPath(addr(sys, "tcp")) / "user" / "echo"))
|
||||
val aliveEcho = system.actorFor(RootActorPath(addr(other, "tcp")) / "user" / "echo")
|
||||
val aliveEcho = system.actorFor(RootActorPath(addr(otherSystem, "tcp")) / "user" / "echo")
|
||||
val n = 100
|
||||
|
||||
// first everything is up and running
|
||||
|
|
@ -223,6 +223,30 @@ class RemotingSpec extends AkkaSpec(RemotingSpec.cfg) with ImplicitSender with D
|
|||
expectMsg("postStop")
|
||||
}
|
||||
|
||||
"not send to remote re-created actor with same name" in {
|
||||
val echo = otherSystem.actorOf(Props[Echo1], "otherEcho1")
|
||||
echo ! 71
|
||||
expectMsg(71)
|
||||
echo ! PoisonPill
|
||||
expectMsg("postStop")
|
||||
echo ! 72
|
||||
expectNoMsg(1.second)
|
||||
|
||||
val echo2 = otherSystem.actorOf(Props[Echo1], "otherEcho1")
|
||||
echo2 ! 73
|
||||
expectMsg(73)
|
||||
// msg to old ActorRef (different uid) should not get through
|
||||
echo2.path.uid must not be (echo.path.uid)
|
||||
echo ! 74
|
||||
expectNoMsg(1.second)
|
||||
|
||||
otherSystem.actorFor("/user/otherEcho1") ! 75
|
||||
expectMsg(75)
|
||||
|
||||
system.actorFor("akka.test://remote-sys@localhost:12346/user/otherEcho1") ! 76
|
||||
expectMsg(76)
|
||||
}
|
||||
|
||||
"look-up actors across node boundaries" in {
|
||||
val l = system.actorOf(Props(new Actor {
|
||||
def receive = {
|
||||
|
|
@ -230,20 +254,41 @@ class RemotingSpec extends AkkaSpec(RemotingSpec.cfg) with ImplicitSender with D
|
|||
case s: String ⇒ sender ! context.actorFor(s)
|
||||
}
|
||||
}), "looker")
|
||||
// child is configured to be deployed on remote-sys (otherSystem)
|
||||
l ! (Props[Echo1], "child")
|
||||
val r = expectMsgType[ActorRef]
|
||||
r ! (Props[Echo1], "grandchild")
|
||||
val remref = expectMsgType[ActorRef]
|
||||
remref.asInstanceOf[ActorRefScope].isLocal must be(true)
|
||||
val child = expectMsgType[ActorRef]
|
||||
// grandchild is configured to be deployed on RemotingSpec (system)
|
||||
child ! (Props[Echo1], "grandchild")
|
||||
val grandchild = expectMsgType[ActorRef]
|
||||
grandchild.asInstanceOf[ActorRefScope].isLocal must be(true)
|
||||
grandchild ! 43
|
||||
expectMsg(43)
|
||||
val myref = system.actorFor(system / "looker" / "child" / "grandchild")
|
||||
myref.isInstanceOf[RemoteActorRef] must be(true)
|
||||
myref ! 43
|
||||
expectMsg(43)
|
||||
lastSender must be theSameInstanceAs remref
|
||||
r.asInstanceOf[RemoteActorRef].getParent must be(l)
|
||||
system.actorFor("/user/looker/child") must be theSameInstanceAs r
|
||||
myref ! 44
|
||||
expectMsg(44)
|
||||
lastSender must be(grandchild)
|
||||
lastSender must be theSameInstanceAs grandchild
|
||||
child.asInstanceOf[RemoteActorRef].getParent must be(l)
|
||||
system.actorFor("/user/looker/child") must be theSameInstanceAs child
|
||||
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
|
||||
|
||||
watch(child)
|
||||
child ! PoisonPill
|
||||
expectMsg("postStop")
|
||||
expectMsgType[Terminated].actor must be === child
|
||||
l ! (Props[Echo1], "child")
|
||||
val child2 = expectMsgType[ActorRef]
|
||||
child2 ! 45
|
||||
expectMsg(45)
|
||||
// msg to old ActorRef (different uid) should not get through
|
||||
child2.path.uid must not be (child.path.uid)
|
||||
child ! 46
|
||||
expectNoMsg(1.second)
|
||||
system.actorFor(system / "looker" / "child") ! 47
|
||||
expectMsg(47)
|
||||
|
||||
}
|
||||
|
||||
"not fail ask across node boundaries" in {
|
||||
|
|
@ -255,7 +300,7 @@ class RemotingSpec extends AkkaSpec(RemotingSpec.cfg) with ImplicitSender with D
|
|||
"be able to use multiple transports and use the appropriate one (TCP)" in {
|
||||
val r = system.actorOf(Props[Echo1], "gonk")
|
||||
r.path.toString must be ===
|
||||
s"akka.tcp://remote-sys@localhost:${port(other, "tcp")}/remote/akka.tcp/RemotingSpec@localhost:${port(system, "tcp")}/user/gonk"
|
||||
s"akka.tcp://remote-sys@localhost:${port(otherSystem, "tcp")}/remote/akka.tcp/RemotingSpec@localhost:${port(system, "tcp")}/user/gonk"
|
||||
r ! 42
|
||||
expectMsg(42)
|
||||
EventFilter[Exception]("crash", occurrences = 1).intercept {
|
||||
|
|
@ -271,7 +316,7 @@ class RemotingSpec extends AkkaSpec(RemotingSpec.cfg) with ImplicitSender with D
|
|||
"be able to use multiple transports and use the appropriate one (UDP)" in {
|
||||
val r = system.actorOf(Props[Echo1], "zagzag")
|
||||
r.path.toString must be ===
|
||||
s"akka.udp://remote-sys@localhost:${port(other, "udp")}/remote/akka.udp/RemotingSpec@localhost:${port(system, "udp")}/user/zagzag"
|
||||
s"akka.udp://remote-sys@localhost:${port(otherSystem, "udp")}/remote/akka.udp/RemotingSpec@localhost:${port(system, "udp")}/user/zagzag"
|
||||
r ! 42
|
||||
expectMsg(10.seconds, 42)
|
||||
EventFilter[Exception]("crash", occurrences = 1).intercept {
|
||||
|
|
@ -287,7 +332,7 @@ class RemotingSpec extends AkkaSpec(RemotingSpec.cfg) with ImplicitSender with D
|
|||
"be able to use multiple transports and use the appropriate one (SSL)" in {
|
||||
val r = system.actorOf(Props[Echo1], "roghtaar")
|
||||
r.path.toString must be ===
|
||||
s"akka.ssl.tcp://remote-sys@localhost:${port(other, "ssl.tcp")}/remote/akka.ssl.tcp/RemotingSpec@localhost:${port(system, "ssl.tcp")}/user/roghtaar"
|
||||
s"akka.ssl.tcp://remote-sys@localhost:${port(otherSystem, "ssl.tcp")}/remote/akka.ssl.tcp/RemotingSpec@localhost:${port(system, "ssl.tcp")}/user/roghtaar"
|
||||
r ! 42
|
||||
expectMsg(10.seconds, 42)
|
||||
EventFilter[Exception]("crash", occurrences = 1).intercept {
|
||||
|
|
@ -305,7 +350,7 @@ class RemotingSpec extends AkkaSpec(RemotingSpec.cfg) with ImplicitSender with D
|
|||
override def beforeTermination() {
|
||||
system.eventStream.publish(TestEvent.Mute(
|
||||
EventFilter.warning(pattern = "received dead letter.*(InboundPayload|Disassociate)")))
|
||||
other.eventStream.publish(TestEvent.Mute(
|
||||
otherSystem.eventStream.publish(TestEvent.Mute(
|
||||
EventFilter[EndpointException](),
|
||||
EventFilter.error(start = "AssociationError"),
|
||||
EventFilter.warning(pattern = "received dead letter.*(InboundPayload|Disassociate|HandleListener)")))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue