I'm using a cloud function for match making.
This is my approach:
- User A creates a request which will add a document into requests collection
- If User B with same language requests, then I am querying the requests collection to get the oldest request by any user which in this case is User A and then deleting both A and B's request
- Add a document in active-pairs collection
This leads to race conditions in production. Is there any better approach for the same ?
i only have gpt to ask would u want to read its answer
- Atomic Document Creation: When a user creates a matchmaking request, create a new document with a unique identifier that includes user information, request details, and a timestamp. This should be done atomically to avoid race conditions.
- Scheduled Background Process: Implement a scheduled background process or cloud function that runs at regular intervals. This process will perform the matchmaking by identifying potential matches among the requests.
- Matching Logic: Within the background process, query the requests collection for potential matches based on language or other criteria. Group the requests by language and then timestamp.
- Create Active Pairs: For each group of potential matches, create active-pairs documents atomically while deleting the respective requests. This helps prevent race conditions, as the matchmaking process is now centralized and not directly influenced by individual user actions.
- Expiry and Cleanup: To handle cases where requests don't find matches, implement an expiry mechanism. If a request remains unmatched for a certain period, the background process can clean up expired requests.
- Notification System: Implement a notification system to inform users when a match is found. This can be done via real-time messaging or email.
- Database Transactions: If your database supports transactions, use them for the creation of active-pairs documents and the deletion of requests. This ensures atomicity and consistency.
- Load Balancing: Distribute the background matchmaking process across multiple instances to handle high loads efficiently.
By moving the matchmaking process to a centralized background function, you can better control the timing of matches and avoid many race conditions associated with individual requests. This approach should help you create a more reliable and consistent matchmaking system in a production environment.
The best way to prevent race conditions is with clever use of unique indexes. In short, the unique index can prevent multiple users from grabbing the same request
You might want to have a matches collection and a unique index on that.
I'm getting confused. Can you please help me with it ?
Do you understand how to use a unique index to prevent race conditions?
What I understood was:
- User A's request is in queue (ie requests collection)
- User B makes a request
- Now I will try adding a document with the user A and B's requestDocId to matches collection which has an attribute to hold the doc id of A and B and which is unique
But in this case, if a document's userDocId1 is present in another document's userDocId2. How can I check that ?
I think you can use bool check if there is a match you can set this to true otherwise it should be false.
But i guess even that will lead to race conditions in production.
The race condition you need to prevent is multiple users matching with user A
So maybe have a request lock collection with the unique index. When user b creates a document in there with the user a request, they have a lock on that and will prevent others from also grabbing that request
So, is there any way to execute a cloud function in the middle of create document initiation to just before adding a document to a collection so that we can prevent another user C from getting paired with B ?
When there is already a request of user A in collection and when user B try to find the match, you can first check if there is a match present in the collection or not if present then don't create user B's request and create new document in pair match collection with both user ids along with user A request id or if match is not present then create user B's request in request collection. This way if user A and B matched then user C will not match with A or B user.
A function wouldn't help with that. The requests lock collection with unique index is what I was suggesting to prevent another user C from getting the request from user B while A
See my previous message
@Steven unique index on which attribute?
Checked this. But didnt actually get what you meant. :/
This is what is implemented as of now afaik
Share more info about your collection, so we can help you with the Steven approach
So you want to avoid the race condition in active-pairs
right? can you explain the attributes in the active-pairs
? what Steven said was to create a unique index, to avoid multiples values in the collection, to do that you can use for example userName1
and userDocId1
for your index. This will throw an error when this two values are stored in the collection and the function try to add it again
Thanks. I have made necessary changes. Will test it and get back to you if I have any questions.
Hey @Chandan Gowda did you solve your problem?
Recommended threads
- Type Mismatch in AppwriteException
There is a discrepancy in the TypeScript type definitions for AppwriteException. The response property is defined as a string in the type definitions, but in pr...
- [SOLVED] OAuth With Google & Flutter
Hi all, I'm trying to sign in with google and it all goes swimmingly until the call back. I get a new user created on the appwrite dashboard however the flutte...
- What Query's are valid for GetDocument?
Documentation shows that Queries are valid here, but doesn't explain which queries are valid. At first I presumed this to be a bug, but before creating a githu...