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

com.crobox.clickhouse.balancing.discovery.cluster.ClusterConnectionProviderActor.scala Maven / Gradle / Ivy

The newest version!
package com.crobox.clickhouse.balancing.discovery.cluster

import akka.actor.{Actor, ActorLogging, ActorRef, Props}
import akka.pattern.{ask, pipe}
import akka.stream.ActorMaterializer
import akka.util.Timeout
import akka.util.Timeout.durationToTimeout
import com.crobox.clickhouse.balancing.discovery.ConnectionManagerActor.Connections
import com.crobox.clickhouse.balancing.discovery.cluster.ClusterConnectionProviderActor.ScanHosts
import com.crobox.clickhouse.discovery.ConnectionConfig
import com.crobox.clickhouse.internal.ClickhouseHostBuilder
import com.crobox.clickhouse.internal.InternalExecutorActor.Execute

import scala.concurrent.Future
import scala.concurrent.duration._
import scala.util.{Failure, Success}

class ClusterConnectionProviderActor(manager: ActorRef, executor: ActorRef) extends Actor with ActorLogging {
  require(manager != null, "Manager has to be provided")
  require(executor != null, "Executor has to be provided")

  private implicit val timeout: Timeout                = durationToTimeout(5 second)
  private implicit val materialzier: ActorMaterializer = ActorMaterializer()

  import context.dispatcher

  override def receive = {
    case ScanHosts(config) =>
      val eventualConnections = resolveHosts(config)
      eventualConnections.onComplete {
        case Success(connection) => log.debug(s"Got successful connections $connection")
        case Failure(ex)         => log.error(ex, "Exception while getting connections")
      }
      eventualConnections pipeTo manager
  }

  def resolveHosts(config: ConnectionConfig): Future[Connections] =
    (executor ? Execute(config.host, s"SELECT host_address FROM system.clusters WHERE cluster='${config.cluster}'"))
      .mapTo[Seq[String]]
      .map(_.toSet)
      .map(result => {
        if (result.isEmpty) {
          throw new IllegalArgumentException(
            s"Could not determine clickhouse cluster hosts from $config. " +
            s"This could indicate that you are trying to use the cluster balancer to connect to a non cluster based clickhouse server. " +
            s"Please use the `SingleHostQueryBalancer` in that case."
          )
        }
        Connections(result.map(ClickhouseHostBuilder.toHost(_, Some(8123))))
      })
}

object ClusterConnectionProviderActor {

  case class ScanHosts(config: ConnectionConfig)

  def props(manager: ActorRef, executor: ActorRef) =
    Props(new ClusterConnectionProviderActor(manager, executor))
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy