feat(go-services): tracker share_* handlers (complete ingest) + shadow tuning

- share.go: cross-machine vital sharing (share_subscribe/unsubscribe/share_*),
  faithful port of the peer-state snapshot + plugin fan-out + /vital-sharing/peers.
  The last ingest handler — the Go tracker now handles every plugin event type.
- shadow consumer: drop the outbound keepalive ping (the firehose is never idle)
  and tighten the read-deadline watchdog to 12s for faster reconnect after the
  upstream's periodic eviction (full-firehose browser clients get evicted ~every
  90s; the watchdog recovers it, ~90% duty cycle). Production-bound /ws/position
  is unaffected (plugins connect to us; no eviction).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-24 11:27:25 +02:00
parent 27757636e4
commit 5b2db439a3
6 changed files with 171 additions and 27 deletions

View file

@ -48,22 +48,8 @@ func (s *Server) shadowConnect(ctx context.Context, wsURL string) error {
connCtx, cancel := context.WithCancel(ctx)
defer cancel()
// Keepalive pings.
go func() {
t := time.NewTicker(20 * time.Second)
defer t.Stop()
for {
select {
case <-connCtx.Done():
return
case <-t.C:
pc, cc := context.WithTimeout(connCtx, 10*time.Second)
_ = c.Ping(pc)
cc()
}
}
}()
// No outbound keepalive ping: the firehose is constant, so the connection is
// never idle, and the read-deadline watchdog below handles dead connections.
// Decouple socket read from ALL processing, including JSON parsing: the read
// loop only copies raw frames onto a queue, so it drains the socket as fast
@ -96,9 +82,9 @@ func (s *Server) shadowConnect(ctx context.Context, wsURL string) error {
func (s *Server) shadowReadLoop(ctx context.Context, c *websocket.Conn, queue chan []byte, n, dropped *int) error {
for {
// Read deadline acts as a liveness watchdog: the firehose is constant, so
// a long silence means the upstream evicted us without closing — time out
// and let runShadowConsumer reconnect.
rctx, rcancel := context.WithTimeout(ctx, 25*time.Second)
// a multi-second silence means the upstream evicted us without closing —
// time out quickly and let runShadowConsumer reconnect (high duty cycle).
rctx, rcancel := context.WithTimeout(ctx, 12*time.Second)
_, raw, err := c.Read(rctx)
rcancel()
if err != nil {