How AA24 Works - Race Condition
In AviAwards 24, we have two systems that work together to ensure that the event runs smoothly. These systems are the Voting Game (Roblox), and Booking Game (Roblox). These two systems allows users to vote for their favorite nominees, and book seats in the theater respectively.
However, as many of you who have recently tried booking a seat on other platforms (like Ticketmaster) may know, there is usually a queue of some sort for booking seats. This is common in many booking systems, and is used to avoid a issue known as “Race Condition”.
What is a Race Condition
A race condition occurs when multiple users try to access and modify the same resource simultaneously, potentially leading to data inconsistency.
In terms of seat booking:
- Two users select the same seat at nearly the same time
- Both users think the seat is available
- Both try to book it simultaneously
- System gets confused about who actually owns the seat
Real-world example: Imagine two people trying to sit in the same chair at the same time. Without proper coordination (like taking turns or queuing), they might collide or argue over who got there first.
In terms of Voting:
- Two users vote at almost the same instant
- Both users’ votes are being processed simultaneously
- System tries to update the total vote count
- Final count might be incorrect as votes overlap
For example: If the count is 100, and two people vote at once, the system might only count one vote, ending at 101 instead of the correct 102.
As such, this requires us to design a system that could, at their architecture level, prevent these issue from happening.
How AA24 Gets Around Race Condition
To prevent these headaches, the games uses some clever tricks to make sure everything run according to plan:
Seat Booking
- Per-Seat Key Session Locking: When a user clicks on a seat, we immediately put a temporary “lock” on it using
MemoryStoreService. Think of it like putting a “reserved” sign on the chair. This lock is unique to that user’s session and that specific seat. If someone else tries to grab the same seat while it’s locked, they’ll be told it’s unavailable. - Entire Seat Data Locking with ProfileService: We use the
ProfileStorelibrary to lock the entire seating data when it’s being actively updated. This prevents any accidental overwrites or conflicts if multiple people, across different servers, are booking at once.ProfileStoreis pretty new, but it’s been working great for us so far. - Promo Code Session Locking: Promocode uses
MemoryStoreServiceas well for session locking before trying to actually redeem it (by talking to our promocode backend, which we manage with NocoDB), we make sure the promo code isn’t being redeemed by multiple users at the same time.
Voting
- Per-User Key Storage: Instead of having one giant database where all votes are tallied, we store each user’s vote individually, tied to their unique Roblox user ID. This is a fairly commonly pattern that I’m sure most of you guys know already(if you’re coming from a Roblox Gamedev background). Imagine everyone having their own ballot box. This way, there’s no central point of contention where votes can collide. We use
ProfileService, which is is battle-tested in a lot of real world situation and games, so we’re pretty sure it’s reliable and robust, even in our use case. - Vote Exporting with OpenCloudTools: To count the votes, we use a custom tool built on top of the data
OpenCloudToolsexported. Once exported, we can safely and accurately tally the votes without worrying about race conditions, as each user’s vote is separate. You can check outOpenCloudToolshere: https://github.com/jlwitthuhn/OpenCloudTools, it’s a pretty neat tool that is surprisingly underused.
If you want to learn more about some of these approaches, feel free to DM me on Discord. We’ve also open-sourced some of our tools and projects, so you can check them out and use them in your own projects Source of the Voting Game on GitHub Source of the Booking Game on GitHub
And no we did not rig the votes lol