akka.actor.typed.scaladsl.ActorContext Scala Examples

The following examples show how to use akka.actor.typed.scaladsl.ActorContext. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: PingPong.scala    From effpi   with MIT License 5 votes vote down vote up
// Effpi - verified message-passing programs in Dotty
// Copyright 2019 Alceste Scalas and Elias Benussi
// Released under the MIT License: https://opensource.org/licenses/MIT
package effpi.benchmarks.akka

import akka.NotUsed
import akka.actor.typed.scaladsl.{ Behaviors, MutableBehavior, ActorContext}
import akka.actor.typed.{ ActorRef, ActorSystem, Behavior, DispatcherSelector, Terminated }
import scala.concurrent.Future
import scala.concurrent.duration._
import scala.concurrent.{ Future, Promise, Await }
import scala.concurrent.ExecutionContext.Implicits.global

object PingPong {

  final case class Ping(iterations: Int, replyTo: ActorRef[Pong])

  case class Pong(iterations: Int, pingTo: ActorRef[Ping])

  val pong = Behaviors.receive[Ping] { (ctx, msg) =>
    msg.replyTo ! Pong(msg.iterations - 1, ctx.self)
    Behaviors.same
  }

  def ping(startTimePromise: Promise[Long], endTimePromise: Promise[Long], expectedIterations: Int) = Behaviors.receive[Pong] { (ctx, pong) =>
    if (pong.iterations == 0) {
      endTimePromise.success(System.nanoTime())
      Behaviors.stopped
    } else {
      if (expectedIterations == pong.iterations) {
        startTimePromise.success(System.nanoTime())
      }
      pong.pingTo ! Ping(pong.iterations, ctx.self)
      Behaviors.same
    }
  }

  def mainActor(
    durationPromise: Promise[Long],
    numPairs: Int,
    numIterations: Int
  ): Behavior[akka.NotUsed] =
    Behaviors.setup { ctx =>

      val (startTimePromises, startTimeFutures): (List[Promise[Long]], List[Future[Long]]) = (1 to numPairs).toList.map { _ =>
        val startTimePromise = Promise[Long]()
        val startTimeFuture = startTimePromise.future

        (startTimePromise, startTimeFuture)
      }.unzip

      val (endTimePromises, endTimeFutures): (List[Promise[Long]], List[Future[Long]]) = (1 to numPairs).toList.map { _ =>
        val endTimePromise = Promise[Long]()
        val endTimeFuture = endTimePromise.future

        (endTimePromise, endTimeFuture)
      }.unzip

      // val refs = (1 to numPairs).toList.map { id =>
      val refs = startTimePromises.zip(endTimePromises).zipWithIndex.map { (promises, id) =>
        val (sPromise, ePromise) = promises
        val pongRef = ctx.spawn(pong, "pong" + id)
        val pingRef = ctx.spawn(ping(sPromise, ePromise, numIterations), "ping" + id)
        ctx.watch(pingRef)
        (pingRef, pongRef)
      }
      refs.foreach { (pingRef, pongRef) => pingRef ! Pong(numIterations, pongRef) }

      val startTimes = Await.result(Future.sequence(startTimeFutures), Duration.Inf)
      val startTime = startTimes.min
      val endTimes = Await.result(Future.sequence(endTimeFutures), Duration.Inf)
      val endTime = endTimes.max
      durationPromise.success(endTime - startTime)
      val pingPongDuration = endTime - startTime

      var terminatedProcesses = 0
      Behaviors.receiveSignal {
        case (_, Terminated(ref)) =>
          terminatedProcesses = terminatedProcesses + 1
          if (terminatedProcesses == numPairs) {
            Behaviors.stopped
          } else {
            Behaviors.same
          }
          Behaviors.stopped
        case (_, _) =>
          Behaviors.empty
      }
    }

  def bench(params: (Int, Int)): Long = {
    val (numPairs, numIterations) = params
    val durationPromise = Promise[Long]()
    val durationFuture = durationPromise.future
    val system = ActorSystem(
      mainActor(durationPromise, numPairs, numIterations), "PingPongDemo")
    Await.result(system.whenTerminated, Duration.Inf)
    val duration = Await.result(durationFuture, Duration.Inf)
    duration
  }
} 
Example 2
Source File: PiClusterSingleton.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster



import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorRef, Behavior, PostStop}

object PiClusterSingleton {

  sealed trait Command
  final case object Ping extends Command

  def apply(settings: Settings, clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]): Behavior[Command] = {
    Behaviors.setup { context =>
      new PiClusterSingleton(context, settings, clusterStatusTracker).run()
    }
  }
}

class PiClusterSingleton private (context: ActorContext[PiClusterSingleton.Command],
                         settings: Settings,
                         clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]) {

  import PiClusterSingleton._

  // Cluster singleton has been started on this node
  clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonOnNode

  def run(): Behavior[Command] = Behaviors.receiveMessage[Command] {
    case Ping =>
      context.log.info(s"PiClusterSingleton was pinged")
      Behaviors.same
  }.receiveSignal {
    case (_, signal) if signal == PostStop =>
      clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonNotOnNode
      Behaviors.same
  }

} 
Example 3
Source File: ClusterStatusTrackerMain.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster

import akka.NotUsed
import akka.actor.typed.scaladsl.adapter.TypedActorSystemOps
import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorSystem, Behavior, Terminated}
import akka.management.scaladsl.AkkaManagement

object Main {
  def apply(settings: Settings): Behavior[NotUsed] = Behaviors.setup { context =>
    val ledStripDriver = context.spawn(LedStripDriver(settings), "led-strip-driver")
    val ledStripController = context.spawn(LedStripVisualiser(settings, ledStripDriver), "led-strip-controller")
    val clusterStatusTracker =
      context.spawn(
        ClusterStatusTracker(
          settings,
          Some(contextToClusterSingleton(settings))
        ),
        "cluster-status-tracker"
      )
    clusterStatusTracker ! ClusterStatusTracker.SubscribeVisualiser(ledStripController)
    Behaviors.receiveSignal {
      case (_, Terminated(_)) =>
        Behaviors.stopped
    }
  }

  private def contextToClusterSingleton(settings: Settings): ActorContextToSingletonBehavior  =
    (context: ActorContext[ClusterStatusTracker.ClusterEvent]) => PiClusterSingleton(settings, context.self)

  type ActorContextToSingletonBehavior = ActorContext[ClusterStatusTracker.ClusterEvent] => Behavior[PiClusterSingleton.Command]
}

object ClusterStatusTrackerMain {
  def main(args: Array[String]): Unit = {
    System.loadLibrary("rpi_ws281x")

    val settings = Settings()
    val config = settings.config
    val system = ActorSystem[NotUsed](Main(settings), settings.actorSystemName, config)

    // Start Akka HTTP Management extension
    AkkaManagement(system.toClassic).start()
  }
} 
Example 4
Source File: LedPulser.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster

import akka.actor.typed.scaladsl.{ActorContext, Behaviors, TimerScheduler}
import akka.actor.typed.{ActorRef, Behavior}
import org.neopixel.Neopixel

import scala.concurrent.duration.FiniteDuration

object LedPulser {
  sealed trait Command
  final case class PulseLed(ledNumber: Int,
                            color: Long,
                            flashDuration: FiniteDuration,
                            overRunColor: Option[Long]) extends Command
  private final case class StopPulse(ledNumber: Int) extends Command

  def apply(settings: Settings, ledStripDriver: ActorRef[LedStripDriver.Command]): Behavior[Command] = Behaviors.setup { context =>
    Behaviors.withTimers { timers =>
      new LedPulser(settings, context, timers, ledStripDriver).run(Neopixel.Black)
    }
  }
}

class LedPulser(settings: Settings,
                context: ActorContext[LedPulser.Command],
                timers: TimerScheduler[LedPulser.Command],
                ledStripDriver: ActorRef[LedStripDriver.Command]) {
  import LedPulser._

  def run(currentColor: Long): Behavior[Command] = Behaviors.receiveMessagePartial {
    case PulseLed(ledNumber, color, flashDuration, overRunColor) if color != currentColor =>
      timers.startTimerWithFixedDelay(StopPulse(ledNumber), flashDuration)
      ledStripDriver ! LedStripDriver.SetLedState(ledNumber, color, None)
      run(color)
    case PulseLed(ledNumber, color, flashDuration, overRunColor) =>
      // If the new color is the same as the current color, it implies that
      // the timer is still running. Obviously, no need to update the color
      // on the LED. Running `startTimerWithFixedDelay` will cancel the current
      // timer and start a "fresh" one
      timers.startTimerWithFixedDelay(StopPulse(ledNumber), flashDuration)
      run(color)
    case StopPulse(ledNumber) =>
      ledStripDriver ! LedStripDriver.SetLedState(ledNumber, Neopixel.Black, None)
      run(Neopixel.Black)
  }
} 
Example 5
Source File: PiClusterSingleton.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster



