perf(tmux): batch session queries in gt down (#477)

* perf(tmux): batch session queries in gt down to reduce N+1 subprocess calls

Add SessionSet type to tmux package for O(1) session existence checks.
Instead of calling HasSession() (which spawns a subprocess) for each
rig/session during shutdown, now calls ListSessions() once and uses
in-memory map lookups.

Changes:
- internal/tmux/tmux.go: Add SessionSet type with GetSessionSet() and Has()
- internal/cmd/down.go: Use SessionSet for dry-run checks and session stops
- internal/session/town.go: Add StopTownSessionWithCache() variant
- internal/tmux/tmux_test.go: Add test for SessionSet

With 5 rigs, this reduces subprocess calls from ~15 to 1 during shutdown
preview, saving 60-150ms of execution time.

Closes: gt-xh2bh

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* perf(tmux): optimize SessionSet to avoid intermediate slice allocation

- Build map directly from tmux output instead of calling ListSessions()
- Use strings.IndexByte for efficient newline parsing
- Pre-size map using newline count to avoid rehashing
- Simplify nil checks in Has() and Names()

* fix(sling): restore bd cook directory context for formula-on-bead mode

The bd cook command needs to run from the target rig's directory to
access the correct formula database. This was accidentally removed
in a previous commit, causing TestSlingFormulaOnBeadRoutesBDCommandsToTargetRig
to fail.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Keith Wyatt
2026-01-13 22:07:05 -08:00
committed by GitHub
parent 5d96243414
commit 08755f62cd
5 changed files with 162 additions and 7 deletions

View File

@@ -39,6 +39,21 @@ func StopTownSession(t *tmux.Tmux, ts TownSession, force bool) (bool, error) {
return false, nil
}
return stopTownSessionInternal(t, ts, force)
}
// StopTownSessionWithCache is like StopTownSession but uses a pre-fetched
// SessionSet for O(1) existence check instead of spawning a subprocess.
func StopTownSessionWithCache(t *tmux.Tmux, ts TownSession, force bool, cache *tmux.SessionSet) (bool, error) {
if !cache.Has(ts.SessionID) {
return false, nil
}
return stopTownSessionInternal(t, ts, force)
}
// stopTownSessionInternal performs the actual session stop.
func stopTownSessionInternal(t *tmux.Tmux, ts TownSession, force bool) (bool, error) {
// Try graceful shutdown first (unless forced)
if !force {
_ = t.SendKeysRaw(ts.SessionID, "C-c")