9c832b0e21
7 cards updated, 4 new cards added. Topics: signal-routing, worker-isolation, storage-layer, adapter-isolation, sense contracts, workflow runtime enforcement, coding conventions details. 小橘 <xiaoju@shazhou.work>
2.8 KiB
2.8 KiB
Sense
A compute() function that samples or derives external data. The only first-class citizen in nerve.
Contract
Each sense module (src/index.ts) must export:
export { snapshots as table } from "./schema.ts"; // drizzle table for runtime to insert into
export async function compute(): Promise<ComputeResult<T>> { ... } // pure, no args
Function Signature & Input Schema:
compute()is parameterless — no direct inputs, environment variables available- No database access within compute — runtime provides isolated execution context
- Must be pure function (no side effects, no external API calls)
Return Value Contract:
ComputeResult<T>=null | { signal: T; workflow: WorkflowTrigger | null }null→ silent, no storage, no signal{ signal: data, workflow: null }→ persist + emit signal{ signal, workflow: WorkflowTrigger }→ persist + emit signal + trigger workflow- Any other value → treated as
{ signal: value, workflow: null }
Error Handling & Serialization:
- Exceptions caught by worker, logged as errors (no signal emitted)
- Signal payload must be JSON-serializable (passed via IPC)
- Invalid workflow triggers silently dropped (signal still emitted)
Timeout & Scheduling Semantics:
- Timeout priority: explicit config → AbortSignal → DEFAULT_TIMEOUT_MS (30s)
- Enforced via
Promise.race()with timeout promise - Grace period can trigger
process.exit(1)after timeout (kills worker group) - Interval translation: YAML config values used directly as milliseconds in
setInterval() - Jitter control: throttle mechanism prevents rapid-fire, single deferred trigger per throttle window
Config (nerve.yaml)
senses:
cpu-usage:
group: system # senses in same group share a worker
throttle: 10s # min interval between computes
timeout: 30s # max compute duration
grace_period: 5s # wait before first compute
interval: 30s # periodic trigger (optional)
on: [disk-pressure] # trigger on signals from other senses (optional)
Manual Trigger Context
nerve sense trigger <name> sends IPC message to running daemon. The compute context is initialized as follows:
- SQLite Database: Opened in read-write mode at
data/senses/<name>.db - Migrations: All
*.sqlfiles insenses/<name>/migrations/applied in lexicographic order - Environment: Inherits daemon process environment (no special secrets injection)
- Arguments: No runtime arguments or mock inputs supported —
compute()is always pure function with no parameters - Isolation: Runs in forked child process (worker) with full filesystem access within user permissions
- Persistence: Runtime automatically calls
db.insert(table).values(result.signal)if compute returns non-null signal