///|
/// A simulator for a cluster network connecting multiple ActorSystems.
/// Supports packet drop, latency, and remote message delivery simulation.
pub struct NetworkSimulator {
nodes : Map[String, ActorSystem]
mut drop_probability : Int // 0 to 100
mut latency : Int // in milliseconds
mut seed : Int
}
///|
/// Creates a new NetworkSimulator.
pub fn NetworkSimulator::new() -> NetworkSimulator {
{ nodes: Map([]), drop_probability: 0, latency: 0, seed: 123456789 }
}
///|
/// Registers a node (ActorSystem) with a unique name in the network.
pub fn NetworkSimulator::register_node(
self : NetworkSimulator,
name : String,
system : ActorSystem,
) -> Unit {
self.nodes.set(name, system)
}
///|
/// Sets the probability (0-100) of dropping any packet sent over the network.
pub fn NetworkSimulator::set_drop_probability(
self : NetworkSimulator,
prob : Int,
) -> Unit {
self.drop_probability = prob
}
///|
/// Sets the network transmission latency in milliseconds.
pub fn NetworkSimulator::set_latency(
self : NetworkSimulator,
lat : Int,
) -> Unit {
self.latency = lat
}
///|
fn NetworkSimulator::next_random(self : NetworkSimulator) -> Int {
self.seed = (self.seed * 1103515245 + 12345) & 0x7fffffff
self.seed
}
///|
/// Sends a serialized message across the network to a target actor on a target node.
pub fn NetworkSimulator::send_remote(
self : NetworkSimulator,
target_node : String,
target_actor_id : Int,
serialized_msg : String,
) -> Unit {
let should_drop = if self.drop_probability > 0 {
let rand = self.next_random()
rand % 100 < self.drop_probability
} else {
false
}
if should_drop {
return
}
match self.nodes.get(target_node) {
Some(system) =>
system.group.spawn_bg(no_wait=true, () => {
try {
if self.latency > 0 {
@async.sleep(self.latency)
}
let reg = system.registry.val
for control in reg {
if control.id == target_actor_id {
(control.send_user_serialized)(serialized_msg)
break
}
}
} catch {
_ => ()
}
})
None => ()
}
}
///|
/// A reference to a remote actor in the cluster.
pub struct RemoteRef[Msg] {
target_node : String
target_actor_id : Int
simulator : NetworkSimulator
serializer : (Msg) -> String
}
///|
/// Creates a new RemoteRef pointing to a specific actor on a target node.
pub fn[Msg] RemoteRef::new(
target_node : String,
target_actor_id : Int,
simulator : NetworkSimulator,
serializer : (Msg) -> String,
) -> RemoteRef[Msg] {
{ target_node, target_actor_id, simulator, serializer }
}
///|
/// Sends a message to the remote actor by serializing it and routing it through the network simulator.
pub fn[Msg] RemoteRef::send(self : RemoteRef[Msg], msg : Msg) -> Unit {
let serialized = (self.serializer)(msg)
self.simulator.send_remote(self.target_node, self.target_actor_id, serialized)
}