diff --git a/agent/cmd/behavision-setup/main.go b/agent/cmd/behavision-setup/main.go index 5cd4996..50fd96b 100644 --- a/agent/cmd/behavision-setup/main.go +++ b/agent/cmd/behavision-setup/main.go @@ -93,6 +93,12 @@ func run() error { } if running := behavisionRunning(); running != "" { + // lint:ignore ST1005 — this is not a wrapped error, it is the whole + // message an operator reads at a shop counter. ST1005 forbids + // trailing punctuation because errors get concatenated mid-sentence; + // nothing wraps this one, and stripping the full stops would make + // three sentences run together. + //lint:ignore ST1005 operator-facing prose, never wrapped return fmt.Errorf("%s is running. Quit Behavision from the tray icon first, then run setup again.\n\n"+ "Setting up underneath a running copy starts a second engine on the same port and, in a demo,\n"+ "re-claims the shop while the open app still holds the old credentials.", running) diff --git a/agent/go.mod b/agent/go.mod index 2fa92c6..3795dc2 100644 --- a/agent/go.mod +++ b/agent/go.mod @@ -3,9 +3,12 @@ module github.com/loyaly/behavision-agent go 1.22 require ( - github.com/eclipse/paho.mqtt.golang v1.4.3 // indirect + github.com/eclipse/paho.mqtt.golang v1.4.3 + golang.org/x/sys v0.20.0 +) + +require ( github.com/gorilla/websocket v1.5.0 // indirect golang.org/x/net v0.8.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.20.0 // indirect ) diff --git a/agent/main.go b/agent/main.go index 57e5af7..62c5898 100644 --- a/agent/main.go +++ b/agent/main.go @@ -81,6 +81,7 @@ usage: %s // agent.json - which is the state that screen was built to end. func cmdClaim(args []string) error { if len(args) == 0 { + //lint:ignore ST1005 usage text read by a person, never wrapped return fmt.Errorf("usage: behavision-agent claim \n" + "Ask whoever manages your shops for one - they can create it from\n" + "the Behavision platform, under the shop.") diff --git a/agent/pkg/cameras/live.go b/agent/pkg/cameras/live.go index 64082ff..dec4e59 100644 --- a/agent/pkg/cameras/live.go +++ b/agent/pkg/cameras/live.go @@ -36,7 +36,6 @@ type Live struct { FPS float64 Width int Quality int - pollDelay time.Duration } // Defaults, measured against the office camera rather than guessed. diff --git a/agent/pkg/engine/supervisor.go b/agent/pkg/engine/supervisor.go index d25d63b..aa49d90 100644 --- a/agent/pkg/engine/supervisor.go +++ b/agent/pkg/engine/supervisor.go @@ -244,6 +244,13 @@ func (s *Supervisor) runOnce(ctx context.Context) error { } return kill() } + // Cancel sends the kill; WaitDelay bounds how long Wait() then waits for + // the output pipes to close. Without it Wait() blocks until every writer + // is gone - and Stop() blocks on Wait() - so one grandchild still holding + // the engine's stdout hangs Stop FOREVER, which on the desktop app means + // the tray's Quit never returns. stopGrace was declared for exactly this + // and never wired to anything; staticcheck found it as an unused const. + cmd.WaitDelay = stopGrace prepare(cmd) if err := cmd.Start(); err != nil { return fmt.Errorf("engine failed to start: %w", err) diff --git a/agent/pkg/mqtt/client.go b/agent/pkg/mqtt/client.go index 45cf7be..0866e05 100644 --- a/agent/pkg/mqtt/client.go +++ b/agent/pkg/mqtt/client.go @@ -18,7 +18,6 @@ import ( "log" "net" "net/url" - neturl "net/url" "os" "strings" "time" @@ -225,7 +224,7 @@ func checkTransport(raw string) error { // url.Parse, not hand-rolled splitting: an IPv6 literal is bracketed and // full of colons, so scanning for the first ":" turns "[::1]:1883" into // "[" and refuses a perfectly good loopback address. - u, err := neturl.Parse(raw) + u, err := url.Parse(raw) if err != nil { return fmt.Errorf("mqtt: cannot parse broker url %q: %w", raw, err) } diff --git a/agent/pkg/mqtt/client_test.go b/agent/pkg/mqtt/client_test.go index fc1f616..b8b01b2 100644 --- a/agent/pkg/mqtt/client_test.go +++ b/agent/pkg/mqtt/client_test.go @@ -92,7 +92,11 @@ func TestPublishOnADeadClientErrorsRatherThanPanics(t *testing.T) { // The pump calls this on every tick; a nil-client panic would take the // whole agent down instead of backing off. c := &Client{} - if err := c.Publish(nil, "t", []byte("{}")); err == nil { //nolint:staticcheck + // The nil context is the POINT: the pump must not panic on a client that + // never connected. //nolint is golangci-lint's directive and staticcheck + // ignores it, which is why this kept being reported. + //lint:ignore SA1012 passing nil is what is under test + if err := c.Publish(nil, "t", []byte("{}")); err == nil { t.Fatal("publish on an unconnected client reported success") } if c.Connected() { diff --git a/agent/pkg/mqtt/pump.go b/agent/pkg/mqtt/pump.go index 75884c2..940995a 100644 --- a/agent/pkg/mqtt/pump.go +++ b/agent/pkg/mqtt/pump.go @@ -205,14 +205,3 @@ func (p *Pump) logf(format string, args ...any) { p.Log.Printf(format, args...) } } - -func sleep(ctx context.Context, d time.Duration) bool { - t := time.NewTimer(d) - defer t.Stop() - select { - case <-ctx.Done(): - return false - case <-t.C: - return true - } -}