feat(bambubuddy): live fleet status, cached - #10
Conversation
… load
Machine status only moved when somebody pressed Sync. That is not just a
stale UI: the batch planner and machine scheduler read machines.status
and current_layer, so a printer that finished an hour ago still looked
busy to the thing deciding what to print next. Right now BambuBuddy
reports FINISH at 406/406 while Tensor shows RUNNING.
Making the UI poll would have made that worse. GET /machine-fleet/:id/live
costs TWO upstream calls - ListPrinters purely to translate a serial into
a printer id, then GetStatus - with no cache anywhere on the path. Three
tabs watching three machines at a 10s poll is 108 requests a minute to a
service running on a laptop at the end of a home connection.
bambu_cache.go caches both reads, following the mutex+TTL+injectable-clock
shape of internal/auth/freshness.go so the client stays pure transport and
the policy sits by its consumers. Two things that cache does NOT have,
because polling makes them matter:
- Single-flight. Twenty tabs arriving on a cold cache produce one
upstream call, not twenty. Hand-rolled in ~25 lines rather than
adding golang.org/x/sync, which is only an indirect require today.
- A detached fetch context. With many viewers sharing one call, the
first arrival navigating away would otherwise cancel the request
every other waiter is blocked on. There is a test for exactly this,
because it regresses silently to "all waiters fail".
Negative caching too: an unreachable printer costs a full 10s client
timeout, and without it every poll pays that again - single-flight only
collapses arrivals that overlap, and staggered tabs do not.
The periodic refresh is what keeps the table honest with nobody watching,
and it deliberately does NOT prune. Reconciliation ends in
DeleteFleetMachinesNotIn, so putting the full sync on a timer would make a
destructive operation automatic: one transiently partial ListPrinters - a
restarting BambuBuddy, a Tailscale blip - and machines are deleted, with
only those mid-print protected. Removing a decommissioned printer stays
something a human asks for; refreshing status is the thing that must
happen every minute. RunOnStart is true here, unlike batch planning: a
fresh deployment's empty machines table is exactly when it should populate.
Either TTL set to 0 disables that cache, which makes a before/after
measurement a config flip rather than a code change.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing |
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|



Machine status only moved when somebody pressed Sync. That is not just a stale UI: the batch planner and machine scheduler read
machines.statusandcurrent_layer, so a printer that finished an hour ago still looked busy to the thing deciding what to print next. Right now BambuBuddy reportsFINISH 406/406while Tensor showsRUNNING.Making the UI poll would have made it worse.
GET /machine-fleet/:id/livecosts two upstream calls —ListPrinterspurely to translate a serial into a printer id, thenGetStatus— with no cache anywhere on the path. Three tabs × three machines at 10s = 108 requests/min to a service on a laptop at the end of a home connection.bambu_cache.goFollows the mutex + TTL + injectable-clock shape of
internal/auth/freshness.go. Two things that cache does not have, because polling makes them matter:golang.org/x/sync(only an indirect require today).Plus negative caching: an unreachable printer costs a full 10s client timeout, and single-flight only collapses arrivals that overlap — staggered tabs don't.
The periodic refresh does not prune
SyncFleetFromBambuBuddyends inDeleteFleetMachinesNotIn. Putting it on a timer makes a destructive operation automatic: one transiently partialListPrinters— a restarting BambuBuddy, a Tailscale blip — and machines are deleted, with only those mid-print protected.Split into
SyncFleetFromBambuBuddy(prune, human-initiated) andRefreshFleetFromBambuBuddy(no prune, the timer).RunOnStart: truehere unlike batch planning: a fresh deployment's empty machines table is exactly when it should populate itself.Verification
-race: TTL, single-flight (20 goroutines → 1 call), leader-cancellation survival, negative caching, TTL-0 passthroughhttpapiintegration testscmd/fleetsyncagainst the real fleet:synced 2 printer(s): [opti1 opti2]Either TTL set to
0disables caching, so a before/after measurement is a config flip rather than a code change.🤖 Generated with Claude Code