spike: PERSISTENT next/ kernel is viable — unblocks RA-live + TA-live
The shared prerequisite for both live steps was: does a next/ kernel process hold gen_server state (flow_store) across HTTP requests? Confirmed yes. plans/ra_kernel.erl is a minimal kernel (flow_store + register the publish-digest flow, then a blocking http:listen that keeps the er-scheduler + gen_server alive); plans/ra-kernel-spike.sh boots it as a background sx_server and drives it with two SEPARATE curls: GET /start suspends instance 1, GET /resume resumes that SAME live instance → done. So durable suspend→resume across requests works on a persistent kernel. Design decision (per the discussion): chose the persistent-kernel path (B) over host-side replay-log (A). B serves BOTH durability (RA) and federation (TA) on one fed-sx-native substrate and exposes the full next/ kernel (projections, outbox, actor model); A only solves flow durability and mixes Erlang into the host process. The er-scheduler-context bug (which kills an in-process kernel, option C) does NOT bite a separate-process kernel — er-bif-http-listen spawns each handler in-scheduler, so gen_server:call completes. Gotchas recorded: a blocking listener hangs any in-process erlang-eval-ast (the kernel must be a dedicated TCP-driven process), and binary =:= is buggy (always true) so routes must pattern-match paths as byte-list binaries. RA-live + TA-live are now BUILD work (a real kernel service + the host as HTTP client + the actor model), not research — the prerequisite is proven. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -264,11 +264,20 @@ the flow instance Id is the resume handle.
|
||||
spawned processes across separate erlang-eval-ast invocations"). So a boot-per-call proves the
|
||||
module (done), but TRUE async (suspend → return the request → resume LATER in another call) needs a
|
||||
PERSISTENT next/ kernel PROCESS holding flow_store — the async boundary (DEBT #3) is deeper than
|
||||
"off the request path". REMAINING: (a) stand up a long-lived next/ kernel (nx_kernel/http_server
|
||||
already run persistently for TCP) that RA talks to; (b) wire a DURABLE behavior binding ({:erl-flow
|
||||
"blog_digest" :needs (effect branch suspend)}) into the live publish engine, routed to RA via
|
||||
select-runner; (c) the resumed completion re-enters via the transport inbound + behavior/pump.
|
||||
The runner + marshalling + suspend/resume mechanics are all proven; this is process lifecycle + wiring.
|
||||
"off the request path".
|
||||
**PERSISTENT-KERNEL SPIKE PASSED 2026-07-02 (plans/ra-kernel-spike.sh + ra_kernel.erl).** A
|
||||
background sx_server running `ra_kernel:start` (flow_store + a blocking http:listen keeps the
|
||||
er-scheduler + gen_server alive) survives across HTTP requests: GET /start suspends instance 1, a
|
||||
SEPARATE GET /resume resumes that SAME live instance → done. So a persistent kernel process IS
|
||||
viable, and the er-scheduler-context fear does NOT bite (er-bif-http-listen spawns each handler
|
||||
IN-scheduler, so gen_server:call completes). Gotchas: start blocking http:listen hangs any
|
||||
in-process erlang-eval-ast (so the kernel is a DEDICATED process, driven over TCP, not epoch cmds);
|
||||
binary =:= is buggy (always true) → dispatch paths by PATTERN (byte-list binaries), not =:=.
|
||||
REMAINING for RA-live: (a) a real kernel module (flow + inbox/outbox routes) run as a persistent
|
||||
service (its own container/placement); (b) the host's RA runner POSTs activities to it (start) +
|
||||
the completion re-enters via the transport inbound + behavior/pump (resume); (c) a durable behavior
|
||||
binding ({:erl-flow "blog_digest" :needs (effect branch suspend)}) routed to RA via select-runner.
|
||||
The prerequisite is PROVEN; this is now build (kernel service + host HTTP client), not research.
|
||||
|
||||
## TA — the FED-SX TRANSPORT adapter ← federation proper
|
||||
- [x] **TA TRANSPORT BUILT + the federation LOOP PROVEN 2026-07-02.** lib/host/ta.sx — a seam
|
||||
@@ -316,6 +325,15 @@ covers everything until a DAG's cost/latency/placement forces the substrate.
|
||||
activities), so business logic can change state, which federates, which triggers more flows.
|
||||
|
||||
## Progress log (newest first)
|
||||
- 2026-07-02 — PERSISTENT-KERNEL SPIKE PASSED (plans/ra-kernel-spike.sh + ra_kernel.erl). The shared
|
||||
prerequisite for RA-live + TA-live is REACHABLE: a background sx_server (flow_store + blocking
|
||||
http:listen) holds gen_server state across HTTP requests — /start suspends instance 1, a separate
|
||||
/resume resumes the SAME live instance → done. The er-scheduler-context fear doesn't bite (handlers
|
||||
spawn in-scheduler). Chose the persistent-kernel path (B) over host-side replay-log (A) — it serves
|
||||
BOTH durability + federation on one fed-sx-native substrate + gives the full next/ kernel. Gotchas:
|
||||
a blocking listener hangs in-process erlang-eval-ast (kernel = a dedicated TCP-driven process);
|
||||
binary =:= buggy → pattern-match paths. RA-live/TA-live are now BUILD (kernel service + host HTTP
|
||||
client + actor model), not research. NEXT: build the real kernel service + wire the host as client.
|
||||
- 2026-07-02 — TA TRANSPORT built + the federation LOOP proven (lib/host/ta.sx, ta 5/5). A seam
|
||||
transport over a directional wire (serialization boundary; activities cross as SX-source). Proven
|
||||
in-memory: A emits → wire → B pump → B's engine fires ITS behavior on A's activity (directional, no
|
||||
|
||||
Reference in New Issue
Block a user