Skip to content

Fix cluster publish forwarding when peer connection is down#1931

Open
vazois wants to merge 6 commits into
mainfrom
vazois/pubsub-forward-fix
Open

Fix cluster publish forwarding when peer connection is down#1931
vazois wants to merge 6 commits into
mainfrom
vazois/pubsub-forward-fix

Conversation

@vazois

@vazois vazois commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #1928 and #1929. When a peer cluster node goes down after a gossip timeout, its GarnetServerNode stays registered while the inner GarnetClient socket is disposed. Forwarding a publish then dereferenced a disconnected client, throwing on the network thread (NullReferenceException) and cascading into an unresponsive process.

Fix

Guard TryClusterPublish with !gc.IsConnected: log and skip forwarding when the gossip client is down. The connection is transient and gossip re-establishes it; admins can CLUSTER FORGET or raise the gossip timeout otherwise.

Test

ClusterPublishSurvivesPeerNodeShutdown (2-node cluster): baseline cross-node publish, shut down the peer, then assert the survivor stays responsive (PING) and PUBLISH recovers. Timing-insensitive; fails when the fix is reverted (socket closes, 0 recoveries).

@vazois vazois marked this pull request as ready for review July 14, 2026 20:50
Copilot AI review requested due to automatic review settings July 14, 2026 20:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a cluster pub/sub forwarding failure mode where a peer node can remain registered after a gossip timeout while its underlying gossip GarnetClient connection is disposed, causing PUBLISH forwarding to throw on the network thread and potentially degrade process responsiveness.

Changes:

  • Add a connectivity guard in GarnetServerNode.TryClusterPublish to skip forwarding when the gossip client is not connected.
  • Add a 2-node cluster regression test that shuts down one node and asserts the surviving node remains responsive and PUBLISH stops failing permanently.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
libs/cluster/Server/Gossip/GarnetServerNode.cs Adds an IsConnected check to avoid forwarding publishes through a disconnected/disposed gossip client.
test/cluster/Garnet.test.cluster/ClusterPubSubForwardTests.cs Adds a regression test covering peer shutdown during publish forwarding and server responsiveness.

Comment thread libs/cluster/Server/Gossip/GarnetServerNode.cs
Comment on lines +86 to +90
Assert.DoesNotThrow(
() => pubRedis.GetServer(publisherEndpoint).Execute("PUBLISH", channelName, message),
"Baseline publish threw while both nodes were up");
ClassicAssert.IsTrue(delivered.Wait(TimeSpan.FromSeconds(15)),
"Baseline publish was not forwarded/delivered while both nodes were up");
Comment on lines +174 to +177
catch (RedisConnectionException)
{
// Transient client-side reconfiguration after peer shutdown; retry.
}
@sanamhub

sanamhub commented Jul 14, 2026

Copy link
Copy Markdown

@vazois thanks for the quick fix. This PR will be backported to stable channel or not?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: NullReferenceException in TryClusterPublishAsync after gossip timeout breaks cluster pub/sub

3 participants