pub struct DefaultHandler {
pub sink: Box<dyn IoSink>,
pub read_root: Option<PathBuf>,
pub budget_remaining: Arc<AtomicU64>,
pub budget_ceiling: Option<u64>,
pub program: Option<Arc<Program>>,
pub chat_registry: Option<Arc<ChatRegistry>>,
pub mcp_clients: McpClientCache,
pub streams: Arc<Mutex<StreamRegistry>>,
pub next_stream_id: Arc<AtomicU64>,
/* private fields */
}Fields§
§sink: Box<dyn IoSink>§read_root: Option<PathBuf>Optional read root for io.read — when set, io.read("p") resolves
to read_root.join(p). Lets tests run without touching the real fs.
budget_remaining: Arc<AtomicU64>Per-run budget pool (#225). Arc<AtomicU64> so parallel
branches share one counter without locking. Initialized to
the policy ceiling at handler construction; each call to a
function with declared [budget(N)] deducts N atomically
via note_call_budget. Cloning the handler is intentional
for net.serve / chat handlers — they share the same pool.
budget_ceiling: Option<u64>The original ceiling that budget_remaining started at, kept
for diagnostics so a BudgetExceeded error can report
(used, ceiling) rather than just “exceeded by N”.
program: Option<Arc<Program>>Shared reference to the program, needed by net.serve so the
handler can spin up fresh VMs to dispatch incoming requests.
None if the handler was constructed without a program.
chat_registry: Option<Arc<ChatRegistry>>Chat registry; populated by net.serve_ws’s per-message
dispatch so chat.broadcast / chat.send work from inside
a handler invocation.
mcp_clients: McpClientCacheLRU cache of agent.call_mcp clients keyed by the
command-line string (#197). Avoids spawn-per-call cost
when an agent invokes the same MCP server in tight loops.
Capped — when the cache is full, the least-recently-used
entry is dropped (its subprocess is reaped on Drop).
streams: Arc<Mutex<StreamRegistry>>Stream registry for agent.cloud_stream / stream.next /
stream.collect (#305 slice 3). Keyed by an opaque handle
id; values are the producer iterators. Wrapped in
Arc<Mutex<…>> so par_map workers can share the same
stream pool (when slice-2’s per-worker handler split chains
the registry through).
next_stream_id: Arc<AtomicU64>Monotonic counter for handing out fresh stream handle ids.
Implementations§
Source§impl DefaultHandler
impl DefaultHandler
pub fn new(policy: Policy) -> Self
pub fn with_program(self, program: Arc<Program>) -> Self
pub fn with_chat_registry(self, registry: Arc<ChatRegistry>) -> Self
pub fn with_sink(self, sink: Box<dyn IoSink>) -> Self
pub fn with_read_root(self, root: PathBuf) -> Self
Trait Implementations§
Source§impl EffectHandler for DefaultHandler
impl EffectHandler for DefaultHandler
Source§fn note_call_budget(&mut self, cost: u64) -> Result<(), String>
fn note_call_budget(&mut self, cost: u64) -> Result<(), String>
Per-call budget enforcement (#225). VM calls this before
invoking any function whose signature declares [budget(N)].
The cost N is deducted atomically from the shared pool;
returning Err aborts the call before any frame is pushed.
Source§fn spawn_for_worker(&self) -> Option<Box<dyn EffectHandler + Send>>
fn spawn_for_worker(&self) -> Option<Box<dyn EffectHandler + Send>>
list.par_map worker-handler factory (#305 slice 2).
Builds a fresh DefaultHandler per worker that shares the
budget pool with the parent (Arc<AtomicU64>) so a parallel
batch can’t escape the run-wide budget ceiling. Other state
is intentionally split per-worker:
sink: aStdoutSinkper worker. Tests that capture output via aSharedSinkwrapped inArc<Mutex<…>>see each worker as a fresh handler. Print interleaving on stdout is acceptable; tests that need ordered capture run workloads serially anyway.mcp_clients: a fresh per-worker LRU cache. The parent’s subprocess handles can’t be shared across threads without mutex-serialising every MCP call, which would defeat the parallelism. Cache hit rate is sub-optimal across the first call per worker; warmed caches still amortise within a worker.chat_registry: clonedArc<ChatRegistry>so all workers route into the same chat dispatch layer.program: clonedArc<Program>sonet.serve(if a worker invokes it) sees the same compiled program.