Keanu
This module currently contains a simple typed EventBus, and a (local) ActorSystem.
EventBus
Extend EventBus[T]
for your type, e.g.
object IntEventBus extends EventBus[Int]
Then, you can have some implementation extend Subsciber[T]
and subscribe, or pass in an anonymous implementation (e.g.
IntEventBus.subscribe((msg: Int) => println(s"Got message $msg"))
)
Under the hood, the subscriber gets a queue of messages, and a thread that processes them, so things will be processed in order, but asynchronously.
ActorSystem
The AcotrSystem
trait is implemented, and you can have an object extend it for easy singleton access. The apply
method also returns a new instance as well.
let's say you have two actors:
case class EchoActor() extends Actor {
override def onMsg: PartialFunction[Any, Any] = {
case any =>
println(s"Echo: $any")
}
}
case class SampleActor(actorSystem: ActorSystem) extends Actor {
println("starting actor")
var counter = 0
override def onMsg: PartialFunction[Any, Any] = {
case n: Int =>
counter += n
actorSystem.tell[EchoActor]("echo", s"Counter is now $counter")
case "boom" => 1 / 0
case "count" =>
counter
case "print" => println(s"Counter is $counter")
case _ => println("Unhandled")
}
}
You can register props
to the actor system which capture arguments used to create actor instances. This is a bit
unsafe in
the sense that it takes varargs that should be supplied to create the actor, so no compiler checks at the moment.
val as = ActorSystem()
val saProps = ActorContext.props[SampleActor](as)
as.registerProp(saProps)
as.registerProp(ActorContext.props[EchoActor]())
at this point, you can send messages to the actors with the tell
method on the ActorSystem
:
// Helper lambda to send messages to the SampleActor named counter
val counterActor = as.tell[SampleActor]("counter", _)
counterActor(1)
counterActor(2)
counterActor(3)
counterActor(4)
counterActor("boom")
counterActor(5)
counterActor("print")
Actors are indexed based on name and type, so you can have multiple actors of the same type, but they must have unique names (and you can have actors with the same name, as long as they are different types).
If you want to shut down the ActorSystem, you can use the shutdownAwait
method, which will send a PoisonPill
to all
actors, and attempt to wait for their queues to finish processing.