2.0 KiB
Leaderboard bot integration
The Discord bot owns all writes to user_levels and voice_time. The website only
subscribes to notifications and then reads the committed database state.
Redis channel
Publish leaderboard notifications to exactly:
erika:sse:leaderboards
The bot and website use the same Redis deployment. Do not add Redis credentials to source code or event payloads.
Event envelopes
XP changes use this exact JSON envelope:
{"event":"xp","data":{}}
Voice-time changes use the affected Discord channel ID:
{"event":"vc","data":{"channelId":"123456789012345678"}}
No additional envelope or data fields are accepted. channelId is a Discord
snowflake represented as a decimal string.
Publish ordering
- Start and complete the bot’s database transaction.
- Confirm that the transaction committed successfully.
- Publish the corresponding Redis event or events.
Never publish before commit, from a rollback path, or from a finally block. The
notification tells an open website page to read the database again, so publishing
before commit can produce a stale refresh.
Event cardinality
- Publish one XP event when one transaction changes XP data.
- Publish one VC event per affected channel when one transaction changes voice time.
- When one transaction changes both XP and voice time, publish one XP event and one VC event for each affected channel.
- For a bulk transaction, deduplicate affected scopes and channel IDs. Publish per affected scope/channel, never per user.
Example: a bulk transaction changes XP for 200 users and voice time in channels 111
and 222. After commit, publish three events: one XP event, one VC event for 111,
and one VC event for 222.
Error handling
Publishing is best-effort. Log Redis failures with enough context to identify the event scope, but do not roll back or report a successfully committed database transaction as failed. Open pages recover on SSE reconnection or the next navigation.