diff --git a/client/internal/dns_peer_activator.go b/client/internal/dns_peer_activator.go index 2e222f783..1bd740ef9 100644 --- a/client/internal/dns_peer_activator.go +++ b/client/internal/dns_peer_activator.go @@ -20,11 +20,17 @@ type dnsPeerActivator struct { peerStore *peerstore.Store status *peer.Status mu *sync.Mutex + // ctx is the engine's long-lived context. The connection dial is tied to it + // (not the per-query DNS wait budget) so a handshake that outlasts the wait + // still completes in the background rather than being cancelled at the deadline. + ctx context.Context } // ActivatePeersByIP triggers wake-up for the peer(s) owning ips and waits until -// one is connected or ctx expires. Unknown or already-connected IPs are skipped, -// so the steady-state (warm) path adds no latency. +// one is connected or ctx (the per-query DNS wait budget) expires. Activation +// itself is tied to the engine's long-lived context so the dial survives a wait +// that times out. Unknown or already-connected IPs are skipped, so the +// steady-state (warm) path adds no latency. func (a *dnsPeerActivator) ActivatePeersByIP(ctx context.Context, ips []string) { if a == nil || a.connMgr == nil { return @@ -41,7 +47,7 @@ func (a *dnsPeerActivator) ActivatePeersByIP(ctx context.Context, ips []string) if !ok { continue } - a.connMgr.ActivatePeer(ctx, conn) + a.connMgr.ActivatePeer(a.ctx, conn) pending = append(pending, ip) } a.mu.Unlock() diff --git a/client/internal/engine.go b/client/internal/engine.go index eee4e3e29..7c24d70b2 100644 --- a/client/internal/engine.go +++ b/client/internal/engine.go @@ -663,6 +663,7 @@ func (e *Engine) Start(netbirdConfig *mgmProto.NetbirdConfig, mgmtURL *url.URL) peerStore: e.peerStore, status: e.statusRecorder, mu: e.syncMsgMux, + ctx: e.ctx, }) } diff --git a/e2e/agentnetwork/chat_test.go b/e2e/agentnetwork/chat_test.go index a92eb3487..17ed40d5f 100644 --- a/e2e/agentnetwork/chat_test.go +++ b/e2e/agentnetwork/chat_test.go @@ -92,7 +92,7 @@ func availableProviders() []providerCase { region = "us-east-1" } // A valid Bedrock inference-profile id (region prefix + date + version), - // overridable per account. `global.` profiles are invokable from any + // overridable per account. `global.` profiles can be invoked from any // region; set AWS_BEDROCK_MODEL to match the enabled profile for the token. model := os.Getenv("AWS_BEDROCK_MODEL") if model == "" {