polyphony-chat / symfonia

A Polyphony chat server, compatible with Spacebar and the Discord API.
Mozilla Public License 2.0
25 stars 3 forks source link

Events via WebSocket #48

Open bitfl0wer opened 2 months ago

bitfl0wer commented 2 months ago

To make Events via WebSockets as efficient as possible, we strive to reduce database operations by using a caching system that immediately tells us, which event is supposed to be sent to which client.

Splitting up the problem

Tackling this problem is best with a bit of divide and conquer, meaning: Instead of tackling the entire problem as a whole, we should divide it into smaller parts first, then tackle those smaller parts.

If we think about it, ~95% of events are emitted in the context of a Guild. Whether it is new messages, guild member updates or changes to channels and channel state (voicechat joins/leaves) - all of these can be traced back to a Guild. However, Guilds are not a fine enough denominator when it comes to determining whether a user should receive an event or not. Think of the case where Guild moderators have a moderator-only channel - it would be bad if the MessageCreate events in that channel were sent to everyone on that Guild.

One level "below" Guilds are Roles. Every user has at least the @\everyone role, and roles with their assigned permissions determine which channels a user can and cannot see.

But there are two slight problems:

  1. Using only roles to determine event-eligibility would make channel/category permission overrides for individual users useless.
  2. The other ~5% of our Gateway traffic are caused by DMs, Group DMs and Inter-User relationships. Roles do not work here either

As such, the second "bin" with which we determine event eligibility should be individual user IDs.

The end result

In the end, we have two "bins" of eligible subscribers for events:

Using a mathematical set like HashSet<T>, we can deduplicate, so that one user doesn't receive an event twice, then send the event to all recipients.

Tracking tasks