diff --git a/internal/tasksws/client.go b/internal/tasksws/client.go index 92c68cc..b46e7d6 100644 --- a/internal/tasksws/client.go +++ b/internal/tasksws/client.go @@ -111,6 +111,12 @@ func (c *Client) session(ctx context.Context, since *int64) error { defer conn.Close() _ = conn.SetReadDeadline(time.Now().Add(90 * time.Second)) + // Server sends Ping; gorilla delivers it as Ping (not Pong). Reset deadline or + // idle boards die every ~90s with "i/o timeout" despite healthy pings. + conn.SetPingHandler(func(appData string) error { + _ = conn.SetReadDeadline(time.Now().Add(90 * time.Second)) + return conn.WriteControl(websocket.PongMessage, []byte(appData), time.Now().Add(10*time.Second)) + }) conn.SetPongHandler(func(string) error { _ = conn.SetReadDeadline(time.Now().Add(90 * time.Second)) return nil @@ -146,9 +152,13 @@ func (c *Client) session(ctx context.Context, since *int64) error { *since = ev.Seq } if c.OnEvent != nil { - if err := c.OnEvent(ctx, ev); err != nil && c.Log != nil { - c.Log.Warn("tasks ws handler", "error", err, "type", ev.Type) - } + ev := ev + hctx := context.WithoutCancel(ctx) + go func() { + if err := c.OnEvent(hctx, ev); err != nil && c.Log != nil { + c.Log.Warn("tasks ws handler", "error", err, "type", ev.Type) + } + }() } } }