Skip to content

[P1] Make presence leave flow connection-aware across multiple tabs #177

Description

@smereczynski

Priority: P1 (High)

Category: Correctness / Presence Management

Issue

The hub maintains _UserConnectionCounts to keep a user present while multiple tabs or connections remain open, but PresenceController.Leave() removes the user from the presence tracker immediately without considering active connection count. One tab can therefore make the user appear offline even when another connection is still active.

Location

  • src/Chat.Web/Controllers/PresenceController.cs
  • src/Chat.Web/Hubs/ChatHub.cs

Risk

  • Presence state becomes incorrect for multi-tab users
  • Users can disappear from room presence while still connected
  • Presence change notifications become inconsistent with hub lifecycle
  • Debugging connection and presence issues becomes harder

Proposed Fix

Unify presence removal semantics so HTTP leave actions and hub disconnect actions use the same connection-aware model.

Suggested implementation direction:

  • Make leave room-scoped instead of removing the whole user presence record, or
  • Route presence removal through a shared service that understands active connection count
  • Avoid direct RemoveUserAsync from controller code unless the last connection is known to be closed
  • Add tests covering multiple simultaneous connections for the same user

Effort Estimate

1-2 hours

Acceptance Criteria

  • A leave action from one tab does not remove presence for other active connections
  • Presence tracker behavior matches hub connection-count semantics
  • Tests cover single-tab and multi-tab leave and disconnect flows
  • Presence snapshots remain consistent after mixed HTTP leave and SignalR disconnect sequences
  • Logging makes the chosen leave semantics explicit

Reference

Static review finding from architecture and correctness review of src on 2026-05-02

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions