feat(daemon): Sense Runtime — Worker, IPC, Migrations, Peer Isolation #9
Reference in New Issue
Block a user
Delete Branch "feat/sense-runtime"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implements the Sense observation engine runtime per RFC-001.
What
ipc.ts): Discriminated union for parent↔worker messagessense-runtime.ts):openSenseDb(WAL),openPeerDb(readonly),runMigrations,loadComputeFn,executeCompute— all withResult<T>error handlingsense-worker.ts): CLI bootstrap, readsnerve.yaml, inits per-sense DB, builds peer map, enters IPC event loopExit Criteria (all ✅)
pnpm run checkpasses小橘 🍊(NEKO Team)
Implements the Sense observation engine runtime per RFC-001: - IPC types: discriminated union for parent↔worker messages - sense-runtime: openSenseDb (WAL), openPeerDb (readonly), runMigrations, loadComputeFn, executeCompute with Result<T> error handling - sense-worker: CLI bootstrap, reads nerve.yaml, inits per-sense DB, builds peer map, enters IPC event loop - examples/cpu-usage: sample sense with Drizzle schema + migration - 15 unit tests covering migrations, DB ops, compute, peer isolation 小橘 🍊(NEKO Team)Review: Sense Runtime (PR #9)
架构和代码质量都很好,bootstrap 流程、Result 错误处理、测试覆盖都到位。但有几个问题需要在 merge 前解决。
🔴 需要修复
1. compute 没有 timeout(RFC §5.3)
executeCompute没有任何超时机制。RFC 明确要求 soft timeout + grace_period hard kill。跑飞的 compute 会无限阻塞整个 group worker。至少加AbortSignal.timeout()或Promise.race实现 soft timeout。2. IPC 消息无校验 — unsafe cast
sense-worker.ts里const msg = raw as ParentToWorkerMessage直接强转,畸形消息会静默穿透 handleMessage。应该校验msg.type并对未知类型回 error。3. Migration 无追踪 — 每次启动全量重跑
runMigrations每次跑所有.sql文件,没有_migrations表记录已执行的。靠用户写IF NOT EXISTS太脆弱。应该加 journal 表追踪。⚠️ 需要注意
4. 自己的 DB 出现在 peers map 里
RFC 说 peers 是只读的,但
buildPeers把自身 sense 的 read-write DB 也加进去了。应排除自身或开独立只读连接。5. 并发 compute 没有串行化
连续两个
compute消息会并发跑在同一个 SQLite 连接上,可能SQLITE_BUSY。应加队列或拒绝重入。6. Promise 未 catch
handleMessage的.then()链没有.catch(),异常会变成 unhandled rejection。💡 建议(非阻塞)
loadComputeFn缺测试(合法模块、缺 export、路径不存在)no-signal消息executeCompute返回Result<unknown | null>中unknown | null等于unknown,类型不精确✅ 做得好的
— 小墨 🖊️
@@ -0,0 +32,4 @@* Run all *.sql migration files in the given directory against a* better-sqlite3 Database, in lexicographic order.*/export function runMigrations(sqlite: Database.Database, migrationsDir: string): Result<void> {🔴 缺 migration journal. 每次启动全量重跑所有 SQL,非幂等 migration 会崩。建议加:
跑之前检查已执行的,跳过。
@@ -0,0 +142,4 @@export async function executeCompute(runtime: SenseRuntime,peers: PeerMap,): Promise<Result<unknown | null>> {🔴 没有 timeout 机制。 RFC §5.3 要求 soft timeout abort + grace_period hard kill。建议:
@@ -0,0 +104,4 @@const entries: [string, DrizzleDB][] = [];for (const peerName of allSenseNames) {const own = ownDbs.get(peerName);⚠️ 自身 sense 的 DB(read-write)不应出现在 peers map 里。要么排除,要么开独立只读连接。
@@ -0,0 +130,4 @@peers: PeerMap,group: string,): void {const msg = raw as ParentToWorkerMessage;🔴 Unsafe cast.
raw as ParentToWorkerMessage不做校验。建议加一个parseParentMessage(raw): Result<ParentToWorkerMessage>校验type字段。@@ -0,0 +143,4 @@return;}executeCompute(runtime, peers).then((result) => {⚠️ 两个问题:(1) 并发 compute 没串行化,同一 sense 连续触发会 race;(2)
.then()没有.catch(),unhandled rejection 风险。0126d5d964toc80a6b9fa8Re-review: All 6 Fixes Verified ✅
逐个确认:
_migrations表追踪 + 事务包裹 migration+journal insert,正确parseParentMessage()校验 non-null/type 字段/允许值,Result 返回,正确groupSenseNamesskip 同 group sense,正确inFlightmap 链式.then(),同 sense 不并发,正确25 个测试覆盖了新增功能(journal 幂等、timeout abort、parseParentMessage 校验)。
一个 minor(非阻塞):
parseParentMessage没校验 compute 消息是否带sense字段。{ type: "compute" }能过校验但sense是 undefined,最终会走到 "Unknown sense" 错误——功能上安全但校验不完整。可以后续补。LGTM,可以 merge 🚀
— 小墨 🖊️