[PR #5185] [management] Add heartbeat to Job endpoint to prevent proxy timeouts #27299

Open
opened 2026-08-05 07:08:31 -04:00 by saavagebueno · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/netbirdio/netbird/pull/5185
Author: @maxpain
Created: 1/26/2026
Status: 🔄 Open

Base: mainHead: fix/job-endpoint-heartbeat


📝 Commits (2)

  • 2fd3035 [management] Add heartbeat to Job endpoint to prevent proxy timeouts
  • 7a99e07 Address review feedback

📊 Changes

2 files changed (+71 additions, -12 deletions)

View changed files

📝 management/internals/shared/grpc/server.go (+66 -12)
📝 management/server/job/channel.go (+5 -0)

📄 Description

Summary

  • Add 30-second heartbeat to the /management.ManagementService/Job streaming endpoint to keep connections alive through reverse proxies

Problem

The Job streaming endpoint blocks indefinitely when there are no pending jobs, causing reverse proxies (Traefik, Cloudflare, Nginx) to timeout the connection after their idle timeout period (typically 60-120 seconds).

While the gRPC server has keepalive configured (HTTP/2 PING frames), reverse proxies measure idle time based on HTTP/2 DATA frames, not PING frames. This causes 504 Gateway Timeout errors for self-hosted deployments behind proxies.

Solution

Add a periodic heartbeat (every 30 seconds) that sends an empty JobRequest to keep the stream active. The client already handles empty messages gracefully — it logs "received unknown or empty job request, skipping" and continues.

Changes

  • management/server/job/channel.go: Add EventChan() method to expose channel for select
  • management/internals/shared/grpc/server.go: Modify sendJobsLoop to use ticker + add sendHeartbeat method

Test plan

  • Verified build passes
  • Tested with Traefik proxy (timeout issue resolved)
  • Run existing tests

Fixes #5184

Summary by CodeRabbit

  • New Features

    • Periodic heartbeat messaging added to keep job streams active and reduce unexpected disconnects.
    • Streaming loop upgraded for more responsive, event-driven job delivery.
    • Exposed a read-only events channel for safer integration with select-based consumers.
  • Bug Fixes

    • Improved error handling and connection lifecycle control for more reliable job delivery.

✏️ Tip: You can customize this high-level summary in your review settings.


🔄 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/5185 **Author:** [@maxpain](https://github.com/maxpain) **Created:** 1/26/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/job-endpoint-heartbeat` --- ### 📝 Commits (2) - [`2fd3035`](https://github.com/netbirdio/netbird/commit/2fd30358892c7543b523b76d0b374a54dc13f3d6) [management] Add heartbeat to Job endpoint to prevent proxy timeouts - [`7a99e07`](https://github.com/netbirdio/netbird/commit/7a99e0793f4efa1ec2372d360573fe7b331df4ab) Address review feedback ### 📊 Changes **2 files changed** (+71 additions, -12 deletions) <details> <summary>View changed files</summary> 📝 `management/internals/shared/grpc/server.go` (+66 -12) 📝 `management/server/job/channel.go` (+5 -0) </details> ### 📄 Description ## Summary - Add 30-second heartbeat to the `/management.ManagementService/Job` streaming endpoint to keep connections alive through reverse proxies ## Problem The Job streaming endpoint blocks indefinitely when there are no pending jobs, causing reverse proxies (Traefik, Cloudflare, Nginx) to timeout the connection after their idle timeout period (typically 60-120 seconds). While the gRPC server has keepalive configured (HTTP/2 PING frames), reverse proxies measure idle time based on HTTP/2 DATA frames, not PING frames. This causes **504 Gateway Timeout** errors for self-hosted deployments behind proxies. ## Solution Add a periodic heartbeat (every 30 seconds) that sends an empty `JobRequest` to keep the stream active. The client already handles empty messages gracefully — it logs "received unknown or empty job request, skipping" and continues. ## Changes - `management/server/job/channel.go`: Add `EventChan()` method to expose channel for select - `management/internals/shared/grpc/server.go`: Modify `sendJobsLoop` to use ticker + add `sendHeartbeat` method ## Test plan - [x] Verified build passes - [x] Tested with Traefik proxy (timeout issue resolved) - [ ] Run existing tests Fixes #5184 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Periodic heartbeat messaging added to keep job streams active and reduce unexpected disconnects. * Streaming loop upgraded for more responsive, event-driven job delivery. * Exposed a read-only events channel for safer integration with select-based consumers. * **Bug Fixes** * Improved error handling and connection lifecycle control for more reliable job delivery. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- 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 07:08:31 -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#27299