From 09113afd8758badf55611ed1f5c46edac47a50e6 Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Sun, 7 Jun 2026 10:56:17 +0200 Subject: [PATCH] perf(web): probe datastore hosts concurrently in SeedExtraDevices (refs #451) SeedExtraDevices probed each datastore host serially via AddDeviceByHost, whose /info call blocks up to its 10 s timeout for an unknown host. With offline speakers in the datastore, a re-sync (e.g. the admin page's discovery sweep on load, or the periodic discovery) stalled for 10 s per offline device, one after another. Fan the per-host probes out across goroutines and wait for all of them, so the seed costs roughly a single timeout regardless of how many devices are offline. AddDeviceByHost is already registry-safe under concurrency (covered by TestRegistryConcurrent). Co-Authored-By: Claude Opus 4.8 (1M context) --- pkg/service/soundtouchweb/discovery.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/pkg/service/soundtouchweb/discovery.go b/pkg/service/soundtouchweb/discovery.go index 4d27c3d..dccbde9 100644 --- a/pkg/service/soundtouchweb/discovery.go +++ b/pkg/service/soundtouchweb/discovery.go @@ -3,6 +3,7 @@ package soundtouchweb import ( "context" "log" + "sync" "time" "github.com/gesellix/bose-soundtouch/pkg/client" @@ -95,18 +96,34 @@ func (app *WebApp) AddDeviceByHost(host string, port int, source string) { // (if set) via AddDeviceByHost. Idempotent: already-known hosts are skipped. // Used by the embedded build to surface the service datastore's devices even // when network discovery is disabled; a no-op for standalone soundtouch-web. +// +// Hosts are probed concurrently: AddDeviceByHost makes a blocking /info call +// (up to its 10 s timeout) for each unknown host, so an offline speaker in the +// datastore would otherwise stall the whole seed for 10 s, serially. Fanning +// out bounds the cost to roughly a single timeout regardless of how many +// devices are offline. AddDeviceByHost is registry-safe under concurrency. func (app *WebApp) SeedExtraDevices() { if app.ExtraDeviceHosts == nil { return } + var wg sync.WaitGroup + for _, host := range app.ExtraDeviceHosts() { if host == "" { continue } - app.AddDeviceByHost(host, 8090, "service-store") + wg.Add(1) + + go func(h string) { + defer wg.Done() + + app.AddDeviceByHost(h, 8090, "service-store") + }(host) } + + wg.Wait() } // DiscoverDevices refreshes the device registry. When TriggerDiscovery is set