Skip to content

hub_runtime: total runtime resets on every upgrade (mutable state lives in core/hci.lua) #445

Description

@Aybook

Problem

core/hci.lua holds mutable runtime state — the persisted lifetime accumulator behind +runtime show / +uptime / +hubinfo and GET /v1/runtime:

hci_tbl = {
    [ "hubruntime" ] = 0,
    [ "hubruntime_last_check" ] = 0,
}

It is read and rewritten via util.loadtable / util.savetable by hub_runtime (60s onTimer), cmd_uptime and cmd_hubinfo.

But it lives under core/, which is a shipped directory:

  • CMakeLists.txt:117install(DIRECTORY core/ DESTINATION core), wholesale, no exclusion.
  • Docker (docs/DOCKER.md) mounts ./cfg/ and ./scripts/; core/ is baked into the image.

So the pristine hubruntime = 0 ships over the operator''s accumulated value:

  • Source install: cmake --install into an existing tree → counter reset to 0.
  • Docker: every image update → fresh core/hci.lua → counter reset to 0.

hub_runtime''s check_hci() only guards a missing or corrupt file (it recreates zeros); a zeroed file is indistinguishable from a fresh hub, so nothing detects the loss.

Net effect: the "total runtime" figure an operator has been accumulating for months silently returns to zero on upgrade — which defeats the entire purpose of the accumulator (session uptime is already available separately via signal.get("start")).

Why it happened

This is the one piece of plugin state living under core/ instead of scripts/data/<plugin>.tbl, contrary to the rule in CLAUDE.md §7 / docs/DEVELOPMENT.md §3. The rule exists precisely for this: scripts/ is a mounted volume in Docker and is not clobbered by an upgrade, core/ is neither.

Note core/hci.lua is not a module (it is deliberately absent from init.lua''s _core array — that part is correct and should stay); it is a data file that happens to sit in the wrong directory.

Proposed fix

  • Move the store to scripts/data/hub_runtime.tbl (owner: hub_runtime, which is the only writer on the timer path).
  • Migrate once: on onStart, if scripts/data/hub_runtime.tbl is absent but core/hci.lua exists with a non-zero hubruntime, adopt its value and write the new file. Without this, the fix itself would zero everyone''s counter — the exact bug it repairs.
  • Update the three readers (hub_runtime, cmd_uptime, cmd_hubinfo) and the /v1/runtime GET/PUT handlers.
  • Delete core/hci.lua once the migration path has shipped for a release (or leave it read-only as the migration source and stop writing it).
  • docs/HTTP_API.md footnote for /v1/runtime names core/hci.lua as the backing store — update.

Verification

  • Regression that fails pre-fix: seed a non-zero accumulator, re-run cmake --install over the tree, assert the value survives (pre-fix it is 0).
  • Migration test: old core/hci.lua with a value + no new file → value adopted; new file present → old file ignored.

Found by the dead-code audit (core/hci.lua was flagged as a possible dead/stub module — it is neither, but the check surfaced this). CLAUDE.md §3 previously mislabelled it as a "(stub)"; corrected separately in the doc-currency pass.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Fields

No fields configured for Bug.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions