Add `d2` diagram sources + rendered SVGs
7 hand-authored `docs/diagrams/*.d2` sources (sketch-mode, grayscale theme, `elk` layout) w/ their pre-rendered fallback SVGs committed under `docs/_diagrams/` (served as-is when no `d2` bin is found, eg. in CI), - `actor_tree`: the hero supervision-tree, - `context_handshake`: seq diagram of the `Start`/`StartAck`/`Started`/`Yield`/`Stop`/`Return` ctx dialog, - `streaming_pipeline`: 4-actor fan-in topology, - `runtime_stack`: the per-actor layer cake, - `debug_lock`: root-tty-lock REPL serialization, - `error_propagation`: one-cancels-all boxed-err flow, - `infected_aio`: guest-mode loop nesting. Rendered w/ `d2` v0.7.1 via `nix run nixpkgs#d2`. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
|
After Width: | Height: | Size: 98 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 98 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
|
@ -0,0 +1,31 @@
|
|||
# tractor docs diagram: the hero supervision tree.
|
||||
# A process tree of trio-task-trees; every arrow is
|
||||
# a parent which *must wait* on its children.
|
||||
vars: {
|
||||
d2-config: {
|
||||
sketch: true
|
||||
theme-id: 1
|
||||
pad: 16
|
||||
layout-engine: elk
|
||||
}
|
||||
}
|
||||
direction: down
|
||||
root: "root actor" {
|
||||
main: "main()"
|
||||
an: "ActorNursery"
|
||||
main -> an: opens
|
||||
}
|
||||
w0: "subactor\n'worker_0'" {
|
||||
tasks: "trio task tree"
|
||||
}
|
||||
w1: "subactor\n'worker_1'" {
|
||||
main: "serve()"
|
||||
an: "ActorNursery"
|
||||
main -> an: opens
|
||||
}
|
||||
gc: "subactor\n'deeper'" {
|
||||
tasks: "trio task tree"
|
||||
}
|
||||
root.an -> w0: "spawns +\nsupervises"
|
||||
root.an -> w1: "spawns +\nsupervises"
|
||||
w1.an -> gc: "spawns +\nsupervises"
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# tractor docs diagram: the inter-actor `Context`
|
||||
# dialog; tractor's SC-transitive msg protocol as
|
||||
# seen from both sides of `Portal.open_context()`.
|
||||
vars: {
|
||||
d2-config: {
|
||||
sketch: true
|
||||
theme-id: 1
|
||||
pad: 16
|
||||
layout-engine: elk
|
||||
}
|
||||
}
|
||||
shape: sequence_diagram
|
||||
parent: "parent task\n(Portal)"
|
||||
child: "child actor task\n(@tractor.context fn)"
|
||||
parent -> child: "Start: open_context(fn, **kwargs)"
|
||||
child -> parent: "StartAck"
|
||||
child -> parent: "Started: await ctx.started(value)"
|
||||
parent -> child: "Yield: stream.send()"
|
||||
child -> parent: "Yield: stream.send()"
|
||||
parent -> child: "Stop: stream closed"
|
||||
child -> parent: "Return: fn return value"
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# tractor docs diagram: multi-actor debugger REPL
|
||||
# serialization via the root actor's tty lock.
|
||||
vars: {
|
||||
d2-config: {
|
||||
sketch: true
|
||||
theme-id: 1
|
||||
pad: 16
|
||||
layout-engine: elk
|
||||
}
|
||||
}
|
||||
shape: sequence_diagram
|
||||
mary: "subactor 'mary'"
|
||||
root: "root actor\n(owns the tty)"
|
||||
bob: "subactor 'bob'"
|
||||
mary -> root: "tractor.pause(): acquire tty lock"
|
||||
root -> mary: "granted: pdb REPL is yours"
|
||||
bob -> root: "tractor.pause(): acquire tty lock"
|
||||
mary -> root: "continue: release lock"
|
||||
root -> bob: "granted: pdb REPL is yours"
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# tractor docs diagram: one-cancels-all error
|
||||
# propagation up a (sub-)actor tree; no zombies,
|
||||
# no lost errors.
|
||||
vars: {
|
||||
d2-config: {
|
||||
sketch: true
|
||||
theme-id: 1
|
||||
pad: 16
|
||||
layout-engine: elk
|
||||
}
|
||||
}
|
||||
direction: down
|
||||
root: "root actor\n(ActorNursery)"
|
||||
gertie: "subactor 'gertie'\n(healthy, gets cancelled)"
|
||||
bobbie: "subactor 'bobbie'\nraises NameError"
|
||||
root -> gertie: supervises
|
||||
root -> bobbie: supervises
|
||||
bobbie -> root: "RemoteActorError\n(boxed NameError)" {
|
||||
style: {
|
||||
stroke-dash: 3
|
||||
}
|
||||
}
|
||||
root -> gertie: "cancel()" {
|
||||
style: {
|
||||
stroke-dash: 3
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# tractor docs diagram: "infected asyncio" mode;
|
||||
# trio runs as a guest on the asyncio loop with
|
||||
# SC supervision linking tasks across both.
|
||||
vars: {
|
||||
d2-config: {
|
||||
sketch: true
|
||||
theme-id: 1
|
||||
pad: 16
|
||||
layout-engine: elk
|
||||
}
|
||||
}
|
||||
direction: down
|
||||
sub: "subactor process (infect_asyncio=True)" {
|
||||
aio: "asyncio event loop" {
|
||||
aiotask: "asyncio.Task\naio_echo_server()"
|
||||
trio: "trio (guest mode)" {
|
||||
triotask: "trio task\n@tractor.context fn"
|
||||
}
|
||||
trio.triotask <-> aiotask: "LinkedTaskChannel\n.send()/.receive()"
|
||||
}
|
||||
}
|
||||
parent: "parent actor (pure trio)"
|
||||
parent <-> sub.aio.trio.triotask: "IPC: Context + MsgStream"
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# tractor docs diagram: the layered runtime view
|
||||
# inside any single actor process.
|
||||
vars: {
|
||||
d2-config: {
|
||||
sketch: true
|
||||
theme-id: 1
|
||||
pad: 16
|
||||
layout-engine: elk
|
||||
}
|
||||
}
|
||||
grid-rows: 4
|
||||
grid-gap: 0
|
||||
app: "your app: plain trio tasks + nurseries"
|
||||
tractor: "tractor runtime: actors, portals,\ncontexts + streams, RPC"
|
||||
ipc: "IPC Channel: msgspec-typed msgs\nover TCP | UDS transports"
|
||||
os: "OS: one process per actor"
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# tractor docs diagram: multi-actor streaming
|
||||
# pipeline topology from
|
||||
# examples/full_fledged_streaming_service.py
|
||||
vars: {
|
||||
d2-config: {
|
||||
sketch: true
|
||||
theme-id: 1
|
||||
pad: 16
|
||||
layout-engine: elk
|
||||
}
|
||||
}
|
||||
direction: right
|
||||
s0: "actor 'streamer_0'" {
|
||||
fn: "stream_data(0)"
|
||||
}
|
||||
s1: "actor 'streamer_1'" {
|
||||
fn: "stream_data(1)"
|
||||
}
|
||||
agg: "actor 'aggregator'" {
|
||||
fn: "aggregate()"
|
||||
}
|
||||
main: "root actor" {
|
||||
fn: "main()"
|
||||
}
|
||||
s0 -> agg: "async for:\nyielded ints"
|
||||
s1 -> agg: "async for:\nyielded ints"
|
||||
agg -> main: "deduped\nstream"
|
||||