import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorRef, Behavior, PostStop}
import akkapi.cluster.{ClusterStatusTracker, Settings}

object PiClusterSingleton {

  sealed trait Command
  final case object Ping extends Command

  def apply(settings: Settings, clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]): Behavior[Command] = {
    Behaviors.setup { context =>
      new PiClusterSingleton(context, settings, clusterStatusTracker).run()
    }
  }
}

class PiClusterSingleton private (context: ActorContext[PiClusterSingleton.Command],
                         settings: Settings,
                         clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]) {

  import PiClusterSingleton._

  // Cluster singleton has been started on this node
  clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonOnNode

  def run(): Behavior[Command] = Behaviors.receiveMessage[Command] {
    case Ping =>
      context.log.info(s"PiClusterSingleton was pinged")
      Behaviors.same
  }.receiveSignal {
    case (_, signal) if signal == PostStop =>
      clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonNotOnNode
      Behaviors.same
  }

} 
Example 6
Source File: SudokuProgressTracker.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster.sudoku

import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorRef, Behavior}

object SudokuProgressTracker {

  sealed trait Command
  final case class NewUpdatesInFlight(count: Int) extends Command
  final case class SudokuDetailState(index: Int, state: ReductionSet) extends Command
  // My responses
  sealed trait Response
  final case class Result(sudoku: Sudoku) extends Response

  def apply(rowDetailProcessors: Map[Int, ActorRef[SudokuDetailProcessor.Command]],
            sudokuSolver: ActorRef[Response]): Behavior[Command] =
    Behaviors.setup { context =>
      new SudokuProgressTracker(rowDetailProcessors, context, sudokuSolver).trackProgress(updatesInFlight = 0)
    }
}

class SudokuProgressTracker private (rowDetailProcessors: Map[Int, ActorRef[SudokuDetailProcessor.Command]],
                            context: ActorContext[SudokuProgressTracker.Command],
                            sudokuSolver: ActorRef[SudokuProgressTracker.Response]) {

  import SudokuProgressTracker._

  def trackProgress(updatesInFlight: Int): Behavior[Command] = Behaviors.receiveMessagePartial {
    case NewUpdatesInFlight(updateCount) if updatesInFlight - 1 == 0 =>
      rowDetailProcessors.foreach { case (_, processor) => processor ! SudokuDetailProcessor.GetSudokuDetailState(context.self) }
      collectEndState()
    case NewUpdatesInFlight(updateCount) =>
      trackProgress(updatesInFlight + updateCount)
  }

  def collectEndState(remainingRows: Int = 9, endState: Vector[SudokuDetailState] = Vector.empty[SudokuDetailState]): Behavior[Command] =
    Behaviors.receiveMessagePartial {
      case detail @ SudokuDetailState(index, state) if remainingRows == 1 =>
        sudokuSolver ! Result((detail +: endState).sortBy { case SudokuDetailState(idx, _) => idx }.map { case SudokuDetailState(_, state) => state})
        trackProgress(updatesInFlight = 0)
      case detail @ SudokuDetailState(index, state) =>
        collectEndState(remainingRows = remainingRows - 1, detail +: endState)
    }
} 
Example 7
Source File: SudokuProblemSender.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster.sudoku

import java.io.File

import akka.actor.typed.scaladsl.{ActorContext, Behaviors, TimerScheduler}
import akka.actor.typed.{ActorRef, Behavior}

object SudokuProblemSender {

  sealed trait Command
  case object SendNewSudoku extends Command
  // Wrapped responses
  private final case class SolutionWrapper(result: SudokuSolver.Response) extends Command

  private val rowUpdates: Seq[SudokuDetailProcessor.RowUpdate] =
    SudokuIO.readSudokuFromFile(new File("sudokus/001.sudoku"))
      .map { case (rowIndex, update) => SudokuDetailProcessor.RowUpdate(rowIndex, update) }

  def apply(sudokuSolver: ActorRef[SudokuSolver.Command],
            sudokuSolverSettings: SudokuSolverSettings): Behavior[Command] =
    Behaviors.setup { context =>
      Behaviors.withTimers { timers =>
        new SudokuProblemSender(sudokuSolver, context, timers, sudokuSolverSettings).sending()
      }
    }
}

class SudokuProblemSender private (sudokuSolver: ActorRef[SudokuSolver.Command],
                                   context: ActorContext[SudokuProblemSender.Command],
                                   timers: TimerScheduler[SudokuProblemSender.Command],
                                   sudokuSolverSettings: SudokuSolverSettings) {
  import SudokuProblemSender._

  private val solutionWrapper: ActorRef[SudokuSolver.Response] =
    context.messageAdapter(response => SolutionWrapper(response))

  private val initialSudokuField = rowUpdates.toSudokuField

  private val rowUpdatesSeq = LazyList.continually(
    Seq(
      initialSudokuField,
      initialSudokuField.flipVertically,
      initialSudokuField.flipHorizontally,
      initialSudokuField.flipHorizontally.flipVertically,
      initialSudokuField.flipVertically.flipHorizontally,
      initialSudokuField.columnSwap(0,1),
      initialSudokuField.rowSwap(4,5).rowSwap(0, 2),
      initialSudokuField.randomSwapAround,
      initialSudokuField.randomSwapAround,
      initialSudokuField.rotateCW,
      initialSudokuField.rotateCCW,
      initialSudokuField.rotateCW.rotateCW,
      initialSudokuField.transpose,
      initialSudokuField.randomSwapAround,
      initialSudokuField.rotateCW.transpose,
      initialSudokuField.randomSwapAround,
      initialSudokuField.rotateCCW.transpose,
      initialSudokuField.randomSwapAround,
      initialSudokuField.randomSwapAround,
      initialSudokuField.flipVertically.transpose,
      initialSudokuField.flipVertically.rotateCW,
      initialSudokuField.columnSwap(4,5).columnSwap(0, 2).rowSwap(3,4),
      initialSudokuField.rotateCW.rotateCW.transpose
    ).map(_.toRowUpdates)).flatten.iterator

  private val problemSendInterval = sudokuSolverSettings.ProblemSender.SendInterval
  timers.startTimerAtFixedRate(SendNewSudoku, problemSendInterval) // on a 5 node RPi 4 based cluster in steady state, this can be lowered to about 6ms

  def sending(): Behavior[Command] = Behaviors.receiveMessagePartial {
    case SendNewSudoku =>
      context.log.debug("sending new sudoku problem")
      sudokuSolver ! SudokuSolver.InitialRowUpdates(rowUpdatesSeq.next, solutionWrapper)
      Behaviors.same
    case SolutionWrapper(solution: SudokuSolver.SudokuSolution) =>
      context.log.info(s"${SudokuIO.sudokuPrinter(solution)}")
      Behaviors.same
  }
} 
Example 8
Source File: ClusterStatusTrackerMain.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster

import akka.NotUsed
import akka.actor.typed.scaladsl.adapter.TypedActorSystemOps
import akka.actor.typed.scaladsl.{ActorContext, Behaviors, Routers}
import akka.actor.typed.{ActorSystem, Behavior, Terminated}
import akka.cluster.typed.{ClusterSingleton, SingletonActor}
import akka.management.scaladsl.AkkaManagement
import akkapi.cluster.sudoku.{SudokuSolverSettings, SudokuSolver, SudokuProblemSender}

