SPL Meter 0.4.2: the device picker can build the tool it needs #18

Merged
michael merged 1 commits from claude/spl-devices-without-binary into main 2026-09-28 11:30:42 -04:00
Owner

NA-Ingest could not list a single audio interface.

The module had been installed from the catalog, which ships source only because the capture binary is gitignored. The admin page's device picker shells out to that binary with --list, so it returned nothing:

[spl-meter] device list failed: spawn .../spl-capture ENOENT

The missing-binary build already existed, but only inside the listener — and the listener only starts once a device has been picked. No tool meant no device list, and no device meant no listener to build the tool. Nothing was going to break that cycle on its own, which makes this a trap for every future catalog install rather than a one-off on one machine.

The fix

The build moved to module scope and both callers use it:

  • init() asks for it on mount, whether or not a device is configured
  • /devices asks again on every call, so simply opening the admin page starts it

It is still a plain non-blocking spawn — that part was fixed in 0.4.0 after a spawnSync copied from the LTC listener froze the whole server for two minutes on AB. health() now names the situation too, rather than leaving an empty dropdown unexplained.

While moving it I found two per-listener build flags left shadowing the new module-scope ones. They would have made the "is a build already running" test always false and allowed a second build to start under the first.

Tested the way it failed

A data directory holding only the six source files and no binary, exactly as a catalog install arrives. The build starts on mount and /devices answers with the real device list moments later.

Deployed to both machines: NA now lists 4 interfaces, AB lists 12.

🤖 Generated with Claude Code

NA-Ingest could not list a single audio interface. The module had been installed from the catalog, which ships source only because the capture binary is gitignored. The admin page's device picker shells out to that binary with `--list`, so it returned nothing: ``` [spl-meter] device list failed: spawn .../spl-capture ENOENT ``` The missing-binary build already existed, but only inside the listener — and the listener only starts once a device has been picked. **No tool meant no device list, and no device meant no listener to build the tool.** Nothing was going to break that cycle on its own, which makes this a trap for every future catalog install rather than a one-off on one machine. ## The fix The build moved to module scope and both callers use it: - `init()` asks for it on mount, whether or not a device is configured - `/devices` asks again on every call, so simply opening the admin page starts it It is still a plain non-blocking `spawn` — that part was fixed in 0.4.0 after a `spawnSync` copied from the LTC listener froze the whole server for two minutes on AB. `health()` now names the situation too, rather than leaving an empty dropdown unexplained. While moving it I found two per-listener build flags left shadowing the new module-scope ones. They would have made the "is a build already running" test always false and allowed a second build to start under the first. ## Tested the way it failed A data directory holding only the six source files and no binary, exactly as a catalog install arrives. The build starts on mount and `/devices` answers with the real device list moments later. Deployed to both machines: NA now lists 4 interfaces, AB lists 12. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
michael added 1 commit 2026-09-23 15:26:52 -04:00
NA could not list a single audio interface. The module was installed from
the catalog, which ships source only because the capture binary is
gitignored, and the picker shells out to that binary with --list. So it
returned nothing, forever:

  [spl-meter] device list failed: spawn .../spl-capture ENOENT

The missing-binary build existed, but only inside the listener, and the
listener only starts once a device has been picked. No tool meant no device
list, and no device meant no listener to build the tool. Nothing was going
to break that on its own.

The build now lives at module scope and both callers use it: init() asks for
it on mount whether or not a device is configured, and /devices asks again
each time it is called, so opening the admin page is enough to start it. It
is still a plain spawn that never touches the event loop, and health() now
names the situation instead of leaving an empty dropdown unexplained.

Also removed two per-listener build flags left shadowing the module-scope
ones, which would have made the "is a build already running" test always
false and let a second build start under the first.

Tested the way it actually failed: a data directory holding only the six
source files, no binary. The build starts on mount and /devices answers with
the real device list moments later.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
michael merged commit 58f3e5010a into main 2026-09-28 11:30:42 -04:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: michael/ProdDash#18