Module-scoped persistent storage (ctx.storage), first consumer: docker update state #37
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Problem
Modules have no way to persist state across restarts. The SDK offers no storage capability — no KV, no module data directory. Any module holding derived-but-expensive state loses it when the container is recreated.
Concrete case: the docker module's update verdicts (
state.updatesinpackages/modules/docker/backend/mod.ts) live in module memory. The schedule side is already persisted correctly — theinterval-updatesschedule row in DuckDB survives restarts andnextRunMs = max(lastRunMs + everyMs, now)deliberately avoids re-sweeping registries on every boot. But the sweep result dies with the process, so after recreating the OpsDeck container the UI shows no available updates until the next scheduled sweep, up toCHECK_INTERVAL_MS(default 6 h) later.Firing the sweep at startup instead is the wrong fix: it resurrects the boot-anchored behaviour the persisted schedule window exists to prevent (a restart-heavy or crash-looping host would hammer rate-limited registries with a manifest request per image on every boot).
Proposal
Core: module-scoped KV storage, exposed on the module context:
ctx.storage.get(key)/ctx.storage.set(key, value)/ctx.storage.delete(key), JSON values./data), keyed(module, key), going through the single serialized DB queue like every other DuckDB access.server/src/modules/host.ts), same pattern as metrics/scheduler/events — a module can never read another module's keys.Docker module: persist update state.
refreshUpdates), store{ updates, updatesCheckedAt }.register(), rehydratestate.updatesfrom storage. Correctness is already handled by existing machinery:refreshStacksre-derivesupdateAvailablefrom local image digests vs the storedremoteDigeston every poll, andpruneUpdatesdrops images that no longer run. Per-imagecheckedAtsurvives too, which keeps the staleness-ordered rotation incheckUpdatesfair across restarts.Result
Update badges/counters survive a container recreate; the registry sweep cadence stays exactly as scheduled. The storage capability is reusable by any module caching expensive remote facts (e.g. module_teamspeak's badge catalog and icon cache).