Meteor.SetTimout run on server, notify client / possibility to abort

Hello Guys,

I’m coding a reservation system in which a timeslot is automatically unavailable for everyone else when somebody picks it. Now due to the possibility that the user could pick a slot and then close the browser / tab, those timeslots should be made available again. I have thought about different solutions for this:

  1. Run a task that deletes unfinished reservations older than x seconds
  2. Start a timer server side, that notifies the client with the possibility to continue, which after another x seconds automatically deletes the reservation if there’s no interaction of the user (I’m doing this now with a client side setTimeout, however this only works if the client is running the site (on some Browsers like Chrome Mobile, also if the Browser is not active, on Safari Mobile it will continue once the Browser is opened again, it doesn’t work on either if the tab is closed, obvioulsy) I also have a beforeunloadtask that removes the reservation, however this doesn’t work with closing tabs / browser.

Conclusion: While 1. would be no problem to achieve, I think it be a better solution to use 2. however the setTimout/ setIntervalwould need to run server side, then notify the client, and if no interaction is made, another timeout should remove the booking (or the User himself would remove it). I’m a bit clueless how to achieve this, so I hoped someone of you guys might have a hint for me? Or is the entire idea of the second solution backwards?

Thanks in advance already.

I’d consider using MongoDB’s TTL (expireAfterSeconds) capability.

Basically, your reservations collection has documents which expire after n seconds. If the client completes the transaction within the configured time, a document is created in the bookings collection and the reservation document is removed.

1 Like

Thanks for your Input! Seems like a solid approach. However I’d need still to give the user the possibility to continue and at this point of state of the application, it would be quiet a start-over. Now I have dynamic timeslots as a collection and bookings as a collection that relate to them, those bookings feature states which changes from “reserved” to “booked” when the user finishes the booking. In a method I ensure that only “reserved” bookings can removed, respectively they can be removed by an admin. Would you still recommend to change to your approach?

It sounds like you’ve made more of a commitment to the architecture than I inferred!

My general rule-of-thumb is to let the database engine do what the database engine is optimised for. However, the decision to stick or twist can only be yours! :slight_smile:

I like that rule-of-thumb, however I can only think of complicated solutions to warn the user first and give him a choice with this. Or maybe I just can’t imagine the easy solution?

So I finally solved it as follows:
Server: I have a server-side function that sets the booking to the status “temporary” after creating it, followed by a timeout of 15min which then changes the status to “expiring”, and starting another timeout of 15sec before removing the booking and freeing up the timeslot.

Client: an observeChanges on client-side opens a modal when the booking changes to status “expiring”, leaving the user the possibility within 15seconds (I might increase this) to tell the app that he wishes to continue, which recalls the server-side function and therefore sets the status again to “temporary” and after 15min again to “expiring” and so on… Meanwhile the first called server-side function stopped since there was no booking with the given ID and the status “expiring”. Without interaction the server side function will remove the booking and free the timeslot. Should work, testing now.

Let me know if you think there’s an easier way.
Thanks again for your input.