Repository navigation
fix(anticheat): stop duplicate module reports flooding the database and Sentry - #79
Open
tintinhamans wants to merge 3 commits into
Open
tintinhamans wants to merge 3 commits into
tintinhamans wants to merge 3 commits into
Conversation
…nd Sentry Every anti-cheat probe response re-inserted each non-allowlisted module, one DbContext per module, and every repeat in the same match hit the user_id_match_id_module_name unique key. Each failure was logged and sent to Sentry: millions of events that exhausted the error quota, so all project errors have been dropped since 2026-10-11. Modules already flagged for the current match are now remembered on the session, the remaining ones are written in one batched INSERT ... ON DUPLICATE KEY UPDATE per probe response, the allowlists are parsed once and refreshed on config reload, and expected duplicate keys are never reported. The CRC review insert gets the same idempotent upsert. Fixes SERVICES-47 Fixes SERVICES-4B
The EF Core migration lost the original ON DUPLICATE semantics. Connection outcomes and service stats raced on their day/hour keys at rollover, player stats lost concurrent updates in a read-modify-write of the JSON document, device registration could collide on concurrent logins, and leaderboard row creation rolled back all three tables when one row existed. Each now uses a single INSERT ... ON DUPLICATE KEY UPDATE that preserves the original behaviour (increments, GREATEST peaks, JSON_SET per stat, no-op on existing rows). Fixes SERVICES-41
…cates ac_reviews_crc's primary key spans all four columns, including most_recent_match, so a duplicate is an identical report and there is nothing to refresh. Update the comment and statement to say so.
Skyaero42
approved these changes
Oct 27, 2026
Skyaero42
left a comment
There was a problem hiding this comment.
I struggle with the AntiCheat.cs file because I'm not familiar with the implemention yet.
The rest looks good.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Remembers which modules were already flagged for the current match on the session, so repeated anti-cheat probes no longer re-insert the same modules. Each probe response now writes the remaining ones in a single batched
INSERT ... ON DUPLICATE KEY UPDATEinstead of one DbContext and insert per module. Before this, every repeat hit theuser_id_match_id_module_nameunique key and was logged and sent to Sentry, roughly a million times every six hours in prod. That used up the Sentry error quota, so nothing from the service has reached Sentry since 2026-10-11.The allowlists are parsed once and refreshed on config reload instead of per module, and expected duplicate keys are no longer reported. Connection outcomes, service stats, player stats, device registration, leaderboard rows and the CRC review insert had the same lost
ON DUPLICATEbehaviour from the EF Core move, so they're atomic upserts now too, keeping their old semantics (in-database increments,GREATESTpeaks, per-statJSON_SET, no-op on existing rows). All statements were checked against the prod schema on MariaDB 10.11.This adds raw MySQL SQL back, which conflicts with #77. Once that lands I'll move the upserts to the provider-neutral setup; the session dedupe doesn't depend on the database and covers almost all of the volume on its own.