CU3 — The shape of the execution
g.plan() # how it is going to be walkedStatus: closed. 39 tests in Rust, 38 in Python.
The question: are there several ways of executing a graph?
Section titled “The question: are there several ways of executing a graph?”Yes — local, remote, by turns, in parallel. But the original’s answer is not a
trait of executors: it is an enum of ten variants (Sequence | Parallel | Execute | Step | Loop | Branch | Remote | Composite | Stream | Empty) and a
single match. Remote is not another executor: it is a variant that wraps a
sub-plan.
It is the same principle we had already found — variation as data, not as a subtype — and it has a concrete advantage over a bare function or a trait: when a variant is added, the compiler points at the single place that has to decide what to do with it. A wildcard arm would say nothing.
The missing piece: compiling
Section titled “The missing piece: compiling”Between the structure and the engine there is now a step:
compile(&Graph, &Catalog) -> Plan. It decides the shape, and along the way
everything structural is detected before anything executes. The engine no
longer works out where each node’s input comes from: the plan says so.
Decisions taken
Section titled “Decisions taken”Planis an enum, not a trait. Closed, exhaustive, no wildcards.Executoris a type, not a bare function: executing needs context (today the store; tomorrow a cache and events). That “tomorrow” is what the original callsGraphSession.ValuelosesTensorand gainsNumberandList. Nobody was producing a shaped tensor, and the round trip to Python has to be symmetric: what goes in as a list comes out as a list.
What did NOT go in
Section titled “What did NOT go in”Plan::Remote. There is no transport, so it would be a variant nobody can
execute. What the enum buys is precisely that adding it the day there is a worker
is one more variant, and that the compiler points at every place that has to
decide. (It arrived in CU12.)