Search code examples
databasegoogle-cloud-firestoreconcurrencylocking

Firestore: handling concurrency with booking app


I've currently got a bookings and a bookable collection. Each document in bookings holds a date range (check-out and check-in) and an array of references to bookable documents.

I'm a bit stumped at how to guarantee two overlapping bookings for the same bookables aren't written at the same time. From what I understand I can't technically lock a collection via something like a transaction, so I'm wondering what my options are (perhaps restructuring how I'm storing data, etc).

Any pointers or advice would be much appreciated.

EDIT:

Say User A wants to make a booking for the same two items as User B does and for the same time range. They both load the booking UI at around the same time and confirm their selection.

Prior to creating a new document inside the bookings collection for each of their requests, the app would perform a get query to check for any overlaps and if none exist insert the new booking documents. That fraction of time between the app's check for overlaps across the booking collection and the creation of new documents is what seems to open up a window for inconsistencies (e.g. potentially allowing two documents with overlapping time ranges and items to be created).

Could a transaction help prevent a new document being written to a collection based the existance of other documents in that collection that fit a specific criteria?


Solution

  • To prevent users from accidentally overwriting each other's data, you'll want to use a transaction.

    To prevent users from intentionally overwriting each other's data, you'll want to use security rules. Key to this is to use the information that you want to be unique as the ID of the documents.

    So say you identify time slots by the date and start time, you could have a document ID "20210420T0900". If a user is trying to write to that document when it already exists, you can reject that write in the security rules of your database.