@@ -23,6 +23,8 @@ import (
2323 "go.etcd.io/etcd/raft/v3/raftpb"
2424 "go.opentelemetry.io/otel"
2525 "go.opentelemetry.io/otel/trace"
26+
27+ "google.golang.org/grpc/connectivity"
2628 "google.golang.org/protobuf/proto"
2729
2830 "github.com/dgraph-io/badger/v4/y"
@@ -760,10 +762,13 @@ func (n *Node) joinCluster(ctx context.Context, rc *pb.RaftContext) (*api.Payloa
760762 return nil , errors .Errorf ("REUSE_RAFTID: Raft ID duplicates mine: %+v" , rc )
761763 }
762764
763- // Check that the new node is not already part of the group.
765+ // Reject if a peer with the same Raft ID is already registered at a
766+ // different address AND that peer is still genuinely connected. Using the
767+ // gRPC connection state is more accurate than IsHealthy(), which relies on
768+ // a heartbeat timestamp and stays "healthy" for ~2s after the peer drops.
764769 if addr , ok := n .Peer (rc .Id ); ok && rc .Addr != addr {
765- // There exists a healthy connection to server with same id.
766- if _ , err := GetPools ().Get ( addr ); err == nil {
770+ if pool , err := GetPools (). Get ( addr ); err == nil &&
771+ pool . Get ().GetState () == connectivity . Ready {
767772 return & api.Payload {}, errors .Errorf (
768773 "REUSE_ADDR: IP Address same as existing peer: %s" , addr )
769774 }
0 commit comments