///|
/// The routing strategy for dispatching messages to workers.
pub enum RoutingStrategy {
RoundRobin
Broadcast
Random
}
///|
/// A Router contains a group of worker actors and dispatches messages to them.
pub struct Router[Msg] {
workers : Array[ActorRef[Msg]]
strategy : RoutingStrategy
next_index : Ref[Int]
}
///|
/// Creates a new Router with the given workers and strategy.
pub fn[Msg] Router::new(
workers : Array[ActorRef[Msg]],
strategy : RoutingStrategy,
) -> Router[Msg] {
{ workers, strategy, next_index: { val: 0 } }
}
///|
/// Routes a message to the workers according to the strategy.
pub fn[Msg] Router::route(self : Router[Msg], msg : Msg) -> Unit {
let len = self.workers.length()
if len == 0 {
return
}
match self.strategy {
RoundRobin => {
let idx = self.next_index.val % len
self.next_index.val = idx + 1
self.workers[idx].send(msg)
}
Broadcast =>
for worker in self.workers {
worker.send(msg)
}
Random => {
let seed = self.next_index.val
let next_seed = (seed * 1103515245 + 12345) & 0x7fffffff
self.next_index.val = next_seed
let idx = next_seed % len
self.workers[idx].send(msg)
}
}
}
///|
priv suberror RouterError
///|
/// An Actor behavior that forwards messages to worker actors.
pub async fn[Msg] router_behavior(
_context : Context,
router : Router[Msg],
msg : Msg,
) -> Router[Msg] {
@async.pause()
if false {
raise RouterError
}
router.route(msg)
router
}
///|
fn _dummy_silence_warnings() -> Unit {
let _ = RoundRobin
let _ = Broadcast
let _ = Random
}