All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sandinh.seed.ClusterLeaveAwait.scala Maven / Gradle / Ivy

package com.sandinh.seed

import scala.concurrent.{Await, CanAwait, Awaitable}
import java.util.concurrent.{TimeoutException, CountDownLatch}
import scala.concurrent.duration.Duration
import akka.actor.{Props, ActorSystem, ActorLogging, Actor}
import akka.cluster.ClusterEvent.{InitialStateAsEvents, MemberRemoved}
import akka.cluster.Cluster

object ClusterLeaveAwait extends Awaitable[Unit] {
  private val latch = new CountDownLatch(1)

  private[seed] def countDown(): Unit = latch.countDown()

  def ready(atMost: Duration)(implicit permit: CanAwait): this.type = {
    if (atMost.isFinite()) {
      if (!latch.await(atMost.length, atMost.unit))
        throw new TimeoutException("Await termination timed out after [%s]" format atMost.toString)
    } else latch.await()

    this
  }

  def result(atMost: Duration)(implicit permit: CanAwait): Unit = ready(atMost)

  def awaitLeave(system: ActorSystem, atMost: Duration = Duration.Inf): Unit = {
    val cluster = Cluster(system)
    val trackingActor = system.actorOf(Props[ClusterTracking])
    cluster.subscribe(trackingActor, InitialStateAsEvents, classOf[MemberRemoved])
    cluster.leave(cluster.selfAddress)
    Await.ready(this, atMost)
  }
}

private class ClusterTracking extends Actor with ActorLogging {
  override def receive = {
    case MemberRemoved(member, _) =>
      log.debug("{} is leaving", member.address)
      if (member.address == Cluster(context.system).selfAddress)
        ClusterLeaveAwait.countDown()
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy