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

ru.primetalk.synapse.akka.distributed.RealmDescriptor.scala Maven / Gradle / Ivy

The newest version!
///////////////////////////////////////////////////////////////
// © ООО «Праймтолк», 2014                                   //
// Все права принадлежат компании ООО «Праймтолк».           //
///////////////////////////////////////////////////////////////
/**
 * SynapseGrid
 * © Primetalk Ltd., 2014.
 * All rights reserved.
 * Authors: A.Zhizhelev
 *
 * Created: 07.06.14, zhizhelev
 */
package ru.primetalk.synapse.akka.distributed

import ru.primetalk.synapse.core
import akka.actor.{SupervisorStrategy, Props, ActorRefFactory, ActorPath}
import ru.primetalk.synapse.akka._
import ru.primetalk.synapse.akka.ActorComponent
import ru.primetalk.synapse.core.components.{Component, ComponentWithInternalStructure}

/**
Deployment of a system over a cluster of nodes
 ----------------------------------------------
 The realm knows about other hosts and
 the deployment of systems over all the hosts.
  */
case class RealmDescriptor(topLevelSystem: ComponentWithInternalStructure, deployment: Vector[(List[core.SystemPath], ActorPath)]) {
  /** Looks up for the systemPath in the deployment descriptor
    * and constructs an appropriate ActorPath for it. */
  def getRouterPath(systemPath: core.SystemPath): ActorPath = {
    val hosts = deployment.filter(_._1.contains(systemPath)).map(_._2)
    if (hosts.size != 1)
      throw new IllegalStateException(s"For path=$systemPath found != 1 hosts.")
    hosts.head / systemPathToActorName(systemPath)
  }

  /** Looks up for the systemPath in the deployment descriptor
    * and constructs an appropriate ActorPath for it. */
  def getSystemImplPath(systemPath: core.SystemPath): ActorPath = {
    val hosts = deployment.filter(_._1.contains(systemPath)).map(_._2)
    if (hosts.size != 1)
      throw new IllegalStateException(s"For path=$systemPath found != 1 hosts.")
    hosts.head / ("subsystem_" + systemPathToActorName(systemPath))
  }

  /** List paths of systems that should be created at this host. */
  def pathsForHost(host: ActorPath) =
    deployment.filter(_._2 == host).flatMap(_._1).toSet

  private
  def systemPathToActorName(path: core.SystemPath) =
    path.mkString("_")

  /**
   * Creates all routers for the system.
   * @param s the system to create routers
   * @return collection of SystemPath -> ActorRef - routers for every InnerActorSubsystem.
   */
  def createRouters(s: Component)(context: ActorRefFactory) =
    actorInnerSubsystems2(s).map(_._1).map {
      path =>
        val actorName = systemPathToActorName(path)
        //        log.info("router " + actorName + " for " + path)
        (path, context.actorOf(Props[RouterBecome], actorName))
    }

  /** Recursively finds all subsystems of the system. */
  def actorInnerSubsystems(component: Component): List[(core.SystemPathReversed, ActorComponent)] =
    core.subcomponents(component).collect { case (pathRev, actorInnerSubsystem: ActorComponent) => (pathRev, actorInnerSubsystem)}

  def actorInnerSubsystems2(component: Component): List[(core.SystemPath, ActorComponent)] =
    actorInnerSubsystems(component).map(p => (p._1.reverse, p._2))


  /** Creates subsystem actors for the given top level StaticSystem and
    * the set of paths that belongs to this host.
    *
    * The subsystems send signals to other actors via router actors that should have been
    * created. */
  def createSubsystems(s: Component,
                       pathsForThisHost: Set[core.SystemPath])(context: ActorRefFactory,
                                                               supervisorStrategy: SupervisorStrategy =
                                                               defaultSupervisorStrategy,
                                                               outputFun: Option[InternalSignalsDist => Any] = None, realm: RealmDescriptor) = {
    for {
      (path, actorSubsystem) <- actorInnerSubsystems2(s)
      if pathsForThisHost.contains(path) // we construct only those subsystems that should be instantiated at this host
      subsystem = actorSubsystem.subsystem
      actorName = "subsystem_" + systemPathToActorName(path)
    } yield
      context.actorOf(Props(new ActorForSystemOneLevel(path, subsystem, supervisorStrategy, realm)), actorName)
  }

}

/**
 * Identifier of a host.
 * "akka.tcp://[email protected]:2552/user/actorName"
 * The host is an actor that is responsible for creation and recreation of the system in the particular host.
 */
final case class HostId(host: String, port: Int, actorSystemName: String, hostActorName: String = "synapse") {
  override
  def toString = s"akka.tcp://$actorSystemName@$host:$port/user/$hostActorName"

  def toActorPath =
    ActorPath.fromString(toString)
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy