swactor/crates/iroh-driver/src/lib.rs

37 lines
1.6 KiB
Rust
Raw Normal View History

//! `iroh-driver` — iroh-backed transport driver for the actorized distribution stack.
//!
//! This crate owns the concrete iroh endpoint/QUIC/relay machinery. The
//! distribution crate owns cluster dynamics, protocol actors, routing claims, and
//! wire message definitions.
feat(engine): substrate-neutral execution engine abstraction Introduce the swactor engine: a swactor-owned composite that retains a selected execution substrate, drives the core runtime, and hosts the async/blocking/timer work that backs actors. Integrations receive one cloneable EngineHandle and never construct or borrow a raw Tokio runtime/handle. Engine crate (crates/engine): - The contract: spawn / spawn_blocking / timer / interval / now, a per-implementation capability model with construction-time binding (require()), and engine-owned time. The engine owns all progression; actor handlers stay synchronous and never .await. - TokioBackend owns the Tokio runtime and schedules core ticks and supporting futures on it; SteppingBackend is a single-threaded deterministic scheduler with virtual time (the non-Tokio portability proof). Core is driven through its existing tick() surface; a self-rescheduling CoreDriver is installed at construction and is the sole place permitted to call try_tick. iroh-driver: - Receives an EngineHandle instead of a raw Tokio Handle. Accepts, reads, dials, writes, endpoint construction, and teardown schedule through it; required capabilities (tasks/timers/io) are validated before the endpoint binds. Engine-hosted interval pumps drive actor-bridge, datastream, and edge ingress. myelin: - One node/orchestrator engine owns core, protocol tick injection, and transport progression; the application loop only drains integration-owned queues. Stage-shard process readers, delayed actor messages, helper stdout/stderr, prompt RPC, and CPU sampling all schedule through the engine (spawn_blocking / engine tasks / timers). - Removed the split-engine APIs: install_actor_bridge_pump(period) and spawn_protocol_ticker(period) use each component's stored engine; deleted the no-op pump_network callback and its plumbing; deleted the dashboard raw-Tokio/standalone-runtime conveniences. Enforcement: - A clippy disallowed-methods boundary forbids direct runtime/scheduling/ time/core-driving bypasses, denied in swactor-engine, iroh-driver, and myelin. Retained excluded uses (VastAI provider, provider process supervision/log capture, OS-signal/stdin/process-control sequencing) carry narrow allowances with reasons. Verification: - Engine contract + unit tests (incl. the SteppingBackend portability proof), iroh integration tests (capability rejection before binding, multi-node actor behavior), and a production execution-composition smoke test that observes engine-driven actor progress with no ambient Tokio runtime and no manual tick/pump. Workspace all-target/all-feature clippy and tests are green. Specs co-located with their crates: ENGINE_SPEC.md in crates/engine, IROH_DRIVER_SPEC.md in crates/iroh-driver. VastAI remains explicitly out of scope pending its separate redesign.
2026-08-10 20:23:03 +00:00
// Engine boundary enforcement: disallowed scheduling/time/core-driving methods
// are hard errors in this crate (ENGINE_SPEC.md §2). All engine-hosted
// work goes through `EngineHandle`.
#![deny(clippy::disallowed_methods)]
pub mod blob_transfer;
pub mod edge_transport;
pub mod endpoint_advertisement;
pub mod iroh_driver;
provisioning-reconciler-demo: wire-announce readiness + --docker node kind Replace the per-attempt key-file side channel (DEMO_NODE_KEY_FILE, read_key_report, JoinCheck) with a control-plane announce: node roles send a tagged gossip frame {attempt, logical_node, key_hex, endpoint_addr_json} after joining and every heartbeat thereafter. - iroh-driver: IrohDriver::send_tagged_gossip — fire-and-forget tag-routed gossip egress for bridge-less clients (reuses cached/join connections, dials with backoff). - provisioning: BootstrapMsg::Announce — first delivery while bootstrapping completes the attempt (collector + exactly-once Bootstrapped report); duplicates, misrouted attempts, and terminal-phase announces drop. Unit-tested. - xtask demo: AnnounceActor decodes the tag-routed frame and forwards by attempt to the owning bootstrap actor; last_announce_ms is the wire heartbeat. LocalProcessLogic keeps only process lifecycle. - --docker: DockerProcessLogic (kind "docker") — attached "docker run --rm" child on a per-run labeled bridge network (foreign-node masking: per-container IPs, gateway-dialed supervisor). Standalone scratch image from the static-musl xtask binary (37MB), staged one-file build context. The container is force-removed on every terminal path so a SIGKILLed docker CLI cannot orphan a running container. - Cleanup: no volumes/mounts; label-filtered exit sweep (SIGINT and SIGTERM both drain first) + startup sweep of stale demo resources; images persist per run token. Verified live: process kind (kill -> replacement in 3.4s, provision/ remove/kill waves, zero orphans) and docker kind (8-node abuse waves across docker kill, mid-provision control kills, CLI SIGKILL orphans force-removed, SIGKILL-crash leftovers swept on restart, clean exits leave zero containers/networks/CLIs). provisioning 22 + iroh-driver 13 tests pass.
2026-08-16 16:30:52 +00:00
pub mod telemetry_transport;
pub use blob_transfer::{IrohBlobTransferReceiver, IrohBlobTransferSender};
pub use endpoint_advertisement::{
EndpointAddrMask, MVP_IROH_ENDPOINT_ADDR_MASK_ENV, advertised_endpoint,
};
pub use iroh_driver::{
ActorBridgeConfig, ActorRegistrar, ConnType, EdgeConnector, IrohDriver, IrohDriverConfig,
JoinPhase, JoinStatus, TelemetryPublishHandle, conn_type_of, discover_lan_ips,
};
Move all edge logic into data-plane; reduce iroh-driver to a byte-transport port Duty mixing between iroh-driver and data-plane is resolved: the transport crate now owns only byte pumping, and the data-plane owns every edge semantic. data-plane: - ids.rs: single EdgeId/RingId/StreamId/NodeId/RunId/LeaseRequestId/ ActorAddress definitions; arena, edge_lifecycle, and ring re-export them (previously duplicated per module) - edge_wire.rs: the whole transport contract — WireEvent, EdgeWriter, and the EdgeTransport port (associated Writer/PeerAddr types) - edge_runtime.rs: EdgeRuntime composition engine absorbing iroh-driver's driver_pumps bookkeeping, the EdgeEstablisher lifecycle drive, arena leasing, ingress stream buffering with object-record parsing, and ring writes; effects go through a WorkerPort trait; progress surfaces as structured Observations the application maps to telemetry/agent messages - delete superseded test-only layers: actor.rs (DataPlaneNodeActor), edge_actor.rs, ingress.rs, egress.rs and their guarantee tests - fold ObjectIdAllocator into object_record (now edge-free, starts at 1) iroh-driver: - edge_transport speaks pure data_plane::edge_wire vocabulary; EdgeSendHandle implements EdgeWriter; IrohDriver implements EdgeTransport (PeerAddr = EndpointAddr) — the entire edge surface is open_writer + drain_events - delete driver_pumps.rs; new dependency on data-plane (no cycle) - IROH_DRIVER_SPEC §5 updated for the new module set and edge boundary myelin: - WorkerEdgeRuntime shrinks from ~830 lines of hand glue to an EdgeRuntime holder plus a tinygrad WorkerPort impl and observation reporting; the driver-event/edge-event translation layers and newtype re-wrapping are gone - orchestration/app.rs and job edge drains consume WireEvent Tests: data-plane 31 (5 new EdgeRuntime contract tests), iroh-driver 13, myelin 65 — all green.
2026-08-16 17:49:45 +00:00
pub use edge_transport::{EDGE_ALPN, EdgeSendHandle};
pub use telemetry_transport::{
PullCollectorConfig, PullCollectorHandle, TELEMETRY_ALPN, TelemetryQuicHeader,
TelemetryQuicRead, TelemetryQuicWriteStats, read_events_from_stream, read_next_event,
feat(myelin): enforce actor-owned control flow Architecture enforcement: - Install a repository-owned rustc wrapper for ordinary cargo check, build, and test commands. Resolve compiler item identities so renamed imports and helper wrappers cannot hide spawning, timing, blocking, polling, thread, or runtime-driving capabilities. - Define the execution-owner crates and reject dependencies from those substrates back into Myelin policy. Add compile-pass and compile-fail contracts for actor helpers, execution owners, test waits, forbidden capabilities, suppression attempts, and owner dependency inversions. Execution ownership: - Add engine-owned actor timers with cancellation and generation identity, then migrate lifecycle deadlines and protocol ticks off application tasks. Keep networking, process output, telemetry, and blocking provider calls in their approved I/O substrates. - Move process spawn, wait, signal, Unix listener, and output-following mechanics into swactor-process. Isolate Vast.ai blocking HTTP mechanics behind its adapter while actors retain retry, recovery, and provisioning decisions. Myelin control flow: - Rework manual control, worker lifecycle, provisioning, provider recovery, job deployment, distribution, edge orchestration, and shutdown as actor state transitions and typed effects. Preserve durable provider adoption and command outcomes across graceful and abrupt restarts. - Replace controller loops and timer-forwarding tasks with actor messages; leave substrate tasks as cancellable observation streams with no durable policy state. Properties and resource ownership: - Add deterministic engine and component properties, a stateful mock-VastAI lifecycle model, persisted regression cases, controlled fault injection, and a bounded nightly workflow covering restart and teardown behavior. - Terminate reply observers, cancel telemetry collectors, bound dashboard projections, and release child observers, file descriptors, process records, and inode-verified Unix sockets on every terminal path. Verified with the compiler-policy contracts, 105 Myelin library tests, 32 swactor-process tests, telemetry cancellation contracts, randomized stateful restart cases, cargo check, and formatting checks.
2026-08-19 21:38:14 +00:00
read_next_uni_from_connection, read_pull_request, read_stream_header, read_stream_into_fanout,
spawn_connection_reader, spawn_pull_collector, spawn_pull_collector_to_actor,
provisioning-reconciler-demo: wire-announce readiness + --docker node kind Replace the per-attempt key-file side channel (DEMO_NODE_KEY_FILE, read_key_report, JoinCheck) with a control-plane announce: node roles send a tagged gossip frame {attempt, logical_node, key_hex, endpoint_addr_json} after joining and every heartbeat thereafter. - iroh-driver: IrohDriver::send_tagged_gossip — fire-and-forget tag-routed gossip egress for bridge-less clients (reuses cached/join connections, dials with backoff). - provisioning: BootstrapMsg::Announce — first delivery while bootstrapping completes the attempt (collector + exactly-once Bootstrapped report); duplicates, misrouted attempts, and terminal-phase announces drop. Unit-tested. - xtask demo: AnnounceActor decodes the tag-routed frame and forwards by attempt to the owning bootstrap actor; last_announce_ms is the wire heartbeat. LocalProcessLogic keeps only process lifecycle. - --docker: DockerProcessLogic (kind "docker") — attached "docker run --rm" child on a per-run labeled bridge network (foreign-node masking: per-container IPs, gateway-dialed supervisor). Standalone scratch image from the static-musl xtask binary (37MB), staged one-file build context. The container is force-removed on every terminal path so a SIGKILLed docker CLI cannot orphan a running container. - Cleanup: no volumes/mounts; label-filtered exit sweep (SIGINT and SIGTERM both drain first) + startup sweep of stale demo resources; images persist per run token. Verified live: process kind (kill -> replacement in 3.4s, provision/ remove/kill waves, zero orphans) and docker kind (8-node abuse waves across docker kill, mid-provision control kills, CLI SIGKILL orphans force-removed, SIGKILL-crash leftovers swept on restart, clean exits leave zero containers/networks/CLIs). provisioning 22 + iroh-driver 13 tests pass.
2026-08-16 16:30:52 +00:00
spawn_pull_server, spawn_subscription_writer, write_available_subscription, write_event,
write_pull_request, write_subscription_until_closed,
};