From 87fe47fd7f5daf22470a3954789202bc74328ccc Mon Sep 17 00:00:00 2001 From: Eric Wendland Date: Sun, 5 Jul 2026 17:27:42 +0200 Subject: [PATCH] refactor: extract node runtime state --- crates/geth-node/src/lib.rs | 75 ++----------------------- crates/geth-node/src/runtime.rs | 82 ++++++++++++++++++++++++++++ docs/production-readiness-roadmap.md | 6 +- 3 files changed, 91 insertions(+), 72 deletions(-) create mode 100644 crates/geth-node/src/runtime.rs diff --git a/crates/geth-node/src/lib.rs b/crates/geth-node/src/lib.rs index 7a04526..9622cfe 100644 --- a/crates/geth-node/src/lib.rs +++ b/crates/geth-node/src/lib.rs @@ -1,3 +1,4 @@ +mod runtime; pub mod service; use base64::Engine; @@ -54,7 +55,11 @@ use geth_types::{ }; use iroh::protocol::ProtocolHandler; use iroh_docs::api::protocol::{AddrInfoOptions, ShareMode}; -use std::collections::{BTreeMap, BTreeSet, VecDeque}; +use runtime::{ + KvDocsState, LiveSyncCursor, LiveSyncHealth, NodeRuntime, OverlayTunCounters, + OverlayTunRuntime, PipeRuntime, PubsubGossipTopicRuntime, PubsubRuntime, +}; +use std::collections::{BTreeMap, BTreeSet}; use std::path::{Component, Path, PathBuf}; use std::sync::{Arc, Mutex}; use std::time::Duration; @@ -178,79 +183,11 @@ pub struct LocalNode { runtime: Arc, } -#[derive(Debug)] -struct NodeRuntime { - pubsub: Mutex, - pipes: Mutex, - overlays: Mutex>, -} - -#[derive(Debug, Default)] -struct PubsubRuntime { - messages: VecDeque, - gossip_topics: BTreeMap, -} - -#[derive(Debug, Clone)] -struct PubsubGossipTopicRuntime { - sender: iroh_gossip::api::GossipSender, -} - -#[derive(Debug, Default)] -struct PipeRuntime { - listeners: BTreeMap, - connections: VecDeque, - messages: VecDeque, -} - -#[derive(Debug)] -struct OverlayTunRuntime { - name: String, - interface_name: String, - virtual_ip: String, - cidr: String, - mtu: u16, - started_at_ms: i64, - inject_tx: mpsc::Sender>, - stop_tx: Option>, - counters: Arc>, -} - -#[derive(Debug, Default)] -struct OverlayTunCounters { - packets_from_tun: u64, - packets_to_tun: u64, - packets_to_peers: u64, - last_error: Option, -} - const PUBSUB_RING_LIMIT: usize = 256; const PIPE_CONNECTION_RING_LIMIT: usize = 256; const PIPE_MESSAGE_RING_LIMIT: usize = 1024; const LIVE_SYNC_STALE_AFTER_MS: i64 = 120_000; -#[derive(Debug, serde::Deserialize, serde::Serialize)] -struct LiveSyncCursor { - cursor_ms: i64, -} - -#[derive(Debug, serde::Deserialize, serde::Serialize)] -struct LiveSyncHealth { - last_attempt_ms: i64, - last_success_ms: Option, - last_error: Option, - last_imported: usize, - last_rejected: usize, -} - -#[derive(Debug, serde::Deserialize, serde::Serialize)] -struct KvDocsState { - name: String, - namespace_id: String, - read_ticket: String, - updated_at_ms: i64, -} - struct PipeTcpConnectWire { peer_card: PeerCard, target_addr: String, diff --git a/crates/geth-node/src/runtime.rs b/crates/geth-node/src/runtime.rs new file mode 100644 index 0000000..e71ff11 --- /dev/null +++ b/crates/geth-node/src/runtime.rs @@ -0,0 +1,82 @@ +//! Daemon-local runtime state. +//! +//! `LocalNode` owns one `Arc` for daemon-lifetime, in-memory +//! registries and task handles. Durable resource state still belongs in +//! `geth-store`; these structs only hold transient pubsub rings, pipe +//! listeners/messages, and active overlay TUN runtimes. Each registry has its +//! own mutex so feature handlers can lock the smallest runtime surface they +//! mutate. + +use geth_pipe::{PipeConnection, PipeListener, PipeMessage}; +use geth_pubsub::PubsubMessage; +use std::collections::{BTreeMap, VecDeque}; +use std::sync::{Arc, Mutex}; +use tokio::sync::{mpsc, oneshot}; + +#[derive(Debug)] +pub(crate) struct NodeRuntime { + pub(crate) pubsub: Mutex, + pub(crate) pipes: Mutex, + pub(crate) overlays: Mutex>, +} + +#[derive(Debug, Default)] +pub(crate) struct PubsubRuntime { + pub(crate) messages: VecDeque, + pub(crate) gossip_topics: BTreeMap, +} + +#[derive(Debug, Clone)] +pub(crate) struct PubsubGossipTopicRuntime { + pub(crate) sender: iroh_gossip::api::GossipSender, +} + +#[derive(Debug, Default)] +pub(crate) struct PipeRuntime { + pub(crate) listeners: BTreeMap, + pub(crate) connections: VecDeque, + pub(crate) messages: VecDeque, +} + +#[derive(Debug)] +pub(crate) struct OverlayTunRuntime { + pub(crate) name: String, + pub(crate) interface_name: String, + pub(crate) virtual_ip: String, + pub(crate) cidr: String, + pub(crate) mtu: u16, + pub(crate) started_at_ms: i64, + pub(crate) inject_tx: mpsc::Sender>, + pub(crate) stop_tx: Option>, + pub(crate) counters: Arc>, +} + +#[derive(Debug, Default)] +pub(crate) struct OverlayTunCounters { + pub(crate) packets_from_tun: u64, + pub(crate) packets_to_tun: u64, + pub(crate) packets_to_peers: u64, + pub(crate) last_error: Option, +} + +#[derive(Debug, serde::Deserialize, serde::Serialize)] +pub(crate) struct LiveSyncCursor { + pub(crate) cursor_ms: i64, +} + +#[derive(Debug, serde::Deserialize, serde::Serialize)] +pub(crate) struct LiveSyncHealth { + pub(crate) last_attempt_ms: i64, + pub(crate) last_success_ms: Option, + pub(crate) last_error: Option, + pub(crate) last_imported: usize, + pub(crate) last_rejected: usize, +} + +#[derive(Debug, serde::Deserialize, serde::Serialize)] +pub(crate) struct KvDocsState { + pub(crate) name: String, + pub(crate) namespace_id: String, + pub(crate) read_ticket: String, + pub(crate) updated_at_ms: i64, +} diff --git a/docs/production-readiness-roadmap.md b/docs/production-readiness-roadmap.md index 78bb58c..e2ec6c3 100644 --- a/docs/production-readiness-roadmap.md +++ b/docs/production-readiness-roadmap.md @@ -35,12 +35,12 @@ Goal: make the documented local quality gate pass before deeper refactors. Goal: split `geth-node` into reviewable daemon subsystems without changing behavior. -- `[ ]` Extract daemon startup and runtime ownership. +- `[~]` Extract daemon startup and runtime ownership. Acceptance criteria: - `[ ]` Daemon startup, shutdown, signal handling, socket setup, Iroh endpoint ownership, and background task spawning live outside the main feature handler module. - - `[ ]` Runtime state is represented by narrow structs with documented + - `[x]` Runtime state is represented by narrow structs with documented ownership and locking rules. - `[ ]` Existing daemon startup and status tests pass unchanged. @@ -330,7 +330,7 @@ Goal: prove the system works as an actual base layer before broader use. ## Working Order 1. `[~]` Finish Phase 0. -2. `[ ]` Refactor `geth-node` into daemon subsystems. +2. `[~]` Refactor `geth-node` into daemon subsystems. 3. `[ ]` Add stable contract and golden JSON tests. 4. `[ ]` Harden store migrations and backup. 5. `[ ]` Complete security-boundary test coverage.