Giter Site home page Giter Site logo

zio-pekko-cluster's Introduction

ZIO Pekko Cluster

build Current Version license

The ZIO Pekko Cluster library is a ZIO wrapper on Pekko Cluster. It is a fork of ZIO Akka Cluster providing the same functionality for Apache Pekko. We can use clustering features of the Pekko toolkit without the need to use the actor model.

Introduction

This library provides us following features:

  • Pekko Cluster โ€” This feature contains two Pekko Cluster Membership operations called join and leave and also it has some methods to retrieve Cluster State and Cluster Events.

  • Pekko Distributed PubSub โ€” Pekko has a Distributed Publish Subscribe facility in the cluster. It helps us to send a message to all actors in the cluster that have registered and subscribed for a specific topic name without knowing their physical address or without knowing which node they are running on.

  • Pekko Cluster Sharding โ€” Cluster sharding is useful when we need to distribute actors across several nodes in the cluster and want to be able to interact with them using their logical identifier without having to care about their physical location in the cluster, which might also change over time. When we have many stateful entities in our application that together they consume more resources (e.g. memory) than fit on one machine, it is useful to use Pekko Cluster Sharding to distribute our entities to multiple nodes.

Installation

In order to use this library, we need to add the following line in our build.sbt file:

libraryDependencies += "nl.gn0s1s" %% "zio-pekko-cluster" % "0.2.0"

Example

In the following example, we are using all these three features. We have a distributed counter application that lives in the Pkeko Cluster using Pekko Cluster Sharding feature. So the location of LiveUsers and TotalRequests entities in the cluster is transparent for us. We send the result of each entity to the Distributed PubSub. So every node in the cluster can subscribe and listen to those results. Also, we have created a fiber that is subscribed to the cluster events. All the new events will be logged to the console:

import org.apache.pekko.actor.ActorSystem
import com.typesafe.config.{ Config, ConfigFactory }
import zio._
import zio.pekko.cluster.Cluster
import zio.pekko.cluster.sharding.{ Entity, Sharding }

sealed trait Counter extends Product with Serializable
case object Inc      extends Counter
case object Dec      extends Counter

case class CounterApp(port: String) {
  val config: Config =
    ConfigFactory.parseString(s"""
                                 |pekko {
                                 |  actor {
                                 |    provider = "cluster"
                                 |  }
                                 |  remote {
                                 |    enabled-transports = ["pekko.remote.artery.canonical"]
                                 |    artery.canonical {
                                 |      hostname = "127.0.0.1"
                                 |      port = $port
                                 |    }
                                 |  }
                                 |  cluster {
                                 |    seed-nodes = ["pekko.tcp://[email protected]:$port"]
                                 |    downing-provider-class = "org.apache.pekko.cluster.sbr.SplitBrainResolverProvider"
                                 |  }
                                 |}
                                 |""".stripMargin)

  val actorSystem: ZLayer[Any, Nothing, ActorSystem] =
    ZLayer.scoped(
      ZIO.acquireRelease(ZIO.succeed(ActorSystem("CounterApp", config)))(sys =>
        ZIO.fromFuture(_ => sys.terminate()).either
      )
    )

  val counterApp: ZIO[Scope, Throwable, Unit] =
    (for {
      queue              <- Cluster.clusterEvents(true)
      pubsub             <- zio.pekko.cluster.pubsub.PubSub.createPubSub[Int]
      liveUsersLogger    <- pubsub
        .listen("LiveUsers")
        .flatMap(
          _.take.tap(u => Console.printLine(s"Number of live users: $u")).forever
        )
        .fork
      totalRequestLogger <- pubsub
        .listen("TotalRequests")
        .flatMap(
          _.take.tap(r => Console.printLine(s"Total request until now: $r")).forever
        )
        .fork

      clusterEvents      <- queue.take
        .tap(x => Console.printLine("New event in cluster: " + x.toString))
        .forever
        .fork

      counterEntityLogic  = (c: Counter) =>
        for {
          entity   <- ZIO.environment[Entity[Int]]
          newState <- c match {
            case Inc =>
              entity.get.state.updateAndGet(s => Some(s.getOrElse(0) + 1))
            case Dec =>
              entity.get.state.updateAndGet(s => Some(s.getOrElse(0) - 1))
          }
          _        <- pubsub.publish(entity.get.id, newState.getOrElse(0)).orDie
        } yield ()
      cluster            <- Sharding.start("CounterEntity", counterEntityLogic)

      _ <- cluster.send("LiveUsers", Inc)
      _ <- cluster.send("TotalRequests", Inc)
      _ <- cluster.send("LiveUsers", Dec)
      _ <- cluster.send("LiveUsers", Inc)
      _ <- cluster.send("LiveUsers", Inc)
      _ <- cluster.send("TotalRequests", Inc)
      _ <- cluster.send("TotalRequests", Inc)

      _ <- clusterEvents.join zipPar liveUsersLogger.join zipPar totalRequestLogger.join
    } yield ()).provide(actorSystem)
}

Now, let's create a cluster comprising two nodes:

object CounterApp1 extends ZIOAppDefault {
  override def run = CounterApp("2551").counterApp
}

object CounterApp2 extends ZIOAppDefault {
  override def run = CounterApp("2552").counterApp
}

Documentation

Learn more on the ZIO Pekko Cluster homepage!

Contributing

For the general guidelines, see ZIO contributor's guide.

Code of Conduct

See the Code of Conduct

License

License

zio-pekko-cluster's People

Contributors

adamgfraser avatar calvinlfer avatar ghostdogpr avatar jopecko avatar justcoon avatar khajavi avatar kubukoz avatar mijicd avatar octavz avatar philippus avatar scala-steward avatar softinio avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

Forkers

scala-steward

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.