fix(bx): invalidate monitor snapshot on box config changes - #146
Merged
Conversation
The Bx status monitor polls every 30 seconds and caches each box's full
status (level, latency, last_checked, ConsoleEnabled, etc.) in an
in-memory snapshot. /bx renders from that snapshot.
Side effect: toggling a per-box setting (Remote console, Enabled, …)
in /settings/boxes did not show on /bx until the next 30s tick. User
report described this as "I had it enabled but it was disabled when we
relaunched" (no shell icon visible) plus "I went back to the box and
confirmed the console feature was checked, it was, but I hit save
again anyway and then back to the Bx dashboard and after a couple
more refreshes, it showed up."
Wiring:
- Add EventTypeBoxConfigChanged ("box.config_changed") + Hub.PublishBoxConfigChanged helper.
- HAProxyBoxUpdatePost and HAProxyBoxTogglePost publish the event
immediately after UpdateBox / SetBoxEnabled returns.
- Bx Gear.Start subscribes to "box.config_changed" via deps.EventHub
and calls monitor.PokeBox(serverID) for the affected box.
- New statusMonitor.PokeBox(ctx, boxID) fetches the row, runs a single
probe, and writes the result via m.set — which also broadcasts to
SSE subscribers, so any open /bx tab updates in place without a refresh.
- PokeBox handles the "box was deleted" case by dropping the stale
snapshot entry instead of leaving last-known-good values for a
now-missing box.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR addresses stale data on the Bx fleet view (/bx) after box settings changes by introducing an event-driven cache invalidation path, so the Bx status monitor can refresh a single box’s snapshot immediately rather than waiting for the next 30s poll.
Changes:
- Added a new event type (
box.config_changed) and a helper publisher on the framework event hub. - Published the event after box update and enabled/disabled toggle actions in the HAProxy settings handlers.
- Subscribed the Bx gear to the event and added
statusMonitor.PokeBoxto re-probe and update cached status for a single box.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
gearbox/internal/gears/bx/status.go |
Adds PokeBox to refresh a single box’s cached status out-of-band. |
gearbox/internal/gears/bx/gear.go |
Subscribes Bx gear to box.config_changed to trigger PokeBox. |
gearbox/internal/framework/handler/haproxy_config.go |
Publishes box.config_changed after UpdateBox / SetBoxEnabled operations. |
gearbox/internal/framework/events/hub.go |
Adds EventTypeBoxConfigChanged and PublishBoxConfigChanged. |
- Add statusMonitor.setAndBroadcast that always broadcasts to SSE subscribers; PokeBox now uses it so a config edit that flips only a non-level field (ConsoleEnabled, Enabled, Name, …) still pushes to open /bx tabs. The chatter-suppression in set() is desirable for the steady-state poll loop but defeats the purpose of an out-of-band config-change refresh. - PokeBox now distinguishes transient DB errors from "not found": on err != nil we log and keep the last-known-good snapshot; only box == nil drops the cached entry. Avoids poisoning the UI when SQLite hiccups. - Gear.Start stores the unsubscribe func returned by Subscribe and Gear.Stop now calls it before shutting the monitor down. Closes the events-adapter forwarder goroutine cleanly and stops new PokeBox calls from reaching a winding-down monitor. - Subscribe call now references events.EventTypeBoxConfigChanged (cast to string for the gear.EventPublisher API) instead of a raw "box.config_changed" literal — keeps publisher and subscriber on the same constant. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the "stale UI on /bx after box settings change" issue reported after the nsenter rollout:
DB inspection confirmed
console_enabled = 1was always intact — the symptom was thestatusMonitor's 30-second cache. /bx renders from the monitor's snapshot, so any DB-side toggle (Remote console, Enabled, …) didn't propagate until the next periodic poll.Fix
Event-driven invalidation:
EventTypeBoxConfigChanged(box.config_changed) added toevents/hub.go, with aPublishBoxConfigChanged(serverID)helper.HAProxyBoxUpdatePostandHAProxyBoxTogglePostpublish the event right afterUpdateBox/SetBoxEnabledreturns.Startsubscribes tobox.config_changed; the handler callsmonitor.PokeBox(serverID).statusMonitor.PokeBox(ctx, boxID)reads the row, runs one probe, and writes viam.set, which also broadcasts to SSE subscribers — so any open /bx tab updates in place without a refresh.PokeBoxdrops the stale snapshot entry instead of leaving last-known-good values for a now-missing box.Test plan
go build ./...greengo test ./internal/framework/handler/... ./internal/gears/bx/... ./internal/framework/events/...green🤖 Generated with Claude Code