swactor/deps.dot
zacheryasc 1234838361 feat: code DAG visualizer (#11)
Visualize the inter-module code dependency DAG
2026-02-06 14:54:56 +00:00

215 lines
16 KiB
Text

digraph swactor {
rankdir=LR;
fontname="Helvetica";
fontsize=14;
node [fontname="Helvetica", fontsize=11, style=filled, shape=record];
edge [fontname="Helvetica", fontsize=9];
label="swactor — internal dependency DAG";
labelloc=t;
compound=true;
newrank=true;
splines=ortho;
subgraph cluster_error {
label="error";
style="rounded,filled"; fillcolor="#f0f0f0"; color="#888";
Error [label="{Error|0: Box\<dyn std :: error :: Error + Send + Sync + 'static\>}", fillcolor="#e8f5e9"];
}
subgraph cluster_config {
label="config";
style="rounded,filled"; fillcolor="#f0f0f0"; color="#888";
BackoffPolicy [label="{BackoffPolicy|spin_threshold: u32\nyield_threshold: u32\nsleep_increment_us: u64\nsleep_max_us: u64}", fillcolor="#e8f5e9"];
RuntimeConfig [label="{RuntimeConfig|max_actors: usize\nactor_max_messages: usize\nnum_threads: usize\nmailbox_waterlevel: usize\nbackoff_policy: BackoffPolicy}", fillcolor="#e8f5e9"];
}
subgraph cluster_channel {
label="channel";
style="rounded,filled"; fillcolor="#f0f0f0"; color="#888";
HybridChannel [label="{HybridChannel|ring: ArrayQueue\<T\>\noverflow: SegQueue\<T\>}", fillcolor="#fff9c4"];
Receiver [label="{Receiver|queue: Arc\<HybridChannel\<T\>\>}", fillcolor="#fff9c4"];
Sender [label="{Sender|queue: Arc\<HybridChannel\<T\>\>}", fillcolor="#fff9c4"];
}
subgraph cluster_actor {
label="actor";
style="rounded,filled"; fillcolor="#e3f2fd"; color="#1565c0";
Message [label="{«trait» Message}", fillcolor="#bbdefb"];
ActorInterface [label="{«trait» ActorInterface|Incoming(Message)\nResponse(Message)\nhandle((&self, &Ctx, Self::Incoming))}", fillcolor="#bbdefb"];
ActorAddress [label="{ActorAddress|0: [u8; ..]}", fillcolor="#bbdefb"];
Actor [label="{Actor|addr: ActorAddress\nmailbox: Mailbox\<A::Incoming\>\ninner: A}", fillcolor="#bbdefb"];
AnyActor [label="{«trait» AnyActor|tick((&self, &dyn ContextInner) → bool)\ndeliver((&self, Box\<dyn Any + Send\>) → bool)}", fillcolor="#bbdefb"];
}
subgraph cluster_address_map {
label="address_map";
style="rounded,filled"; fillcolor="#f3e5f5"; color="#7b1fa2";
WorkerId [label="{WorkerId|0: usize}", fillcolor="#e1bee7"];
AddressMap [label="{AddressMap|inner: RwLock\<HashMap\<ActorAddress, WorkerId\>\>}", fillcolor="#e1bee7"];
Placement [label="{Placement|next: AtomicUsize\nnum_workers: usize}", fillcolor="#e1bee7"];
}
subgraph cluster_runtime {
label="runtime";
style="rounded,filled"; fillcolor="#fce4ec"; color="#c62828";
Inbox [label="{Inbox|addr: ActorAddress\ninner: Receiver\<M\>}", fillcolor="#ffcdd2"];
RuntimeHandle [label="{RuntimeHandle|runtime: Arc\<Runtime\>\nthreads: Vec\<JoinHandle\<()\>\>}", fillcolor="#ffcdd2"];
Ctx [label="{Ctx|inner: &'a dyn ContextInner\nself_addr: ActorAddress}", fillcolor="#ffcdd2"];
SenderT [label="{«trait» SenderT|try_send_any((&self, Box\<dyn Any + Send\>))}", fillcolor="#ffcdd2"];
Runtime [label="{Runtime|config: RuntimeConfig\naddress_map: Arc\<AddressMap\>\ninbox_registry: Arc\<InboxRegistry\>\ntransfer_txs: Vec\<Sender\<Envelope\>\>\nspawn_txs: Vec\<Sender\<(ActorAddress, Box\<dyn AnyActor\>)\>\>\nplacement: Placement\nis_running: AtomicBool\nsingle_worker: Option\<RefCell\<Worker\>\>\npending_workers: Option\<Vec\<Worker\>\>}", fillcolor="#ffcdd2"];
Envelope [label="{Envelope|dest: ActorAddress\npayload: Box\<dyn Any + Send\>}", fillcolor="#ffcdd2"];
InboxRegistry [label="{InboxRegistry|senders: RwLock\<HashMap\<ActorAddress, Arc\<dyn SenderT\>\>\>}", fillcolor="#ffcdd2"];
ContextInner [label="{«trait» ContextInner|send_any((&self, ActorAddress, Box\<dyn Any + Send\>) → Result\<(), Error\>)\nspawn_any((&self, ActorAddress, Box\<dyn AnyActor\>) → Result\<(), Error\>)\nmailbox_waterlevel((&self) → usize)}", fillcolor="#ffcdd2"];
}
subgraph cluster_worker {
label="worker";
style="rounded,filled"; fillcolor="#fff3e0"; color="#e65100";
TickContext [label="{TickContext|address_map: &'a AddressMap\ntransfer_txs: &'a [Sender\<Envelope\>]\nspawn_txs: &'a [Sender\<(ActorAddress, Box\<dyn AnyActor\>)\>]\nplacement: &'a Placement\ninbox_registry: &'a InboxRegistry\nconfig: &'a RuntimeConfig}", fillcolor="#ffe0b2"];
Worker [label="{Worker|id: WorkerId\npool: ActorPool\ntransfer_rx: Receiver\<Envelope\>\nspawn_rx: Receiver\<(ActorAddress, Box\<dyn AnyActor\>)\>}", fillcolor="#ffe0b2"];
WorkerContext [label="{WorkerContext|worker_id: WorkerId\naddress_map: &'a AddressMap\ntransfer_txs: &'a [Sender\<Envelope\>]\nspawn_txs: &'a [Sender\<(ActorAddress, Box\<dyn AnyActor\>)\>]\nplacement: &'a Placement\ninbox_registry: &'a InboxRegistry\nconfig: &'a RuntimeConfig\npending_local: &'a RefCell\<Vec\<(ActorAddress, Box\<dyn Any + Send\>)\>\>}", fillcolor="#ffe0b2"];
ActorPool [label="{ActorPool|actors: HashMap\<ActorAddress, Box\<dyn AnyActor\>\>}", fillcolor="#ffe0b2"];
Mailbox [label="{Mailbox|queue: VecDeque\<M\>\nwaterlevel: usize}", fillcolor="#ffe0b2"];
}
subgraph cluster_python {
label="python (feature-gated)";
style="rounded,dashed,filled"; fillcolor="#f5f5f5"; color="#999";
PyMsg [label="{PyMsg|0: PyObject}", fillcolor="#d7ccc8"];
PyActorAddress [label="{PyActorAddress|inner: ActorAddress}", fillcolor="#d7ccc8"];
Effect [label="{«enum» Effect|Send \{ addr: ActorAddress, msg: PyObject \}\nSpawn \{ addr: ActorAddress, handler: PyObject \}}", fillcolor="#d7ccc8"];
PyCtx [label="{PyCtx|self_addr: ActorAddress\neffects: RefCell\<Vec\<Effect\>\>}", fillcolor="#d7ccc8"];
PyActor [label="{PyActor|handler: PyObject}", fillcolor="#d7ccc8"];
PyInbox [label="{PyInbox|inner: Inbox\<PyMsg\>}", fillcolor="#d7ccc8"];
PyRuntimeConfig [label="{PyRuntimeConfig|num_threads: usize\nmax_actors: usize\nactor_max_messages: usize\nmailbox_waterlevel: usize\nspin_threshold: u32\nyield_threshold: u32\nsleep_increment_us: u64\nsleep_max_us: u64}", fillcolor="#d7ccc8"];
PyRuntime [label="{PyRuntime|inner: Option\<Runtime\>}", fillcolor="#d7ccc8"];
PyRuntimeHandle [label="{PyRuntimeHandle|inner: Option\<RuntimeHandle\>}", fillcolor="#d7ccc8"];
}
// ═══════════════════════════════════════════════════════════════════
// INTRA-MODULE EDGES (within same cluster)
// ═══════════════════════════════════════════════════════════════════
ActorInterface -> Message [label="Incoming", style=dashed, color="#666", penwidth=1];
Actor -> ActorAddress [label="addr", style=dashed, color="#666", penwidth=1];
Actor -> AnyActor [label="impl", style=dotted, color="#666", penwidth=1];
Worker -> ActorPool [label="pool", style=dashed, color="#666", penwidth=1];
Worker -> TickContext [label="tick_once() param", style=dashed, color="#666", penwidth=1];
Receiver -> HybridChannel [label="queue", style=dashed, color="#666", penwidth=1];
Sender -> HybridChannel [label="queue", style=dashed, color="#666", penwidth=1];
Receiver -> Sender [label="new_sender() param", style=dashed, color="#666", penwidth=1];
AddressMap -> WorkerId [label="inner", style=dashed, color="#666", penwidth=1];
Placement -> WorkerId [label="next_worker() param", style=dashed, color="#666", penwidth=1];
RuntimeConfig -> BackoffPolicy [label="backoff_policy", style=dashed, color="#666", penwidth=1];
RuntimeHandle -> Runtime [label="runtime", style=dashed, color="#666", penwidth=1];
Ctx -> ContextInner [label="inner", style=dashed, color="#666", penwidth=1];
Runtime -> InboxRegistry [label="inbox_registry", style=dashed, color="#666", penwidth=1];
Runtime -> Envelope [label="transfer_txs", style=dashed, color="#666", penwidth=1];
InboxRegistry -> SenderT [label="senders", style=dashed, color="#666", penwidth=1];
Runtime -> Inbox [label="new_inbox() param", style=dashed, color="#666", penwidth=1];
Runtime -> RuntimeHandle [label="run() param", style=dashed, color="#666", penwidth=1];
Runtime -> ContextInner [label="impl", style=dotted, color="#666", penwidth=1];
PyCtx -> Effect [label="effects", style=dashed, color="#666", penwidth=1];
PyInbox -> PyMsg [label="inner", style=dashed, color="#666", penwidth=1];
PyCtx -> PyActorAddress [label="self_addr() param", style=dashed, color="#666", penwidth=1];
PyInbox -> PyActorAddress [label="addr() param", style=dashed, color="#666", penwidth=1];
PyRuntime -> PyRuntimeConfig [label="new() param", style=dashed, color="#666", penwidth=1];
PyRuntime -> PyActorAddress [label="spawn() param", style=dashed, color="#666", penwidth=1];
PyRuntime -> PyInbox [label="inbox() param", style=dashed, color="#666", penwidth=1];
PyRuntime -> PyRuntimeHandle [label="run() param", style=dashed, color="#666", penwidth=1];
PyRuntimeHandle -> PyActorAddress [label="spawn() param", style=dashed, color="#666", penwidth=1];
PyRuntimeHandle -> PyInbox [label="inbox() param", style=dashed, color="#666", penwidth=1];
// ═══════════════════════════════════════════════════════════════════
// CROSS-MODULE EDGES (the real dependency DAG)
// ═══════════════════════════════════════════════════════════════════
// --- channel depends on runtime ---
Sender -> SenderT [label="impl", style=dotted, color="#666", penwidth=1.5];
// --- actor depends on runtime ---
ActorInterface -> Ctx [label="handle", style=solid, color="#1565c0", penwidth=1.5];
AnyActor -> ContextInner [label="tick", style=solid, color="#1565c0", penwidth=1.5];
Actor -> ContextInner [label="tick() param", style=solid, color="#1565c0", penwidth=1.5];
// --- actor depends on worker ---
Actor -> Mailbox [label="mailbox", style=solid, color="#1565c0", penwidth=1.5];
// --- address_map depends on actor ---
AddressMap -> ActorAddress [label="inner", style=solid, color="#7b1fa2", penwidth=1.5];
// --- runtime depends on error ---
ContextInner -> Error [label="send_any", style=solid, color="#c62828", penwidth=1.5];
Ctx -> Error [label="send() param", style=solid, color="#c62828", penwidth=1.5];
Runtime -> Error [label="spawn() param", style=solid, color="#c62828", penwidth=1.5];
InboxRegistry -> Error [label="try_deliver() param", style=solid, color="#c62828", penwidth=1.5];
// --- runtime depends on config ---
Runtime -> RuntimeConfig [label="config", style=solid, color="#c62828", penwidth=1.5];
// --- runtime depends on channel ---
Inbox -> Receiver [label="inner", style=solid, color="#c62828", penwidth=1.5];
Runtime -> Sender [label="transfer_txs", style=solid, color="#c62828", penwidth=1.5];
// --- runtime depends on actor ---
Inbox -> ActorAddress [label="addr", style=solid, color="#c62828", penwidth=1.5];
Ctx -> ActorAddress [label="self_addr", style=solid, color="#c62828", penwidth=1.5];
Runtime -> ActorAddress [label="spawn_txs", style=solid, color="#c62828", penwidth=1.5];
Runtime -> AnyActor [label="spawn_txs", style=solid, color="#c62828", penwidth=1.5];
Envelope -> ActorAddress [label="dest", style=solid, color="#c62828", penwidth=1.5];
InboxRegistry -> ActorAddress [label="senders", style=solid, color="#c62828", penwidth=1.5];
ContextInner -> ActorAddress [label="send_any", style=solid, color="#c62828", penwidth=1.5];
ContextInner -> AnyActor [label="spawn_any", style=solid, color="#c62828", penwidth=1.5];
// --- runtime depends on address_map ---
Runtime -> AddressMap [label="address_map", style=solid, color="#c62828", penwidth=1.5];
Runtime -> Placement [label="placement", style=solid, color="#c62828", penwidth=1.5];
// --- runtime depends on worker ---
Runtime -> Worker [label="single_worker", style=solid, color="#c62828", penwidth=1.5];
// --- worker depends on error ---
WorkerContext -> Error [label="send_any() param", style=solid, color="#e65100", penwidth=1.5];
// --- worker depends on config ---
TickContext -> RuntimeConfig [label="config", style=solid, color="#e65100", penwidth=1.5];
WorkerContext -> RuntimeConfig [label="config", style=solid, color="#e65100", penwidth=1.5];
Worker -> BackoffPolicy [label="run() param", style=solid, color="#e65100", penwidth=1.5];
// --- worker depends on channel ---
TickContext -> Sender [label="transfer_txs", style=solid, color="#e65100", penwidth=1.5];
Worker -> Receiver [label="transfer_rx", style=solid, color="#e65100", penwidth=1.5];
WorkerContext -> Sender [label="transfer_txs", style=solid, color="#e65100", penwidth=1.5];
// --- worker depends on actor ---
TickContext -> ActorAddress [label="spawn_txs", style=solid, color="#e65100", penwidth=1.5];
TickContext -> AnyActor [label="spawn_txs", style=solid, color="#e65100", penwidth=1.5];
Worker -> ActorAddress [label="spawn_rx", style=solid, color="#e65100", penwidth=1.5];
Worker -> AnyActor [label="spawn_rx", style=solid, color="#e65100", penwidth=1.5];
WorkerContext -> ActorAddress [label="spawn_txs", style=solid, color="#e65100", penwidth=1.5];
WorkerContext -> AnyActor [label="spawn_txs", style=solid, color="#e65100", penwidth=1.5];
ActorPool -> ActorAddress [label="actors", style=solid, color="#e65100", penwidth=1.5];
ActorPool -> AnyActor [label="actors", style=solid, color="#e65100", penwidth=1.5];
// --- worker depends on address_map ---
TickContext -> AddressMap [label="address_map", style=solid, color="#e65100", penwidth=1.5];
TickContext -> Placement [label="placement", style=solid, color="#e65100", penwidth=1.5];
Worker -> WorkerId [label="id", style=solid, color="#e65100", penwidth=1.5];
WorkerContext -> WorkerId [label="worker_id", style=solid, color="#e65100", penwidth=1.5];
WorkerContext -> AddressMap [label="address_map", style=solid, color="#e65100", penwidth=1.5];
WorkerContext -> Placement [label="placement", style=solid, color="#e65100", penwidth=1.5];
// --- worker depends on runtime ---
TickContext -> Envelope [label="transfer_txs", style=solid, color="#e65100", penwidth=1.5];
TickContext -> InboxRegistry [label="inbox_registry", style=solid, color="#e65100", penwidth=1.5];
Worker -> Envelope [label="transfer_rx", style=solid, color="#e65100", penwidth=1.5];
WorkerContext -> Envelope [label="transfer_txs", style=solid, color="#e65100", penwidth=1.5];
WorkerContext -> InboxRegistry [label="inbox_registry", style=solid, color="#e65100", penwidth=1.5];
WorkerContext -> ContextInner [label="impl", style=dotted, color="#e65100", penwidth=1.5];
ActorPool -> ContextInner [label="tick_all() param", style=solid, color="#e65100", penwidth=1.5];
// --- python depends on actor ---
PyActorAddress -> ActorAddress [label="inner", style=solid, color="#999", penwidth=1.5];
Effect -> ActorAddress [label="Send", style=solid, color="#999", penwidth=1.5];
PyCtx -> ActorAddress [label="self_addr", style=solid, color="#999", penwidth=1.5];
PyActor -> ActorInterface [label="impl", style=dotted, color="#999", penwidth=1.5];
// --- python depends on runtime ---
PyInbox -> Inbox [label="inner", style=solid, color="#999", penwidth=1.5];
PyRuntime -> Runtime [label="inner", style=solid, color="#999", penwidth=1.5];
PyRuntimeHandle -> RuntimeHandle [label="inner", style=solid, color="#999", penwidth=1.5];
PyActor -> Ctx [label="handle() param", style=solid, color="#999", penwidth=1.5];
}