0

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?

ghjunior
  • 119
  • 10
  • Your options are in https://firebase.google.com/docs/firestore/manage-data/transactions. If you're having a hard time making that work, share a specific use-case, show what you've tried already in code, and where it failed. – Frank van Puffelen Apr 20 '21 at 14:59
  • Thanks @FrankvanPuffelen, perhaps you're right. I've updated the post with a more detailed explanation of my doubts. – ghjunior Apr 20 '21 at 16:29

2 Answers2

0

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.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks Frank. In the case that the uniqueness of the booking is composed of both time range and booked items (ID's), then perhaps I would need to rethink my database structure, eh? I initially had tried keeping bookings as nested collections under each item but found that strange since each nested booking had it's own ID, but your answer made me think to revisit this approach and potentially use a time identification together with user ID as the nest booking document ID, and then "merge" bookings into one on the UI side to represent one "big" booking of multiple items. – ghjunior Apr 20 '21 at 20:10
  • You could include the item ID in the document ID. It sounds like you'd want a separate booking doc for each item them, so combining a batched write/transaction to ensure all items in the booking are written atomically with security rules to prevent users intentionally overwriting each other's booking. All possible, so if you have problems implement it, I recommend opening a new question with code and data of what you tried and debugging details of what goes wrong. – Frank van Puffelen Apr 20 '21 at 21:01
0

I am facing the exact same problem, and here is my best option at the moment....

I need a collection of all booking (bookingscollection), regardless of date, time, resource booked etc. This collection is usabale in many parts of my UI, as I list upcoming bookingss etc.

I need to avoid writes being made to this collection, where there is an overlap.

I am considering adding an additional collection, where each document descibes the bookings for a specific resource on a specific day (lockcollection). It could be a doc, with the resource id, the date it covers and an array of start,stop times of booking already made.

Then when considering adding a new booking to my bookingscollection, I would make a transaction to the relevant document in the lockcollection, see if there is an overlap in which case I would fail, and if not, I would add the new intervall to the lock document within the transaction.

Once this succeed, I know that I can just plainly add the booking to the booking collection, as the lock is already there....

Similar logic would be applied to the procedure of deleting or changing bookings.

This idea is new to me, but I wanted to sahre, so I can hear your inputs....?

Raketten1963
  • 1
  • 1
  • 1