object Main {
  def apply(settings: Settings): Behavior[NotUsed] = Behaviors.setup { context =>
    val sudokuSolverSettings = SudokuSolverSettings("sudokusolver.conf")
    // Start CLusterStatusTracker & LedStripVisualiser
    val ledStripDriver = context.spawn(LedStripDriver(settings), "led-strip-driver")
    val ledStripController = context.spawn(LedStripVisualiser(settings, ledStripDriver), "led-strip-controller")
    val clusterStatusTracker =
      context.spawn(
        ClusterStatusTracker(
          settings,
          Some(contextToClusterSingleton(settings))
        ),
        "cluster-status-tracker"
      )
    clusterStatusTracker ! ClusterStatusTracker.SubscribeVisualiser(ledStripController)

    // Start SodukuSolver: we'll run one instance/cluster node
    context.spawn(SudokuSolver(ledStripDriver, sudokuSolverSettings), s"sudoku-solver")
    // We'll use a [cluster-aware] group router
    val sudokuSolverGroup = context.spawn(Routers.group(SudokuSolver.Key).withRoundRobinRouting(), "sudoku-solvers")
    // And run one instance if the Sudoku problem sender in the cluster
    ClusterSingleton(context.system).init(SingletonActor(SudokuProblemSender(sudokuSolverGroup, sudokuSolverSettings), "sudoku-problem-sender"))

    Behaviors.receiveSignal {
      case (_, Terminated(_)) =>
        Behaviors.stopped
    }
  }

  private def contextToClusterSingleton(settings: Settings): ActorContextToSingletonBehavior  =
    (context: ActorContext[ClusterStatusTracker.ClusterEvent]) => PiClusterSingleton(settings, context.self)

  type ActorContextToSingletonBehavior = ActorContext[ClusterStatusTracker.ClusterEvent] => Behavior[PiClusterSingleton.Command]
}

object ClusterStatusTrackerMain {
  def main(args: Array[String]): Unit = {
    System.loadLibrary("rpi_ws281x")

    val settings = Settings()
    val config = settings.config
    val system = ActorSystem[NotUsed](Main(settings), settings.actorSystemName, config)
    val classicSystem = system.toClassic

    // Start Akka HTTP Management extension
    AkkaManagement(classicSystem).start()
  }
} 
Example 9
Source File: ForkJoinCreation.scala    From effpi   with MIT License 5 votes vote down vote up
// Effpi - verified message-passing programs in Dotty
// Copyright 2019 Alceste Scalas and Elias Benussi
// Released under the MIT License: https://opensource.org/licenses/MIT
package effpi.benchmarks.akka

import akka.NotUsed
import akka.actor.typed.scaladsl.{ Behaviors, MutableBehavior, ActorContext}
import akka.actor.typed.{ ActorRef, ActorSystem, Behavior, DispatcherSelector, Terminated }

import scala.concurrent.Future
import scala.concurrent.duration._
import scala.concurrent.{ Future, Promise, Await }
import scala.concurrent.ExecutionContext.Implicits.global

object ForkJoinCreation {

  case class Message(msg: String)

  val simpleActor = Behaviors.receive[Message] { (ctx, msg) =>
    Behaviors.stopped
  }

  def mainActor(
    durationPromise: Promise[Long], numActors: Int
  ): Behavior[akka.NotUsed] =
    Behaviors.setup { ctx =>

      val startTime = System.nanoTime()

      val simpleActorRefs = (1 to numActors).toList.map { id =>
        ctx.spawn(simpleActor, "simple" + id)
      }

      simpleActorRefs.foreach { simpleActorRef =>
        simpleActorRef ! Message("Hello World!")
      }

      val endTime = System.nanoTime()

      durationPromise.success(endTime - startTime)
      Behaviors.stopped
    }

  def bench(params: Int): Long = {
    val durationPromise = Promise[Long]()
    val durationFuture = durationPromise.future
    val system = ActorSystem(
      mainActor(durationPromise, params), "ForkJoinCreationDemo")
    Await.result(system.whenTerminated, Duration.Inf)
    val duration = Await.result(durationFuture, Duration.Inf)
    duration
  }

} 
Example 10
Source File: ClusterStatusTrackerMain.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster

import akka.NotUsed
import akka.actor.typed.scaladsl.adapter.TypedActorSystemOps
import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorSystem, Behavior, Terminated}
import akka.management.cluster.bootstrap.ClusterBootstrap
import akka.management.scaladsl.AkkaManagement

object Main {
  def apply(settings: Settings): Behavior[NotUsed] = Behaviors.setup { context =>
    val ledStripDriver = context.spawn(LedStripDriver(settings), "led-strip-driver")
    val ledStripController = context.spawn(LedStripVisualiser(settings, ledStripDriver), "led-strip-controller")
    val clusterStatusTracker =
      context.spawn(
        ClusterStatusTracker(
          settings,
          Some(contextToClusterSingleton(settings))
        ),
        "cluster-status-tracker"
      )
    clusterStatusTracker ! ClusterStatusTracker.SubscribeVisualiser(ledStripController)
    Behaviors.receiveSignal {
      case (_, Terminated(_)) =>
        Behaviors.stopped
    }
  }

  private def contextToClusterSingleton(settings: Settings): ActorContextToSingletonBehavior  =
    (context: ActorContext[ClusterStatusTracker.ClusterEvent]) => PiClusterSingleton(settings, context.self)

  type ActorContextToSingletonBehavior = ActorContext[ClusterStatusTracker.ClusterEvent] => Behavior[PiClusterSingleton.Command]
}

object ClusterStatusTrackerMain {
  def main(args: Array[String]): Unit = {
    System.loadLibrary("rpi_ws281x")

    val settings = Settings()
    val config = settings.config
    val system = ActorSystem[NotUsed](Main(settings), settings.actorSystemName, config)

    // Start Akka HTTP Management extension
    AkkaManagement(system.toClassic).start()
    ClusterBootstrap(system.toClassic).start()
  }
} 
Example 11
Source File: CountingActor.scala    From effpi   with MIT License 5 votes vote down vote up
// Effpi - verified message-passing programs in Dotty
// Copyright 2019 Alceste Scalas and Elias Benussi
// Released under the MIT License: https://opensource.org/licenses/MIT
package effpi.benchmarks.akka

import akka.NotUsed
import akka.actor.typed.scaladsl.{ Behaviors, MutableBehavior, ActorContext}
import akka.actor.typed.{ ActorRef, ActorSystem, Behavior, DispatcherSelector, Terminated }

import scala.concurrent.Future
import scala.concurrent.duration._
import scala.concurrent.{ Future, Promise, Await }
import scala.concurrent.ExecutionContext.Implicits.global

object CountingActor {

  sealed trait CounterAction
  object CounterAction {
    final case class Add(num: Int, p: Promise[Int]) extends CounterAction
    final case class Cheque(replyTo: ActorRef[Sum]) extends CounterAction
  }

  case class Sum(sum: Int)

  val counter = Behaviors.setup[CounterAction] { ctx =>
    new MutableCounter(ctx)
  }

  class MutableCounter(
    ctx: ActorContext[CounterAction]
  ) extends MutableBehavior[CounterAction] {
    var counter = 0

    override def onMessage(msg: CounterAction): Behavior[CounterAction] = {
      msg match {
        case CounterAction.Add(num, p) =>
          counter += 1
          p.success(num)
          Behaviors.same
        case CounterAction.Cheque(replyTo) =>
          replyTo ! Sum(counter)
          Behaviors.stopped
      }
    }
  }

  def sink(endTimePromise: Promise[Long]) = Behaviors.receive[Sum] { (ctx, msg) =>
    endTimePromise.success(System.nanoTime())
    Behaviors.stopped
  }

  def mainActor(
    durationPromise: Promise[Long],
    numMessages: Int
  ): Behavior[akka.NotUsed] =
    Behaviors.setup { ctx =>

      val endTimePromise = Promise[Long]()
      val endTimeFuture = endTimePromise.future

      val sinkRef = ctx.spawn(sink(endTimePromise), "sink")
      ctx.watch(sinkRef)
      val counterRef = ctx.spawn(counter, "counter")

      val startTime = System.nanoTime()
      val futs = (1 to numMessages).toList.map { num =>
        val p = Promise[Int]()
        val f = p.future
        counterRef ! CounterAction.Add(num, p)
        f
      }

      Await.result(Future.sequence(futs), Duration.Inf)

      counterRef ! CounterAction.Cheque(sinkRef)

      val endTime = Await.result(endTimeFuture, Duration.Inf)
      val countingDuration = endTime - startTime
      durationPromise.success(countingDuration)

      Behaviors.receiveSignal {
        case (_, Terminated(ref)) =>
          Behaviors.stopped
        case (_, _) =>
          Behaviors.empty
      }
    }

