Skip to content

Add server-side revalidation of total score matching active mods#379

Merged
peppy merged 9 commits into
ppy:masterfrom
bdach:total-score-correction
Jun 17, 2026
Merged

Add server-side revalidation of total score matching active mods#379
peppy merged 9 commits into
ppy:masterfrom
bdach:total-score-correction

Conversation

@bdach

@bdach bdach commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

This PR adds a processor that checks whether for incoming scores data->'$.total_score_without_mods' matches total_score as defined by the latest score multiplier calculator. This allows an instant cutoff rollout of the new multipliers for all incoming scores without needing to wait on client rollouts.

  • If total_score does not match total_score_without_mods, total_score is rewritten based on total_score_without_mods and the active mods for the score.
  • If total_score_without_mods is missing, the score is marked unranked. Production was checked for this, and there have been no incoming legitimate scores without total_score_without_mods for more than a year now.

Of particular note, this processor must run before everything else, because of data dependencies. Other processors read and do things with total_score, such as add it to profile ranked score, or check it for medal purposes, and so on.

The processor is instrumented with a Datadog counter of scores it rewrote. For this counter I had to commit 19c343d because otherwise it's kind of not possible to log things with the correct Datadog prefix.

@bdach bdach self-assigned this Jun 4, 2026
@bdach bdach moved this from Inbox to Pending Review in osu! team task tracker Jun 4, 2026
@bdach

bdach commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator Author

Self-check done, seems to be working as intended as far as my testing goes (tested with old and new lazer client, have not tested score imports, have not tested ddog metrics).

@bdach bdach marked this pull request as ready for review June 5, 2026 10:02
@peppy peppy self-requested a review June 5, 2026 10:09
try
{
p.ApplyToUserStats(score, userStats, conn, transaction, postTransactionActions);
p.ApplyToUserStats(score, userStats, conn, transaction, postTransactionActions, DogStatsd);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kinda ugly ain't it. Considered adding to interface and passing on start, but not much better.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I almost introduced a context holder object to pass around to these processors instead of spamming further parameters but it would be even more of a disaster on diff size than this already is.

@peppy peppy Jun 5, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, context would be the other direction. Or just making the DogStatsd field static..

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or just making the DogStatsd field static..

That would require a PR in another project and a NuGet package bump after 🙈

Legitimately spent like half an hour mulling over the least worst method to do this.

@peppy

peppy commented Jun 5, 2026

Copy link
Copy Markdown
Member

Intentionally not merging just yet.

@peppy peppy merged commit 8145ca2 into ppy:master Jun 17, 2026
4 checks passed
@github-project-automation github-project-automation Bot moved this from Pending Review to Done in osu! team task tracker Jun 17, 2026
@bdach bdach deleted the total-score-correction branch June 17, 2026 05:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants