fix: presence unreliable within same pod
It was broadcasting presence changes to other pods, but not notifying clients connected to the same pod
This commit is contained in:
@@ -101,6 +101,9 @@ func (h *Hub) handleSubscribe(ctx context.Context, req *subscribeRequest) {
|
|||||||
h.channels[req.channelID] = ch
|
h.channels[req.channelID] = ch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Capture before addMember so multi-tab joins don't emit a spurious join.
|
||||||
|
wasPresentLocally := ch.hasHumanID(req.conn.humanID)
|
||||||
|
|
||||||
// Add to local channel
|
// Add to local channel
|
||||||
ch.addMember(req.conn, req.conn.humanID)
|
ch.addMember(req.conn, req.conn.humanID)
|
||||||
|
|
||||||
@@ -124,6 +127,16 @@ func (h *Hub) handleSubscribe(ctx context.Context, req *subscribeRequest) {
|
|||||||
Channel: req.channelID,
|
Channel: req.channelID,
|
||||||
Presence: presence,
|
Presence: presence,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Notify other local members. The Redis self-filter drops our own echo,
|
||||||
|
// so same-pod peers would otherwise never hear about this join.
|
||||||
|
if !wasPresentLocally {
|
||||||
|
ch.broadcast(ServerMessage{
|
||||||
|
Type: TypeJoin,
|
||||||
|
Channel: req.channelID,
|
||||||
|
HumanID: req.conn.humanID,
|
||||||
|
}, req.conn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Hub) handleUnsubscribe(ctx context.Context, req *unsubscribeRequest) {
|
func (h *Hub) handleUnsubscribe(ctx context.Context, req *unsubscribeRequest) {
|
||||||
@@ -144,6 +157,16 @@ func (h *Hub) handleUnsubscribe(ctx context.Context, req *unsubscribeRequest) {
|
|||||||
slog.Error("redis unsubscribe failed", "channelId", req.channelID, "error", err)
|
slog.Error("redis unsubscribe failed", "channelId", req.channelID, "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notify other local members iff the humanID is fully gone from this pod
|
||||||
|
// (multi-tab: other conns keep them present, so no leave fires).
|
||||||
|
if !ch.hasHumanID(req.conn.humanID) {
|
||||||
|
ch.broadcast(ServerMessage{
|
||||||
|
Type: TypeLeave,
|
||||||
|
Channel: req.channelID,
|
||||||
|
HumanID: req.conn.humanID,
|
||||||
|
}, req.conn)
|
||||||
|
}
|
||||||
|
|
||||||
// Clean up empty local channel
|
// Clean up empty local channel
|
||||||
if ch.isEmpty() {
|
if ch.isEmpty() {
|
||||||
delete(h.channels, req.channelID)
|
delete(h.channels, req.channelID)
|
||||||
@@ -192,6 +215,14 @@ func (h *Hub) handleDisconnect(ctx context.Context, conn *Conn) {
|
|||||||
slog.Error("redis unsubscribe on disconnect failed", "channelId", channelID, "error", err)
|
slog.Error("redis unsubscribe on disconnect failed", "channelId", channelID, "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !ch.hasHumanID(conn.humanID) {
|
||||||
|
ch.broadcast(ServerMessage{
|
||||||
|
Type: TypeLeave,
|
||||||
|
Channel: channelID,
|
||||||
|
HumanID: conn.humanID,
|
||||||
|
}, conn)
|
||||||
|
}
|
||||||
|
|
||||||
if ch.isEmpty() {
|
if ch.isEmpty() {
|
||||||
delete(h.channels, channelID)
|
delete(h.channels, channelID)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user