Publish cluster changes to event bus, see #2202

* ClusterEventBus
* Removed register listener and related
* Removed Gossip.meta because it doesn't handle version conflicts
This commit is contained in:
Patrik Nordwall 2012-08-14 10:58:30 +02:00
parent 9094199011
commit e38dd80f38
14 changed files with 209 additions and 159 deletions

View file

@ -16,6 +16,8 @@ import scala.concurrent.Await
import scala.concurrent.util.Duration
import java.util.concurrent.TimeUnit
import akka.remote.testconductor.RoleName
import akka.actor.Props
import akka.actor.Actor
object LargeClusterMultiJvmSpec extends MultiNodeConfig {
// each jvm simulates a datacenter with many nodes
@ -78,6 +80,7 @@ abstract class LargeClusterSpec
with MultiNodeClusterSpec {
import LargeClusterMultiJvmSpec._
import ClusterEvent._
var systems: IndexedSeq[ActorSystem] = IndexedSeq(system)
val nodesPerDatacenter = system.settings.config.getInt(
@ -143,15 +146,16 @@ abstract class LargeClusterSpec
val latch = TestLatch(clusterNodes.size)
clusterNodes foreach { c
c.registerListener(new MembershipChangeListener {
override def notify(members: SortedSet[Member]): Unit = {
if (!latch.isOpen && members.size == totalNodes && members.forall(_.status == MemberStatus.Up)) {
log.debug("All [{}] nodes Up in [{}], it took [{}], received [{}] gossip messages",
totalNodes, c.selfAddress, tookMillis, gossipCount(c))
latch.countDown()
}
c.subscribe(system.actorOf(Props(new Actor {
def receive = {
case MembersChanged(members)
if (!latch.isOpen && members.size == totalNodes && members.forall(_.status == MemberStatus.Up)) {
log.debug("All [{}] nodes Up in [{}], it took [{}], received [{}] gossip messages",
totalNodes, c.selfAddress, tookMillis, gossipCount(c))
latch.countDown()
}
}
})
})), classOf[MembersChanged])
}
runOn(from) {
@ -271,15 +275,16 @@ abstract class LargeClusterSpec
val latch = TestLatch(nodesPerDatacenter)
systems foreach { sys
Cluster(sys).registerListener(new MembershipChangeListener {
override def notify(members: SortedSet[Member]): Unit = {
if (!latch.isOpen && members.size == liveNodes && Cluster(sys).latestGossip.overview.unreachable.size == unreachableNodes) {
log.info("Detected [{}] unreachable nodes in [{}], it took [{}], received [{}] gossip messages",
unreachableNodes, Cluster(sys).selfAddress, tookMillis, gossipCount(Cluster(sys)))
latch.countDown()
}
Cluster(sys).subscribe(sys.actorOf(Props(new Actor {
def receive = {
case MembersChanged(members)
if (!latch.isOpen && members.size == liveNodes && Cluster(sys).latestGossip.overview.unreachable.size == unreachableNodes) {
log.info("Detected [{}] unreachable nodes in [{}], it took [{}], received [{}] gossip messages",
unreachableNodes, Cluster(sys).selfAddress, tookMillis, gossipCount(Cluster(sys)))
latch.countDown()
}
}
})
})), classOf[MembersChanged])
}
runOn(firstDatacenter) {

View file

@ -9,6 +9,8 @@ import akka.remote.testkit.MultiNodeConfig
import akka.remote.testkit.MultiNodeSpec
import akka.testkit._
import scala.concurrent.util.duration._
import akka.actor.Props
import akka.actor.Actor
object LeaderLeavingMultiJvmSpec extends MultiNodeConfig {
val first = role("first")
@ -32,6 +34,7 @@ abstract class LeaderLeavingSpec
with MultiNodeClusterSpec {
import LeaderLeavingMultiJvmSpec._
import ClusterEvent._
val leaderHandoffWaitingTime = 30.seconds
@ -66,15 +69,16 @@ abstract class LeaderLeavingSpec
val leavingLatch = TestLatch()
val exitingLatch = TestLatch()
val expectedAddresses = roles.toSet map address
cluster.registerListener(new MembershipChangeListener {
def notify(members: SortedSet[Member]) {
def check(status: MemberStatus): Boolean =
(members.map(_.address) == expectedAddresses &&
members.exists(m m.address == oldLeaderAddress && m.status == status))
if (check(MemberStatus.Leaving)) leavingLatch.countDown()
if (check(MemberStatus.Exiting)) exitingLatch.countDown()
cluster.subscribe(system.actorOf(Props(new Actor {
def receive = {
case MembersChanged(members)
def check(status: MemberStatus): Boolean =
(members.map(_.address) == expectedAddresses &&
members.exists(m m.address == oldLeaderAddress && m.status == status))
if (check(MemberStatus.Leaving)) leavingLatch.countDown()
if (check(MemberStatus.Exiting)) exitingLatch.countDown()
}
})
})), classOf[MembersChanged])
enterBarrier("registered-listener")
enterBarrier("leader-left")

View file

@ -10,6 +10,8 @@ import akka.remote.testkit.MultiNodeConfig
import akka.remote.testkit.MultiNodeSpec
import akka.testkit._
import scala.concurrent.util.duration._
import akka.actor.Props
import akka.actor.Actor
object MembershipChangeListenerExitingMultiJvmSpec extends MultiNodeConfig {
val first = role("first")
@ -36,6 +38,7 @@ abstract class MembershipChangeListenerExitingSpec
with MultiNodeClusterSpec {
import MembershipChangeListenerExitingMultiJvmSpec._
import ClusterEvent._
"A registered MembershipChangeListener" must {
"be notified when new node is EXITING" taggedAs LongRunningTest in {
@ -53,12 +56,13 @@ abstract class MembershipChangeListenerExitingSpec
runOn(third) {
val exitingLatch = TestLatch()
cluster.registerListener(new MembershipChangeListener {
def notify(members: SortedSet[Member]) {
if (members.size == 3 && members.exists(m m.address == address(second) && m.status == MemberStatus.Exiting))
exitingLatch.countDown()
cluster.subscribe(system.actorOf(Props(new Actor {
def receive = {
case MembersChanged(members)
if (members.size == 3 && members.exists(m m.address == address(second) && m.status == MemberStatus.Exiting))
exitingLatch.countDown()
}
})
})), classOf[MembersChanged])
enterBarrier("registered-listener")
exitingLatch.await
}

View file

@ -10,6 +10,8 @@ import akka.remote.testkit.MultiNodeConfig
import akka.remote.testkit.MultiNodeSpec
import akka.testkit._
import scala.concurrent.util.duration._
import akka.actor.Props
import akka.actor.Actor
object MembershipChangeListenerJoinMultiJvmSpec extends MultiNodeConfig {
val first = role("first")
@ -29,6 +31,7 @@ abstract class MembershipChangeListenerJoinSpec
with MultiNodeClusterSpec {
import MembershipChangeListenerJoinMultiJvmSpec._
import ClusterEvent._
"A registered MembershipChangeListener" must {
"be notified when new node is JOINING" taggedAs LongRunningTest in {
@ -36,12 +39,13 @@ abstract class MembershipChangeListenerJoinSpec
runOn(first) {
val joinLatch = TestLatch()
val expectedAddresses = Set(first, second) map address
cluster.registerListener(new MembershipChangeListener {
def notify(members: SortedSet[Member]) {
if (members.map(_.address) == expectedAddresses && members.exists(_.status == MemberStatus.Joining))
joinLatch.countDown()
cluster.subscribe(system.actorOf(Props(new Actor {
def receive = {
case MembersChanged(members)
if (members.map(_.address) == expectedAddresses && members.exists(_.status == MemberStatus.Joining))
joinLatch.countDown()
}
})
})), classOf[MembersChanged])
enterBarrier("registered-listener")
joinLatch.await

View file

@ -10,6 +10,8 @@ import akka.remote.testkit.MultiNodeConfig
import akka.remote.testkit.MultiNodeSpec
import akka.testkit._
import akka.actor.Address
import akka.actor.Props
import akka.actor.Actor
object MembershipChangeListenerLeavingMultiJvmSpec extends MultiNodeConfig {
val first = role("first")
@ -34,6 +36,7 @@ abstract class MembershipChangeListenerLeavingSpec
with MultiNodeClusterSpec {
import MembershipChangeListenerLeavingMultiJvmSpec._
import ClusterEvent._
"A registered MembershipChangeListener" must {
"be notified when new node is LEAVING" taggedAs LongRunningTest in {
@ -52,13 +55,14 @@ abstract class MembershipChangeListenerLeavingSpec
runOn(third) {
val latch = TestLatch()
val expectedAddresses = Set(first, second, third) map address
cluster.registerListener(new MembershipChangeListener {
def notify(members: SortedSet[Member]) {
if (members.map(_.address) == expectedAddresses &&
members.exists(m m.address == address(second) && m.status == MemberStatus.Leaving))
latch.countDown()
cluster.subscribe(system.actorOf(Props(new Actor {
def receive = {
case MembersChanged(members)
if (members.map(_.address) == expectedAddresses &&
members.exists(m m.address == address(second) && m.status == MemberStatus.Leaving))
latch.countDown()
}
})
})), classOf[MembersChanged])
enterBarrier("registered-listener")
latch.await
}

View file

@ -8,6 +8,8 @@ import com.typesafe.config.ConfigFactory
import akka.remote.testkit.MultiNodeConfig
import akka.remote.testkit.MultiNodeSpec
import akka.testkit._
import akka.actor.Props
import akka.actor.Actor
object MembershipChangeListenerUpMultiJvmSpec extends MultiNodeConfig {
val first = role("first")
@ -26,6 +28,7 @@ abstract class MembershipChangeListenerUpSpec
with MultiNodeClusterSpec {
import MembershipChangeListenerUpMultiJvmSpec._
import ClusterEvent._
"A set of connected cluster systems" must {
@ -36,12 +39,13 @@ abstract class MembershipChangeListenerUpSpec
runOn(first, second) {
val latch = TestLatch()
val expectedAddresses = Set(first, second) map address
cluster.registerListener(new MembershipChangeListener {
def notify(members: SortedSet[Member]) {
if (members.map(_.address) == expectedAddresses && members.forall(_.status == MemberStatus.Up))
latch.countDown()
cluster.subscribe(system.actorOf(Props(new Actor {
def receive = {
case MembersChanged(members)
if (members.map(_.address) == expectedAddresses && members.forall(_.status == MemberStatus.Up))
latch.countDown()
}
})
})), classOf[MembersChanged])
enterBarrier("listener-1-registered")
cluster.join(first)
latch.await
@ -58,12 +62,13 @@ abstract class MembershipChangeListenerUpSpec
val latch = TestLatch()
val expectedAddresses = Set(first, second, third) map address
cluster.registerListener(new MembershipChangeListener {
def notify(members: SortedSet[Member]) {
if (members.map(_.address) == expectedAddresses && members.forall(_.status == MemberStatus.Up))
latch.countDown()
cluster.subscribe(system.actorOf(Props(new Actor {
def receive = {
case MembersChanged(members)
if (members.map(_.address) == expectedAddresses && members.forall(_.status == MemberStatus.Up))
latch.countDown()
}
})
})), classOf[MembersChanged])
enterBarrier("listener-2-registered")
runOn(third) {

View file

@ -9,6 +9,8 @@ import akka.remote.testkit.MultiNodeConfig
import akka.remote.testkit.MultiNodeSpec
import akka.testkit._
import scala.concurrent.util.duration._
import akka.actor.Props
import akka.actor.Actor
object NodeLeavingAndExitingMultiJvmSpec extends MultiNodeConfig {
val first = role("first")
@ -32,6 +34,7 @@ abstract class NodeLeavingAndExitingSpec
with MultiNodeClusterSpec {
import NodeLeavingAndExitingMultiJvmSpec._
import ClusterEvent._
"A node that is LEAVING a non-singleton cluster" must {
@ -44,15 +47,16 @@ abstract class NodeLeavingAndExitingSpec
val leavingLatch = TestLatch()
val exitingLatch = TestLatch()
val expectedAddresses = roles.toSet map address
cluster.registerListener(new MembershipChangeListener {
def notify(members: SortedSet[Member]) {
def check(status: MemberStatus): Boolean =
(members.map(_.address) == expectedAddresses &&
members.exists(m m.address == secondAddess && m.status == status))
if (check(MemberStatus.Leaving)) leavingLatch.countDown()
if (check(MemberStatus.Exiting)) exitingLatch.countDown()
cluster.subscribe(system.actorOf(Props(new Actor {
def receive = {
case MembersChanged(members)
def check(status: MemberStatus): Boolean =
(members.map(_.address) == expectedAddresses &&
members.exists(m m.address == secondAddess && m.status == status))
if (check(MemberStatus.Leaving)) leavingLatch.countDown()
if (check(MemberStatus.Exiting)) exitingLatch.countDown()
}
})
})), classOf[MembersChanged])
enterBarrier("registered-listener")
runOn(third) {

View file

@ -11,6 +11,8 @@ import akka.testkit._
import scala.concurrent.util.duration._
import scala.collection.immutable.SortedSet
import java.util.concurrent.atomic.AtomicReference
import akka.actor.Props
import akka.actor.Actor
object NodeUpMultiJvmSpec extends MultiNodeConfig {
val first = role("first")
@ -27,6 +29,7 @@ abstract class NodeUpSpec
with MultiNodeClusterSpec {
import NodeUpMultiJvmSpec._
import ClusterEvent._
"A cluster node that is joining another cluster" must {
"be moved to UP by the leader after a convergence" taggedAs LongRunningTest in {
@ -39,12 +42,13 @@ abstract class NodeUpSpec
"be unaffected when joining again" taggedAs LongRunningTest in {
val unexpected = new AtomicReference[SortedSet[Member]](SortedSet.empty)
cluster.registerListener(new MembershipChangeListener {
def notify(members: SortedSet[Member]) {
if (members.size != 2 || members.exists(_.status != MemberStatus.Up))
unexpected.set(members)
cluster.subscribe(system.actorOf(Props(new Actor {
def receive = {
case MembersChanged(members)
if (members.size != 2 || members.exists(_.status != MemberStatus.Up))
unexpected.set(members)
}
})
})), classOf[MembersChanged])
enterBarrier("listener-registered")
runOn(second) {

View file

@ -11,6 +11,8 @@ import akka.testkit._
import scala.concurrent.util.duration._
import java.util.concurrent.atomic.AtomicReference
import scala.collection.immutable.SortedSet
import akka.actor.Props
import akka.actor.Actor
object SunnyWeatherMultiJvmSpec extends MultiNodeConfig {
val first = role("first")
@ -40,6 +42,7 @@ abstract class SunnyWeatherSpec
with MultiNodeClusterSpec {
import SunnyWeatherMultiJvmSpec._
import ClusterEvent._
"A normal cluster" must {
"be healthy" taggedAs LongRunningTest in {
@ -55,12 +58,13 @@ abstract class SunnyWeatherSpec
log.info("5 joined")
val unexpected = new AtomicReference[SortedSet[Member]]
cluster.registerListener(new MembershipChangeListener {
def notify(members: SortedSet[Member]) {
// we don't expected any changes to the cluster
unexpected.set(members)
cluster.subscribe(system.actorOf(Props(new Actor {
def receive = {
case MembersChanged(members)
// we don't expected any changes to the cluster
unexpected.set(members)
}
})
})), classOf[MembersChanged])
for (n 1 to 30) {
enterBarrier("period-" + n)