Blocks #768.
I assumed we already had this and we don't. RecRolePingService detects a rec role ping on messageCreate, posts the opt-in reminder, and throws the observation away — no entity, no repository, no timestamp. The only trace a ping ever happened is an application log line, which isn't queryable. So there is no "last time this role was used" to read, and #768 can't start until there is.
Every day this isn't recording is a day added to the wait before the first prune.
What to build
A new RecRoleUsageEntity, one row per rec game role, keyed on role ID rather than name so a rename doesn't split the series (Warcaster → EldritchMage in #519 is the precedent):
| column |
why |
roleId (unique) |
the stable key |
roleName |
denormalised for reports, refreshed on each observation |
firstObservedAt |
so nothing gets pruned for being quiet when we've only been watching it a fortnight |
lastMentionedAt (nullable) |
the actual signal |
mentionCount |
separates "pinged once, ever" from "pinged weekly" |
lastMentionChannelId / lastMentionMessageId |
audit trail for when someone disputes a prune |
Wiring, both hooks already exist:
gatherRolesCron (hourly) already enumerates every rec role — have it upsert a row per role, so roles that have never been pinged still get a firstObservedAt and appear in the data as a genuine null rather than as an absence.
onMessage already computes mentionedRecRoles — have it stamp lastMentionedAt and bump mentionCount.
The writes should live in a new RecRoleUsageService rather than inline in RecRolePingService, so recording doesn't depend on the reminder post succeeding. Today a failed channel.send is caught and swallowed; the observation must not go with it.
No new gateway intent needed — mention_roles arrives on the message payload regardless of MessageContent, which we don't have.
Scope
In:
- entity + migration
RecRoleUsageService with the upsert and the stamp
- unit tests
Out, and tracked on #768:
- the staleness report and warning notice
- anything that deletes a role
- the history backfill (worth doing, but it's a separate one-off script and this shouldn't wait on it)
Known trap
MessageEvents.handleMessageEvent returns early for bot authors, so a rec role ping sent by a scheduled-event bot or a webhook records nothing and the role will read as dead. Worth confirming against real usage in the guild before the data gets trusted for a prune decision — if it turns out pings do come from bots, this needs handling before #768 acts on any of it.
Blocks #768.
I assumed we already had this and we don't.
RecRolePingServicedetects a rec role ping onmessageCreate, posts the opt-in reminder, and throws the observation away — no entity, no repository, no timestamp. The only trace a ping ever happened is an application log line, which isn't queryable. So there is no "last time this role was used" to read, and #768 can't start until there is.Every day this isn't recording is a day added to the wait before the first prune.
What to build
A new
RecRoleUsageEntity, one row per rec game role, keyed on role ID rather than name so a rename doesn't split the series (Warcaster→EldritchMagein #519 is the precedent):roleId(unique)roleNamefirstObservedAtlastMentionedAt(nullable)mentionCountlastMentionChannelId/lastMentionMessageIdWiring, both hooks already exist:
gatherRolesCron(hourly) already enumerates every rec role — have it upsert a row per role, so roles that have never been pinged still get afirstObservedAtand appear in the data as a genuine null rather than as an absence.onMessagealready computesmentionedRecRoles— have it stamplastMentionedAtand bumpmentionCount.The writes should live in a new
RecRoleUsageServicerather than inline inRecRolePingService, so recording doesn't depend on the reminder post succeeding. Today a failedchannel.sendis caught and swallowed; the observation must not go with it.No new gateway intent needed —
mention_rolesarrives on the message payload regardless of MessageContent, which we don't have.Scope
In:
RecRoleUsageServicewith the upsert and the stampOut, and tracked on #768:
Known trap
MessageEvents.handleMessageEventreturns early for bot authors, so a rec role ping sent by a scheduled-event bot or a webhook records nothing and the role will read as dead. Worth confirming against real usage in the guild before the data gets trusted for a prune decision — if it turns out pings do come from bots, this needs handling before #768 acts on any of it.