  def bench(params: Int): Long = {
    val durationPromise = Promise[Long]()
    val durationFuture = durationPromise.future
    val system = ActorSystem(
      mainActor(durationPromise, params), "CountingActorDemo")
    Await.result(system.whenTerminated, Duration.Inf)
    val duration = Await.result(durationFuture, Duration.Inf)
    duration
  }
} 
Example 12
Source File: ForkJoinThroughput.scala    From effpi   with MIT License 5 votes vote down vote up
// Effpi - verified message-passing programs in Dotty
// Copyright 2019 Alceste Scalas and Elias Benussi
// Released under the MIT License: https://opensource.org/licenses/MIT
package effpi.benchmarks.akka

import akka.NotUsed
import akka.actor.typed.scaladsl.{ Behaviors, MutableBehavior, ActorContext}
import akka.actor.typed.{ ActorRef, ActorSystem, Behavior, DispatcherSelector, Terminated }
import scala.concurrent.Future
import scala.concurrent.duration._
import scala.concurrent.{ Future, Promise, Await }
import scala.concurrent.ExecutionContext.Implicits.global

object ForkJoinThroughput {

  case class Message(msg: String)

  def receiver(maxMsgs: Int) = Behaviors.setup[Message] { ctx =>
    new MutableSimpleActor(ctx, maxMsgs)
  }

  class MutableSimpleActor(
    ctx: ActorContext[Message],
    maxMsgs: Int
  ) extends MutableBehavior[Message] {
    var count = 0

    override def onMessage(msg: Message): Behavior[Message] = {
      count +=1
      if (count < maxMsgs) {
        Behaviors.same
      } else {
        Behaviors.stopped
      }
    }
  }

  def mainActor(
    durationPromise: Promise[Long],
    numActors: Int,
    numMessages: Int
  ): Behavior[akka.NotUsed] =
    Behaviors.setup { ctx =>

      val receiversRef = (1 to numActors).map{ id => ctx.spawn(receiver(numMessages), "receiver" + id)}

      val startTime = System.nanoTime()

      (1 to numMessages).foreach { n =>
        receiversRef.foreach { simpleActor =>
          simpleActor ! Message("Hello World!")
        }
      }

      val endTime = System.nanoTime()

      durationPromise.success(endTime - startTime)
      Behaviors.stopped
    }

  def bench(params: (Int, Int)): Long = {
    val (numActors, numMessages) = params
    val durationPromise = Promise[Long]()
    val durationFuture = durationPromise.future
    val system = ActorSystem(
      mainActor(durationPromise, numActors, numMessages),
      "ForkJoinCreationDemo")
    Await.result(system.whenTerminated, Duration.Inf)
    val duration = Await.result(durationFuture, Duration.Inf)
    duration
  }
} 
Example 13
Source File: Watcher.scala    From kafka-lag-exporter   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.kafkalagexporter.watchers

import akka.actor.typed.ActorRef
import akka.actor.typed.scaladsl.ActorContext
import com.lightbend.kafkalagexporter.{AppConfig, KafkaCluster}
import com.lightbend.kafkalagexporter.KafkaClusterManager

object Watcher {

  sealed trait Message
  sealed trait Stop extends Message
  final case object Stop extends Stop

  trait Client {
    def close(): Unit
  }

  trait Events {
    def added(cluster: KafkaCluster): Unit
    def removed(cluster: KafkaCluster): Unit
    def error(e: Throwable): Unit
  }

  def createClusterWatchers(context: ActorContext[KafkaClusterManager.Message],
                            appConfig: AppConfig): Seq[ActorRef[Watcher.Message]] = {
    // Add additional watchers here..
    val configMap = Seq(StrimziClusterWatcher.name -> appConfig.strimziWatcher)
    configMap.flatMap {
      case (StrimziClusterWatcher.name, true) =>
        context.log.info(s"Adding watcher: ${StrimziClusterWatcher.name}")
        Seq(context.spawn(StrimziClusterWatcher.init(context.self), s"strimzi-cluster-watcher-${StrimziClusterWatcher.name}"))
      case _ => Seq()
    }
  }
} 
Example 14
Source File: JobActor.scala    From fusion-data   with Apache License 2.0 5 votes vote down vote up
package mass.job.service.job

import akka.actor.typed.scaladsl.{ ActorContext, Behaviors }
import akka.actor.typed.{ ActorRef, ActorSystem, Behavior }
import akka.cluster.typed.{ ClusterSingleton, ClusterSingletonSettings, SingletonActor }
import fusion.inject.guice.GuiceApplication
import fusion.json.CborSerializable
import helloscala.common.IntStatus
import mass.core.Constants
import mass.job.JobScheduler
import mass.job.service.job.JobActor.CommandReply
import mass.message.job._

import scala.concurrent.Future

object JobActor {
  sealed trait Command extends CborSerializable
  final case class CommandReply(message: JobMessage, replyTo: ActorRef[JobResponse]) extends Command
  final case class CommandEvent(event: JobEvent) extends Command

  val NAME = "job"

  def init(system: ActorSystem[_]): ActorRef[Command] = {
    ClusterSingleton(system).init(
      SingletonActor(apply(), NAME).withSettings(ClusterSingletonSettings(system).withRole(Constants.Roles.CONSOLE)))
  }

  private def apply(): Behavior[Command] = Behaviors.setup[Command](context => new JobActor(context).init())
}

import mass.job.service.job.JobActor._
class JobActor private (context: ActorContext[Command]) extends JobServiceComponent {
  import context.executionContext
  override val jobScheduler: JobScheduler = GuiceApplication(context.system).instance[JobScheduler]

  def init(): Behavior[Command] = {
    receive()
  }

  def receive(): Behavior[Command] = Behaviors.receiveMessage[Command] {
    case CommandReply(message, replyTo) =>
      receiveMessage(message).foreach(resp => replyTo ! resp)
      Behaviors.same
    case CommandEvent(event) =>
      receiveEvent(event)
      Behaviors.same
  }

  private def receiveMessage(message: JobMessage): Future[JobResponse] =
    try {
      val future = message match {
        case req: JobScheduleReq     => handleScheduleJob(req)
        case req: JobPageReq         => handlePage(req)
        case req: JobFindReq         => handleFind(req)
        case req: JobUploadJobReq    => handleUploadJob(req)
        case req: JobListReq         => handleList(req)
        case req: JobGetAllOptionReq => Future(handleGetAllOption(req))
        case req: JobCreateReq       => handleCreateJob(req)
        case req: JobUpdateReq       => handleUpdate(req)
        case req: JobUploadFilesReq  => handleUploadFiles(req)
      }
      future.recover {
        case e =>
          val message = s"Handle message error: ${e.getMessage}."
          logger.error(message, e)
          JobErrorResponse(IntStatus.INTERNAL_ERROR, message)
      }
    } catch {
      case e: Throwable =>
        val message = s"Process message error: ${e.getMessage}."
        logger.error(message)
        Future.successful(JobErrorResponse(IntStatus.INTERNAL_ERROR, message))
    }

  private def receiveEvent(v: JobEvent): Unit =
    try {
      v match {
        case event: JobTriggerEvent => triggerJob(event)
      }
    } catch {
      case e: Throwable => logger.error(s"Process event error: ${e.getMessage}", e)
    }
} 
Example 15
Source File: Main.scala    From streamee   with Apache License 2.0 5 votes vote down vote up
package io.moia.streamee.demo

import akka.actor.{ ActorSystem => ClassicSystem }
import akka.actor.CoordinatedShutdown.Reason
import akka.actor.typed.{ Behavior, Scheduler }
import akka.actor.typed.scaladsl.{ ActorContext, Behaviors }
import akka.actor.typed.scaladsl.adapter.{ ClassicActorSystemOps, TypedActorSystemOps }
import akka.cluster.typed.{
  Cluster,
  ClusterSingleton,
  SelfUp,
  SingletonActor,
  Subscribe,
  Unsubscribe
}
import akka.management.cluster.bootstrap.ClusterBootstrap
import akka.management.scaladsl.AkkaManagement
import io.moia.streamee.FrontProcessor
import org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
import org.slf4j.LoggerFactory
import pureconfig.generic.auto.exportReader
import pureconfig.ConfigSource
import scala.concurrent.ExecutionContext
import scala.concurrent.duration.FiniteDuration

object Main {

  final case class Config(
      api: Api.Config,
      textShufflerProcessorTimeout: FiniteDuration,
      textShuffler: TextShuffler.Config
  )

  final object TopLevelActorTerminated extends Reason

  private val logger = LoggerFactory.getLogger(getClass)

  def main(args: Array[String]): Unit = {
    // Always use async logging!
    sys.props += "log4j2.contextSelector" -> classOf[AsyncLoggerContextSelector].getName

    // Must happen before creating the actor system!
    val config = ConfigSource.default.at("streamee-demo").loadOrThrow[Config]

    // Always start with a classic system!
    val system = ClassicSystem("streamee-demo")
    system.spawn(Main(config), "main")

    // Cluster bootstrap
    AkkaManagement(system).start()
    ClusterBootstrap(system).start()
  }

  def apply(config: Config): Behavior[SelfUp] =
    Behaviors.setup { context =>
      if (logger.isInfoEnabled)
        logger.info(s"${context.system.name} started and ready to join cluster")
      Cluster(context.system).subscriptions ! Subscribe(context.self, classOf[SelfUp])

      Behaviors.receive { (context, _) =>
        if (logger.isInfoEnabled) logger.info(s"${context.system.name} joined cluster and is up")
        Cluster(context.system).subscriptions ! Unsubscribe(context.self)

        initialize(config)(context)

        Behaviors.empty
      }
    }

  private def initialize(config: Config)(implicit context: ActorContext[_]) = {
    import config._

    implicit val classicSystem: ClassicSystem = context.system.toClassic
    implicit val ec: ExecutionContext         = context.executionContext
    implicit val scheduler: Scheduler         = context.system.scheduler

    val wordShufflerRunner =
      ClusterSingleton(context.system).init(
        SingletonActor(WordShufflerRunner(), "word-shuffler")
          .withStopMessage(WordShufflerRunner.Shutdown)
      )

    val textShufflerProcessor =
      FrontProcessor(
        TextShuffler(config.textShuffler, wordShufflerRunner),
        textShufflerProcessorTimeout,
        "text-shuffler"
      )

    Api(config.api, textShufflerProcessor)
  }
} 
Example 16
Source File: WsHeart.scala    From AckCord   with MIT License 5 votes vote down vote up
package ackcord.voice

import scala.concurrent.duration._

import akka.actor.typed.scaladsl.{ActorContext, Behaviors, TimerScheduler}
import akka.actor.typed.{ActorRef, Behavior}

object WsHeart {

  def apply(parent: ActorRef[VoiceWsHandler.Command]): Behavior[Command] =
    Behaviors.setup { ctx =>
      Behaviors.withTimers(timers => runningHeart(ctx, timers, parent, None, receivedAck = true))
    }

  def runningHeart(
      context: ActorContext[Command],
      timers: TimerScheduler[Command],
      parent: ActorRef[VoiceWsHandler.Command],
      previousNonce: Option[Int],
      receivedAck: Boolean
  ): Behavior[Command] = Behaviors.receiveMessage {
    case StartBeating(interval, nonce) =>
      context.log.debug(s"Starting to beat with initial nonce $nonce")
      timers.startTimerAtFixedRate("heartbeatTimerKey", Beat, interval.millis)
      runningHeart(context, timers, parent, Some(nonce), receivedAck = true)

    case StopBeating =>
      timers.cancel("heartbeatTimerKey")
      runningHeart(context, timers, parent, None, receivedAck = true)

    case BeatAck(nonce) =>
      val log = context.log
      log.debug(s"Received HeartbeatACK with nonce $nonce")
      if (previousNonce.contains(nonce))
        runningHeart(context, timers, parent, None, receivedAck = true)
      else {
        log.warn("Did not receive correct nonce in HeartbeatACK. Restarting.")
        parent ! VoiceWsHandler.Restart(fresh = false, 500.millis)
        Behaviors.same
      }
    case Beat =>
      val log = context.log
      if (receivedAck) {
        val nonce = System.currentTimeMillis().toInt

        parent ! VoiceWsHandler.SendHeartbeat(nonce)
        log.debug(s"Sent Heartbeat with nonce $nonce")

        runningHeart(context, timers, parent, previousNonce = Some(nonce), receivedAck = false)
      } else {
        log.warn("Did not receive HeartbeatACK between heartbeats. Restarting.")
        parent ! VoiceWsHandler.Restart(fresh = false, 0.millis)
        Behaviors.same
      }
  }

  sealed trait Command
  case class StartBeating(interval: Double, nonce: Int) extends Command
  case object StopBeating                               extends Command
  case class BeatAck(nonce: Int)                        extends Command
  case object Beat                                      extends Command
} 
Example 17
Source File: ModelServerBehavior.scala    From model-serving-tutorial   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.modelserving.akka

import akka.Done
import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl.{AbstractBehavior, ActorContext}
import com.lightbend.model.winerecord.WineRecord
import com.lightbend.modelserving.model.{Model, ModelToServe, ModelToServeStats, ServingResult}


class ModelServerBehavior(context: ActorContext[ModelServerActor], dataType : String) extends AbstractBehavior[ModelServerActor] {

  println(s"Creating a new Model Server for data type $dataType")

  private var currentModel: Option[Model[WineRecord, Double]] = None
  var currentState: Option[ModelToServeStats] = None

  override def onMessage(msg: ModelServerActor): Behavior[ModelServerActor] = {
    msg match {
      case update : UpdateModel => // Update Model
        // Update model
        println(s"Updated model: ${update.model}")
        ModelToServe.toModel[WineRecord, Double](update.model) match {
          case Some(m) => // Successfully got a new model
            // close current model first
            currentModel.foreach(_.cleanup())
            // Update model and state
            currentModel = Some(m)
            currentState = Some(ModelToServeStats(update.model))
          case _ =>   // Failed converting
            println(s"Failed to convert model: ${update.model}")
        }
        update.reply ! Done
      case scoreData : ScoreData => // Serve data
        // Actually process data
        val result = currentModel match {
          case Some(model) => {
            val start = System.currentTimeMillis()
            // Actually serve
            val result = model.score(scoreData.record.getRecord)
            val duration = System.currentTimeMillis() - start
            // Update state
            currentState = Some(currentState.get.incrementUsage(duration))
            // result
            Some(ServingResult(currentState.get.name, scoreData.record.getType, scoreData.record.getRecord.asInstanceOf[WineRecord].ts, result.asInstanceOf[Double]))
          }
          case _ => None
        }
        scoreData.reply ! result
      case getState : GetState => // State query
        getState.reply ! currentState.getOrElse(ModelToServeStats())
    }
    this
  }
} 
Example 18
Source File: ModelServerManagerBehavior.scala    From model-serving-tutorial   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.modelserving.akka

import akka.actor.typed.scaladsl.{AbstractBehavior, ActorContext, Behaviors}
import akka.actor.typed.{ActorRef, Behavior}
import com.lightbend.modelserving.model.ModelToServeStats


class ModelServerManagerBehavior(context: ActorContext[ModelServerManagerActor]) extends AbstractBehavior[ModelServerManagerActor] {

  println("Creating Model Serving Manager")

  private def getModelServer(dataType: String): ActorRef[ModelServerActor] = {

    context.child(dataType) match {
      case Some(actorRef) => actorRef.asInstanceOf[ActorRef[ModelServerActor]]
      case _ => context.spawn(Behaviors.setup[ModelServerActor](
        context => new ModelServerBehavior(context, dataType)), dataType)
    }
  }

  private def getInstances : GetModelsResult = GetModelsResult(context.children.map(_.path.name).toSeq)

  override def onMessage(msg: ModelServerManagerActor): Behavior[ModelServerManagerActor] = {
    msg match {
      case updateModel : UpdateModel =>
        getModelServer(updateModel.model.dataType) tell updateModel
      case scoreData : ScoreData =>
        getModelServer(scoreData.record.getType) tell scoreData
      case getState : GetState => // Used for state queries
        context.child(getState.dataType) match{
        case Some(server) => server.asInstanceOf[ActorRef[ModelServerActor]] tell getState
        case _ => getState.reply ! ModelToServeStats()
      }
      case getModels : GetModels => // Get list of models
        getModels.reply ! getInstances
    }
    this
  }
} 
Example 19
Source File: ClusterStatusTrackerMain.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster

import akka.NotUsed
import akka.actor.typed.scaladsl.adapter.TypedActorSystemOps
import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorSystem, Behavior, Terminated}
import akka.management.scaladsl.AkkaManagement

object Main {
  def apply(settings: Settings): Behavior[NotUsed] = Behaviors.setup { context =>
    val ledStripDriver = context.spawn(LedStripDriver(settings), "led-strip-driver")
    val ledStripController = context.spawn(LedStripVisualiser(settings, ledStripDriver), "led-strip-controller")
    val clusterStatusTracker =
      context.spawn(
        ClusterStatusTracker(
          settings,
          Some(contextToClusterSingleton(settings))
        ),
        "cluster-status-tracker"
      )
    clusterStatusTracker ! ClusterStatusTracker.SubscribeVisualiser(ledStripController)
    Behaviors.receiveSignal {
      case (_, Terminated(_)) =>
        Behaviors.stopped
    }
  }

  private def contextToClusterSingleton(settings: Settings): ActorContextToSingletonBehavior  =
    (context: ActorContext[ClusterStatusTracker.ClusterEvent]) => PiClusterSingleton(settings, context.self)

  type ActorContextToSingletonBehavior = ActorContext[ClusterStatusTracker.ClusterEvent] => Behavior[PiClusterSingleton.Command]
}

object ClusterStatusTrackerMain {
  def main(args: Array[String]): Unit = {
    System.loadLibrary("rpi_ws281x")

    val settings = Settings()
    val config = settings.config
    val system = ActorSystem[NotUsed](Main(settings), settings.actorSystemName, config)

    // Start Akka HTTP Management extension
    AkkaManagement(system.toClassic).start()
  }
} 
Example 20
Source File: RoomActor.scala    From lila-ws   with GNU Affero General Public License v3.0 5 votes vote down vote up
package lila.ws

import akka.actor.typed.scaladsl.ActorContext

import ipc._

object RoomActor {

  import ClientActor._

  case class State(
      id: RoomId,
      isTroll: IsTroll,
      lastCrowd: ClientIn.Crowd = ClientIn.emptyCrowd
  )

  def onStart(
      state: State,
      fromVersion: Option[SocketVersion],
      deps: Deps,
      ctx: ActorContext[ClientMsg]
  ): Unit = {
    import deps._
    ClientActor.onStart(deps, ctx)
    req.user foreach { users.connect(_, ctx.self) }
    Bus.subscribe(Bus.channel room state.id, ctx.self)
    roomCrowd.connect(state.id, req.user)
    History.room.getFrom(state.id, fromVersion) match {
      case None         => clientIn(ClientIn.Resync)
      case Some(events) => events map { versionFor(state.isTroll, _) } foreach clientIn
    }
  }

  def onStop(state: State, deps: Deps, ctx: ActorContext[ClientMsg]): Unit = {
    Bus.unsubscribe(Bus.channel room state.id, ctx.self)
    deps.roomCrowd.disconnect(state.id, deps.req.user)
  }

  def versionFor(isTroll: IsTroll, msg: ClientIn.Versioned): ClientIn.Payload =
    if (!msg.troll.value || isTroll.value) msg.full
    else msg.skip

  def receive(
      state: State,
      deps: Deps
  ): PartialFunction[ClientMsg, (Option[State], Option[LilaIn.AnyRoom])] = {

    case versioned: ClientIn.Versioned =>
      deps.clientIn(versionFor(state.isTroll, versioned))
      None -> None

    case ClientIn.OnlyFor(endpoint, payload) =>
      if (endpoint == ClientIn.OnlyFor.Room(state.id)) deps.clientIn(payload)
      None -> None

    case crowd: ClientIn.Crowd =>
      if (crowd == state.lastCrowd) None -> None
      else
        Some {
          deps.clientIn(crowd)
          state.copy(lastCrowd = crowd)
        } -> None

    case SetTroll(v) =>
      Some(state.copy(isTroll = v)) -> None

    case ClientOut.ChatSay(msg) =>
      None -> deps.req.user.map { u => LilaIn.ChatSay(state.id, u.id, msg) }

    case ClientOut.ChatTimeout(suspect, reason, text) =>
      None -> deps.req.user.map { u => LilaIn.ChatTimeout(state.id, u.id, suspect, reason, text) }
  }
} 
Example 21
Source File: ApiActor.scala    From lila-ws   with GNU Affero General Public License v3.0 5 votes vote down vote up
package lila.ws

import akka.actor.typed.{ Behavior, PostStop }
import akka.actor.typed.scaladsl.{ ActorContext, Behaviors }

import ipc._

object ApiActor {

  def start(deps: Deps): Behavior[ClientMsg] =
    Behaviors.setup { ctx =>
      deps.services.users.connect(deps.user, ctx.self)
      LilaWsServer.connections.incrementAndGet
      apply(deps)
    }

  def onStop(deps: Deps, ctx: ActorContext[ClientMsg]): Unit = {
    import deps._
    LilaWsServer.connections.decrementAndGet
    services.users.disconnect(user, ctx.self)
    services.friends.onClientStop(user.id)
  }

  private def apply(deps: Deps): Behavior[ClientMsg] =
    Behaviors
      .receive[ClientMsg] { (ctx, msg) =>
        msg match {

          case ClientCtrl.ApiDisconnect => Behaviors.stopped

          case _ =>
            Monitor.clientOutUnhandled("api").increment()
            Behaviors.same
        }

      }
      .receiveSignal {
        case (ctx, PostStop) =>
          onStop(deps, ctx)
          Behaviors.same
      }

  case class Deps(user: User, services: Services)
} 
Example 22
Source File: Shop.scala    From Learn-Scala-Programming   with MIT License 5 votes vote down vote up
package ch12

import akka.actor.typed.{ActorRef, ActorSystem, Behavior}
import akka.actor.typed.receptionist.{Receptionist, ServiceKey}
import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.receptionist.Receptionist._
import ch12.Bakery.Groceries
import ch12.Manager.ReceiveGroceries
import ch12.Shop.seller
import com.typesafe.config.ConfigFactory

object Store extends App {
  val config = ConfigFactory.load("grocery.conf")
  val system = ActorSystem(seller(Shop.systemReceptionist), "Typed-Bakery", config)
}
object Shop {
  final case class ShoppingList(eggs: Int,
                                flour: Int,
                                sugar: Int,
                                chocolate: Int)
  final case class SellByList(list: ShoppingList,
                              toWhom: ActorRef[Manager.Command])

  val SellerKey = ServiceKey[SellByList]("GrocerySeller")

  type ReceptionistFactory = ActorContext[SellByList] => ActorRef[Receptionist.Command]

  val systemReceptionist: ReceptionistFactory = _.system.receptionist

  def seller(receptionist: ReceptionistFactory): Behavior[SellByList] = Behaviors.setup { ctx ⇒
    receptionist(ctx) ! Register(SellerKey, ctx.self)
    Behaviors.receiveMessage[SellByList] {
      case SellByList(list, toWhom) ⇒
        import list._
        toWhom ! ReceiveGroceries(Groceries(eggs, flour, sugar, chocolate))
        Behaviors.same
    }
  }

} 
Example 23
Source File: PiClusterSingleton.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster



import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorRef, Behavior, PostStop}

object PiClusterSingleton {

  sealed trait Command
  final case object Ping extends Command

  def apply(settings: Settings, clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]): Behavior[Command] = {
    Behaviors.setup { context =>
      new PiClusterSingleton(context, settings, clusterStatusTracker).run()
    }
  }
}

class PiClusterSingleton private (context: ActorContext[PiClusterSingleton.Command],
                         settings: Settings,
                         clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]) {

  import PiClusterSingleton._

  // Cluster singleton has been started on this node
  clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonOnNode

  def run(): Behavior[Command] = Behaviors.receiveMessage[Command] {
    case Ping =>
      context.log.info(s"PiClusterSingleton was pinged")
      Behaviors.same
  }.receiveSignal {
    case (_, signal) if signal == PostStop =>
      clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonNotOnNode
      Behaviors.same
  }

} 
Example 24
Source File: ClusterStatusTrackerMain.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster

import akka.NotUsed
import akka.actor.typed.scaladsl.adapter.TypedActorSystemOps
import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorSystem, Behavior, Terminated}
import akka.management.scaladsl.AkkaManagement

object Main {
  def apply(settings: Settings): Behavior[NotUsed] = Behaviors.setup { context =>
    val ledStripDriver = context.spawn(LedStripDriver(settings), "led-strip-driver")
    val ledStripController = context.spawn(LedStripVisualiser(settings, ledStripDriver), "led-strip-controller")
    val clusterStatusTracker =
      context.spawn(
        ClusterStatusTracker(
          settings,
          Some(contextToClusterSingleton(settings))
        ),
        "cluster-status-tracker"
      )
    clusterStatusTracker ! ClusterStatusTracker.SubscribeVisualiser(ledStripController)
    Behaviors.receiveSignal {
      case (_, Terminated(_)) =>
        Behaviors.stopped
    }
  }

  private def contextToClusterSingleton(settings: Settings): ActorContextToSingletonBehavior  =
    (context: ActorContext[ClusterStatusTracker.ClusterEvent]) => PiClusterSingleton(settings, context.self)

  type ActorContextToSingletonBehavior = ActorContext[ClusterStatusTracker.ClusterEvent] => Behavior[PiClusterSingleton.Command]
}

object ClusterStatusTrackerMain {
  def main(args: Array[String]): Unit = {
    System.loadLibrary("rpi_ws281x")

    val settings = Settings()
    val config = settings.config
    val system = ActorSystem[NotUsed](Main(settings), settings.actorSystemName, config)

    // Start Akka HTTP Management extension
    AkkaManagement(system.toClassic).start()
  }
} 
Example 25
Source File: PiClusterSingleton.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster



import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorRef, Behavior, PostStop}

object PiClusterSingleton {

  sealed trait Command
  final case object Ping extends Command

  def apply(settings: Settings, clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]): Behavior[Command] = {
    Behaviors.setup { context =>
      new PiClusterSingleton(context, settings, clusterStatusTracker).run()
    }
  }
}

class PiClusterSingleton private (context: ActorContext[PiClusterSingleton.Command],
                         settings: Settings,
                         clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]) {

  import PiClusterSingleton._

  // Cluster singleton has been started on this node
  clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonOnNode

  def run(): Behavior[Command] = Behaviors.receiveMessage[Command] {
    case Ping =>
      context.log.info(s"PiClusterSingleton was pinged")
      Behaviors.same
  }.receiveSignal {
    case (_, signal) if signal == PostStop =>
      clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonNotOnNode
      Behaviors.same
  }

} 
Example 26
Source File: ClusterStatusTrackerMain.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster

import akka.NotUsed
import akka.actor.typed.scaladsl.adapter.TypedActorSystemOps
import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorSystem, Behavior, Terminated}
import akka.management.scaladsl.AkkaManagement

object Main {
  def apply(settings: Settings): Behavior[NotUsed] = Behaviors.setup { context =>
    val ledStripDriver = context.spawn(LedStripDriver(settings), "led-strip-driver")
    val ledStripController = context.spawn(LedStripVisualiser(settings, ledStripDriver), "led-strip-controller")
    val clusterStatusTracker =
      context.spawn(
        ClusterStatusTracker(
          settings,
          Some(contextToClusterSingleton(settings))
        ),
        "cluster-status-tracker"
      )
    clusterStatusTracker ! ClusterStatusTracker.SubscribeVisualiser(ledStripController)
    Behaviors.receiveSignal {
      case (_, Terminated(_)) =>
        Behaviors.stopped
    }
  }

  private def contextToClusterSingleton(settings: Settings): ActorContextToSingletonBehavior  =
    (context: ActorContext[ClusterStatusTracker.ClusterEvent]) => PiClusterSingleton(settings, context.self)

  type ActorContextToSingletonBehavior = ActorContext[ClusterStatusTracker.ClusterEvent] => Behavior[PiClusterSingleton.Command]
}

object ClusterStatusTrackerMain {
  def main(args: Array[String]): Unit = {
    System.loadLibrary("rpi_ws281x")

    val settings = Settings()
    val config = settings.config
    val system = ActorSystem[NotUsed](Main(settings), settings.actorSystemName, config)

    // Start Akka HTTP Management extension
    AkkaManagement(system.toClassic).start()
  }
} 
Example 27
Source File: PiClusterSingleton.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster



import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorRef, Behavior, PostStop}

object PiClusterSingleton {

  sealed trait Command
  final case object Ping extends Command

  def apply(settings: Settings, clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]): Behavior[Command] = {
    Behaviors.setup { context =>
      new PiClusterSingleton(context, settings, clusterStatusTracker).run()
    }
  }
}

class PiClusterSingleton private (context: ActorContext[PiClusterSingleton.Command],
                         settings: Settings,
                         clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]) {

  import PiClusterSingleton._

  // Cluster singleton has been started on this node
  clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonOnNode

  def run(): Behavior[Command] = Behaviors.receiveMessage[Command] {
    case Ping =>
      context.log.info(s"PiClusterSingleton was pinged")
      Behaviors.same
  }.receiveSignal {
    case (_, signal) if signal == PostStop =>
      clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonNotOnNode
      Behaviors.same
  }

} 
Example 28
Source File: TriggerRunner.scala    From daml   with Apache License 2.0 5 votes vote down vote up
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package com.daml.lf.engine.trigger

import akka.actor.typed.{Behavior, PostStop}
import akka.actor.typed.scaladsl.AbstractBehavior
import akka.actor.typed.SupervisorStrategy._
import akka.actor.typed.Signal
import akka.actor.typed.scaladsl.Behaviors
import akka.actor.typed.scaladsl.ActorContext
import akka.stream.Materializer
import com.typesafe.scalalogging.StrictLogging
import com.daml.grpc.adapter.ExecutionSequencerFactory

class InitializationHalted(s: String) extends Exception(s) {}
class InitializationException(s: String) extends Exception(s) {}

object TriggerRunner {
  type Config = TriggerRunnerImpl.Config

  trait Message
  final case object Stop extends Message

  def apply(config: Config, name: String)(
      implicit esf: ExecutionSequencerFactory,
      mat: Materializer): Behavior[TriggerRunner.Message] =
    Behaviors.setup(ctx => new TriggerRunner(ctx, config, name))
}

class TriggerRunner(
    ctx: ActorContext[TriggerRunner.Message],
    config: TriggerRunner.Config,
    name: String)(implicit esf: ExecutionSequencerFactory, mat: Materializer)
    extends AbstractBehavior[TriggerRunner.Message](ctx)
    with StrictLogging {

  import TriggerRunner.{Message, Stop}

  // Spawn a trigger runner impl. Supervise it. Stop immediately on
  // initialization halted exceptions, retry any initialization or
  // execution failure exceptions.
  private val child =
    ctx.spawn(
      Behaviors
        .supervise(
          Behaviors
            .supervise(TriggerRunnerImpl(config))
            .onFailure[InitializationHalted](stop)
        )
        .onFailure(
          restartWithBackoff(
            config.restartConfig.minRestartInterval,
            config.restartConfig.maxRestartInterval,
            config.restartConfig.restartIntervalRandomFactor)),
      name
    )

  override def onMessage(msg: Message): Behavior[Message] =
    Behaviors.receiveMessagePartial[Message] {
      case Stop =>
        Behaviors.stopped // Automatically stops the child actor if running.
    }

  override def onSignal: PartialFunction[Signal, Behavior[Message]] = {
    case PostStop =>
      logger.info(s"Trigger $name stopped")
      this
  }

} 
Example 29
Source File: PiClusterSingleton.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster



import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorRef, Behavior, PostStop}

object PiClusterSingleton {

  sealed trait Command
  final case object Ping extends Command

  def apply(settings: Settings, clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]): Behavior[Command] = {
    Behaviors.setup { context =>
      new PiClusterSingleton(context, settings, clusterStatusTracker).run()
    }
  }
}

class PiClusterSingleton private (context: ActorContext[PiClusterSingleton.Command],
                         settings: Settings,
                         clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]) {

  import PiClusterSingleton._

  // Cluster singleton has been started on this node
  clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonOnNode

  def run(): Behavior[Command] = Behaviors.receiveMessage[Command] {
    case Ping =>
      context.log.info(s"PiClusterSingleton was pinged")
      Behaviors.same
  }.receiveSignal {
    case (_, signal) if signal == PostStop =>
      clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonNotOnNode
      Behaviors.same
  }

} 
Example 30
Source File: ClusterStatusTrackerMain.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster

import akka.NotUsed
import akka.actor.typed.scaladsl.adapter.TypedActorSystemOps
import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorSystem, Behavior, Terminated}
import akka.management.cluster.bootstrap.ClusterBootstrap
import akka.management.scaladsl.AkkaManagement

object Main {
  def apply(settings: Settings): Behavior[NotUsed] = Behaviors.setup { context =>
    val ledStripDriver = context.spawn(LedStripDriver(settings), "led-strip-driver")
    val ledStripController = context.spawn(LedStripVisualiser(settings, ledStripDriver), "led-strip-controller")
    val clusterStatusTracker =
      context.spawn(
        ClusterStatusTracker(
          settings,
          Some(contextToClusterSingleton(settings))
        ),
        "cluster-status-tracker"
      )
    clusterStatusTracker ! ClusterStatusTracker.SubscribeVisualiser(ledStripController)
    Behaviors.receiveSignal {
      case (_, Terminated(_)) =>
        Behaviors.stopped
    }
  }

  private def contextToClusterSingleton(settings: Settings): ActorContextToSingletonBehavior  =
    (context: ActorContext[ClusterStatusTracker.ClusterEvent]) => PiClusterSingleton(settings, context.self)

  type ActorContextToSingletonBehavior = ActorContext[ClusterStatusTracker.ClusterEvent] => Behavior[PiClusterSingleton.Command]
}

object ClusterStatusTrackerMain {
  def main(args: Array[String]): Unit = {
    System.loadLibrary("rpi_ws281x")

    val settings = Settings()
    val config = settings.config
    val system = ActorSystem[NotUsed](Main(settings), settings.actorSystemName, config)

    // Start Akka HTTP Management extension
    AkkaManagement(system.toClassic).start()
    ClusterBootstrap(system.toClassic).start()
  }
} 
Example 31
Source File: PiClusterSingleton.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster



import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorRef, Behavior, PostStop}

object PiClusterSingleton {

  sealed trait Command
  final case object Ping extends Command

  def apply(settings: Settings, clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]): Behavior[Command] = {
    Behaviors.setup { context =>
      new PiClusterSingleton(context, settings, clusterStatusTracker).run()
    }
  }
}

class PiClusterSingleton private (context: ActorContext[PiClusterSingleton.Command],
                         settings: Settings,
                         clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]) {

  import PiClusterSingleton._

  // Cluster singleton has been started on this node
  clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonOnNode

  def run(): Behavior[Command] = Behaviors.receiveMessage[Command] {
    case Ping =>
      context.log.info(s"PiClusterSingleton was pinged")
      Behaviors.same
  }.receiveSignal {
    case (_, signal) if signal == PostStop =>
      clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonNotOnNode
      Behaviors.same
  }

} 
Example 32
Source File: ClusterStatusTrackerMain.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster

import akka.NotUsed
import akka.actor.typed.scaladsl.adapter.TypedActorSystemOps
import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorSystem, Behavior, Terminated}
import akka.management.scaladsl.AkkaManagement

object Main {
  def apply(settings: Settings): Behavior[NotUsed] = Behaviors.setup { context =>
    val ledStripDriver = context.spawn(LedStripDriver(settings), "led-strip-driver")
    val ledStripController = context.spawn(LedStripVisualiser(settings, ledStripDriver), "led-strip-controller")
    val clusterStatusTracker =
      context.spawn(
        ClusterStatusTracker(
          settings,
          Some(contextToClusterSingleton(settings))
        ),
        "cluster-status-tracker"
      )
    clusterStatusTracker ! ClusterStatusTracker.SubscribeVisualiser(ledStripController)
    Behaviors.receiveSignal {
      case (_, Terminated(_)) =>
        Behaviors.stopped
    }
  }

  private def contextToClusterSingleton(settings: Settings): ActorContextToSingletonBehavior  =
    (context: ActorContext[ClusterStatusTracker.ClusterEvent]) => PiClusterSingleton(settings, context.self)

  type ActorContextToSingletonBehavior = ActorContext[ClusterStatusTracker.ClusterEvent] => Behavior[PiClusterSingleton.Command]
}

object ClusterStatusTrackerMain {
  def main(args: Array[String]): Unit = {
    System.loadLibrary("rpi_ws281x")

    val settings = Settings()
    val config = settings.config
    val system = ActorSystem[NotUsed](Main(settings), settings.actorSystemName, config)

    // Start Akka HTTP Management extension
    AkkaManagement(system.toClassic).start()
  }
} 
Example 33
Source File: PiClusterSingleton.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster



import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorRef, Behavior, PostStop}

object PiClusterSingleton {

  sealed trait Command
  final case object Ping extends Command

  def apply(settings: Settings, clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]): Behavior[Command] = {
    Behaviors.setup { context =>
      new PiClusterSingleton(context, settings, clusterStatusTracker).run()
    }
  }
}

class PiClusterSingleton private (context: ActorContext[PiClusterSingleton.Command],
                         settings: Settings,
                         clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]) {

  import PiClusterSingleton._

  // Cluster singleton has been started on this node
  clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonOnNode

  def run(): Behavior[Command] = Behaviors.receiveMessage[Command] {
    case Ping =>
      context.log.info(s"PiClusterSingleton was pinged")
      Behaviors.same
  }.receiveSignal {
    case (_, signal) if signal == PostStop =>
      clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonNotOnNode
      Behaviors.same
  }

} 
Example 34
Source File: ClusterStatusTrackerMain.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster

import akka.NotUsed
import akka.actor.typed.scaladsl.adapter.TypedActorSystemOps
import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorSystem, Behavior, Terminated}
import akka.management.scaladsl.AkkaManagement

object Main {
  def apply(settings: Settings): Behavior[NotUsed] = Behaviors.setup { context =>
    val ledStripDriver = context.spawn(LedStripDriver(settings), "led-strip-driver")
    val ledStripController = context.spawn(LedStripVisualiser(settings, ledStripDriver), "led-strip-controller")
    val clusterStatusTracker =
      context.spawn(
        ClusterStatusTracker(
          settings,
          Some(contextToClusterSingleton(settings))
        ),
        "cluster-status-tracker"
      )
    clusterStatusTracker ! ClusterStatusTracker.SubscribeVisualiser(ledStripController)
    Behaviors.receiveSignal {
      case (_, Terminated(_)) =>
        Behaviors.stopped
    }
  }

  private def contextToClusterSingleton(settings: Settings): ActorContextToSingletonBehavior  =
    (context: ActorContext[ClusterStatusTracker.ClusterEvent]) => PiClusterSingleton(settings, context.self)

  type ActorContextToSingletonBehavior = ActorContext[ClusterStatusTracker.ClusterEvent] => Behavior[PiClusterSingleton.Command]
}

object ClusterStatusTrackerMain {
  def main(args: Array[String]): Unit = {
    System.loadLibrary("rpi_ws281x")

    val settings = Settings()
    val config = settings.config
    val system = ActorSystem[NotUsed](Main(settings), settings.actorSystemName, config)

    // Start Akka HTTP Management extension
    AkkaManagement(system.toClassic).start()
  }
} 
Example 35
Source File: PiClusterSingleton.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package akkapi.cluster



import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorRef, Behavior, PostStop}

object PiClusterSingleton {

  sealed trait Command
  final case object Ping extends Command

  def apply(settings: Settings, clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]): Behavior[Command] = {
    Behaviors.setup { context =>
      new PiClusterSingleton(context, settings, clusterStatusTracker).run()
    }
  }
}

class PiClusterSingleton private (context: ActorContext[PiClusterSingleton.Command],
                         settings: Settings,
                         clusterStatusTracker: ActorRef[ClusterStatusTracker.ClusterEvent]) {

  import PiClusterSingleton._

  // Cluster singleton has been started on this node
  clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonOnNode

  def run(): Behavior[Command] = Behaviors.receiveMessage[Command] {
    case Ping =>
      context.log.info(s"PiClusterSingleton was pinged")
      Behaviors.same
  }.receiveSignal {
    case (_, signal) if signal == PostStop =>
      clusterStatusTracker ! ClusterStatusTracker.PiClusterSingletonNotOnNode
      Behaviors.same
  }

}