-
Notifications
You must be signed in to change notification settings - Fork 160
Open
Description
Description
The rating update logic uses a "Read-Calculate-Write" pattern without locking. If a user completes two matches efficiently (e.g., in two browser tabs or against two fast bots), the second update may overwrite the first update's results.
How to Reproduce
- User A (Rating 1200) finishes Match 1. Server reads 1200.
- Milliseconds later, User A finishes Match 2. Server reads 1200 (Match 1 write hasn't finished).
- Match 1 calculation sets Rating to 1210. Writes to DB.
- Match 2 calculation sets Rating to 1190 (based on 1200). Writes to DB.
- Final Rating is 1190. The gain from Match 1 is completely lost.
Root Cause
In rating_service.go, UpdateRatings retrieves the user object, performs math in Go, and then sets the new values with $set. It does not check if the document changed in between.
Expected Behavior
Both match results should be applied sequentially and correctly.
Potential Fixes
- Use MongoDB FindOneAndUpdate to perform the read and write atomically (though Glicko math is complex to do in-db).
- Use Optimistic Locking: Include a version field in the User document. Update only if version matches the read version. Retry if it fails.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels