[PR #6530] [MERGED] [client] Keep signal stream alive while receive loop is blocked on worker handoff #28387

Closed
opened 2026-08-05 08:06:16 -04:00 by saavagebueno · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/netbirdio/netbird/pull/6530
Author: @lixmal
Created: 6/24/2026
Status: Merged
Merged: 6/28/2026
Merged by: @lixmal

Base: mainHead: signal-watchdog-backpressure


📝 Commits (1)

  • 4cb2c62 Keep signal stream alive while receive loop is blocked on worker handoff

📊 Changes

2 files changed (+47 additions, -1 deletions)

View changed files

📝 shared/signal/client/grpc.go (+23 -1)
📝 shared/signal/client/watchdog_test.go (+24 -0)

📄 Description

Describe your changes

The signal receive watchdog tears the stream down and reconnects when no message is read for the inactivity window. But the receive loop also stops reading while it is parked handing a message off to a busy decryption worker: in that window the stream looks silent though it is healthy. The watchdog read that self-inflicted backpressure as a dead stream and reconnected, and each reconnect re-triggered offers to peers, feeding a churn loop that left peers stuck connecting/relayed instead of going direct.

  • Track when the receive loop is blocked on the worker handoff
  • Treat the stream as alive in that state so the watchdog does not reconnect, since a reconnect feeds the same worker and cannot help; a genuinely silent stream (loop reading, worker idle) is still detected and reconnected

N/A

Stack

Checklist

  • Is it a bug fix
  • Is a typo/documentation fix
  • Is a feature enhancement
  • It is a refactor
  • Created tests that fail without the change (if possible)
  • This change does not modify the public API, gRPC protocols, functionality behavior, CLI / service flags, or introduce a new feature — OR I have discussed it with the NetBird team beforehand (link the issue / Slack thread in the description). See CONTRIBUTING.md.

By submitting this pull request, you confirm that you have read and agree to the terms of the Contributor License Agreement.

Documentation

Select exactly one:

  • I added/updated documentation for this change
  • Documentation is not needed for this change (explain why)

Internal change to the client's signal connection-recovery logic; no user-facing surface.

Docs PR URL (required if "docs added" is checked)

Paste the PR link from https://github.com/netbirdio/docs here:

https://github.com/netbirdio/docs/pull/__

Summary by CodeRabbit

  • Bug Fixes
    • Refined the receive-stream watchdog liveness logic to prevent false “dead stream” detection during intentional receive-to-decryption handoff backpressure.
    • Watchdog now holds off reconnect behavior when inactivity is due to worker handoff rather than true network silence.
  • Diagnostics
    • Added a worker queue-length metric for decrypted backlog visibility.
    • Improved watchdog “holding stream” and engine restart logging details; adjusted ICE candidate-pair logging verbosity.
  • Tests
    • Added a test covering watchdog liveness behavior for both handoff-blocked and true receive-inactivity scenarios.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/netbirdio/netbird/pull/6530 **Author:** [@lixmal](https://github.com/lixmal) **Created:** 6/24/2026 **Status:** ✅ Merged **Merged:** 6/28/2026 **Merged by:** [@lixmal](https://github.com/lixmal) **Base:** `main` ← **Head:** `signal-watchdog-backpressure` --- ### 📝 Commits (1) - [`4cb2c62`](https://github.com/netbirdio/netbird/commit/4cb2c62f2af4b892cd45dbb9a664c99da0ea405e) Keep signal stream alive while receive loop is blocked on worker handoff ### 📊 Changes **2 files changed** (+47 additions, -1 deletions) <details> <summary>View changed files</summary> 📝 `shared/signal/client/grpc.go` (+23 -1) 📝 `shared/signal/client/watchdog_test.go` (+24 -0) </details> ### 📄 Description ## Describe your changes The signal receive watchdog tears the stream down and reconnects when no message is read for the inactivity window. But the receive loop also stops reading while it is parked handing a message off to a busy decryption worker: in that window the stream looks silent though it is healthy. The watchdog read that self-inflicted backpressure as a dead stream and reconnected, and each reconnect re-triggered offers to peers, feeding a churn loop that left peers stuck connecting/relayed instead of going direct. - Track when the receive loop is blocked on the worker handoff - Treat the stream as alive in that state so the watchdog does not reconnect, since a reconnect feeds the same worker and cannot help; a genuinely silent stream (loop reading, worker idle) is still detected and reconnected ## Issue ticket number and link N/A ## Stack <!-- branch-stack --> ### Checklist - [x] Is it a bug fix - [ ] Is a typo/documentation fix - [ ] Is a feature enhancement - [ ] It is a refactor - [x] Created tests that fail without the change (if possible) - [ ] This change does **not** modify the public API, gRPC protocols, functionality behavior, CLI / service flags, or introduce a new feature — **OR** I have discussed it with the NetBird team beforehand (link the issue / Slack thread in the description). See [CONTRIBUTING.md](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTING.md#discuss-changes-with-the-netbird-team-first). > By submitting this pull request, you confirm that you have read and agree to the terms of the [Contributor License Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md). ## Documentation Select exactly one: - [ ] I added/updated documentation for this change - [x] Documentation is **not needed** for this change (explain why) Internal change to the client's signal connection-recovery logic; no user-facing surface. ### Docs PR URL (required if "docs added" is checked) Paste the PR link from https://github.com/netbirdio/docs here: https://github.com/netbirdio/docs/pull/__ <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Refined the receive-stream watchdog liveness logic to prevent false “dead stream” detection during intentional receive-to-decryption handoff backpressure. * Watchdog now holds off reconnect behavior when inactivity is due to worker handoff rather than true network silence. * **Diagnostics** * Added a worker queue-length metric for decrypted backlog visibility. * Improved watchdog “holding stream” and engine restart logging details; adjusted ICE candidate-pair logging verbosity. * **Tests** * Added a test covering watchdog liveness behavior for both handoff-blocked and true receive-inactivity scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
saavagebueno added the pull-request label 2026-08-05 08:06:16 -04:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: DYNR/netbird#28387