I am writing a hotel booking software using PHP and MySQL. I am pretty much done with it but I ran into a race condition problem. For example there is only one standard room left and when 2 guests both select it it shows available to both of them. I tried fixing it by checking the room again when the guest clicks confirm before payment but that still has issues. I also tried making the room status to pending when whoever clicks the confirm first but I can't figure out how to change it back to available if the guest decides not to pay or just closes the browser. I searched SO for answers but I didn't really find a definitive answer. Thanks in advance
One solution is to add two columns to a table in the database. One column is the session ID or user ID or whatever of the user that is being offered the room. The second column is a timestamp indicating when that offer will expire.
Then, in your app, only show rooms that have an expired timestamp in the hold column. (Set the initial timestamp to 0 so that it starts out expired.) When a room is selected, check the column again. If there's an unexpired timestamp there, the user gets a "sorry, you were too slow" message. Otherwise, put a timestamp there for 15 minutes into the future or whatever, and proceed.
You see this on travel sites and ticket-purchasing sites a lot where it says something like "We're holding these seats for you for another 14 minutes. Please complete the transaction by then or it will be released blah blah blah."
I would also go with the pending state. You could save the state together with the session id of this user and have a cronjob that deletes all pending states that have expired session ids associated to them.
Related
I'll try and cover most of the important details here...
I'm currently working on a booking system for a transport provider. I am using Laravel and originally started by having the Booking model attached to a User.
The client now however wants them to not have to login or register until the last step of the booking process. I have done carts etc in Session / Local Storage before but I thought before I start I would get some input from the friendly folks over at StackOverflow!
The most ideal way for me at this point would be to make the user_id on the Booking model nullable, but then when the visitor returns to the site how will I then know which booking is theirs?
I hope this makes sense & I hope someone out there has dealt with a similar problem to this one and can shed some light on the best strategy going forward!
I created something similar to what you say in a company that has been working for some time, I indicate how I proposed it, to see if it can help you achieve what you want to achieve in the most optimal way.
As you indicated, I created the reservations with the nullable user_id, as it usually happens in almost all reserve applications, they are not eternal, so I added a field (max_datetime) of maximum time that reservation would last and a field (token) with code only for the reservation, in addition to a field (ip) for the ip of the session. (In the application that I made, the reservation was maintained 12 hours maximum or until 11:59 pm on the same day, which may be less than 12 hours).
Then create a Task Scheduling for a custom Artisan Console. What it did was eliminate the reserves that fulfilled the condition to be eliminated.
When the reservation was completed it was associated with the user_id and the other fields with null (max_datetime, token, ip). Ah! Yes and a field (confirmed) to confirm with "true" that the reservation has been completed, by default to "false".
I used session to check the "ip" and the "token", and if not, I asked that if they had the token, to indicate it.
The system allowed you to obtain the "token" in case you did not want to continue at that moment, warning you of the time the reservation was kept.
I do not have access to the code since it was from a company and I only kept the idea. I hope it helps you. A cordial greeting.
First time posting.
I manage a website that handles certain types of transactions for virtual currency.
It is a php/mysql web application.
Recently we've had a user somehow withdraw the same amount (essentially duplicating their virtual money) 6 or 7 times (until we ran out of funds).
Looking at the log, the transactions were processed milliseconds apart, so I'm assuming that they user had for example 5,000 funds and requested to withdraw them by spamming the request in order to attempt to withdraw more than they owned.
How could I go about preventing this from happening in the future, and how could I test this, or repeat this process myself?
Thanks for any help.
I don't think this is a typical question on here, I'm sorry. I'm not a developer, my current developer is on leave, so he's refused to assist.
One way this could be managed would be to force a certain time interval to pass at a timestamp level (i.e the user cannot process multiple transactions within x minutes).
To do this, and assuming you'd be inserting into your table the transaction stats then apply it accordingly, you can force a check constraint on new insertions that will reject any row not respecting your timestamp condition
A SQL to withdraw funds should be:
UPDATE balance
FROM users
SET balance = balance - $amount
WHERE id = $id AND balance >= $amount
If there is 0 rows affected then there is insufficient balance.
Any solution that tests balance before hand is susceptible to race conditions.
Some idea to avoid to spam request :
FRONT SIDE :
Disable the button that allow user to click and spam the request.
When user click replace the button by some loading icon
BACK SIDE :
Create a temporary file when the transaction begin (or edit one file to add some information about the transaction) and when the transaction end delete the file (or the data). So before EACH transaction, you check if you have the file / data : if you have something -> no transaction because one is already running. Some documentation about this : http://php.net/manual/fr/function.file-put-contents.php
An other idea is to add some param in your database (or create some table like user_transaction) and when you start the transaction you create a user_transaction row (or change a param from 0 to 1 as you want) and when the transaction end you delete the row or change the param from 1 to0. So before EACH transaction you check if a row exist for this user or if the param is 1 : if yes -> no transaction because one is already running. Nothing complicated here, I have no information about your database so can't do more :)
Try to add one lock from FRONT + one lock from BACK and you should reduce the problem !
EDIT : add some tracking
To avoid user to spam request, you can add some tracking to avoid fraude :
You can add some counter and add +1 each time user click to know if he spam
You can create a table in database to know each time a user send a request to know which user click, when and how much currency for example
This way you know who fraude (who click a lot to spam request or who send to many request in few times) and you can send email or warning message for example, or if you can track the amount of currency he win by "cheating", ask him to give it back I don't know how your app works !
If the type of the balance is an integer or big integer, making it unsigned will prevent it going negative.
ALTER TABLE user MODIFY balance BIGINT UNSIGNED NOT NULL;
Ok so I store the User ID and a PHP Timestamp on a db. What I want to do is check whether the user has visited on a daily basis. Something very similar to SO's visited system. I know that I should have the user's visit record.
But what I can't imagine right now is how do I determine the days that the user has visited and not visited. Any ideas? I really can't piece it together some help would be appreciated. A simple point to the direction if its ok. thanks
Edit:
I want to know the days the user has visited. Literally if the user visited on Nov. 1, 2013. I want to identify that but it wouldn't be just one day it would be each day since the user registered.
Append your user table with the following columns:
visittime
visitcount
consecutive (boolean)
When a user visits, check if the visittime was more than a day ago, and update consecutive accordingly. Als increment visitcount if visited consecutively.
There are a couple of approaches to solve this problem.
The most common way is to create a new table in your database.
This table should contain an "access log" of yout users (on entry per user per day). This way you can check if the user has accessed the site or not on a particular day. With this information you can calculate (almost) any information regarding to access stuff.
The fields coud be:
user_id
visit_time
visit_count
consecutive (tiny int)
You could add those fields to your existing table as well, but I think an additional table is cleaner.
This should get you up and running I guess.
So I suppose your main problem is how to determine if visitor is new or not.
You can use a $_COOKIE for that (as google analytic do), incrementing it for each visitor (this will be your visitor-unique-id)
Then if the cookie and you is not present, this is a new visitor.
Then store every page loading you want in a db
We have a back end application to manage messages from our clients. We have 4 customer care executives and we want to prevent the situation where the same message can't be opened by two different members, so we would like to do following...
Suppose user1 opened message id 15 and after that user2 opens same message, so we would like to give a alert that 'This message is already opened by user1'. How do we do it?
Create a different table in your database.
When a user opens a message, update the table to show which message has been opened and by which user.
When another user tries to open it, crosscheck the table to see if there is a row for that message. You can then do the appropriate action such as open or warn the user.
You can delete the rows after a given timeout period to allow others to open.
Schema eg
User_id msg_id time_opened
Unfortunately, you can't use sessions since the sesssion is user specific. However, you can employ flatfiles.
To delete the rows, employ a method such as
$timeout_time_in_seconds = 30;
$time = time() - $timeout_time_in_seconds;
$Query= "delete from table where time_opened
Note that depending on the time field, which can be an int, datetime or timestring, additional date formating of the $time variable may be required. However, int will be most convenient due to ease in comparison and subtraction and no formatting.
I'm mobile so pardon any errors. Also that's why I didn't comment but had to edit. Js issues.
What happens is, when the first user clicks, a quick check and update of the database is made.
When the second user tries, the script will detect the first user has already opened by checking the database.
You can count on this to work if the traffic load is low and the number of users trying to access is not too great. And also counting on the fact that the read and insert queries occur in a short time which as you can Guess is faster then two users clicking at the same time. Unless you have another issue, this should work
Simpliest way would be to implement as pessimistic locking at the DB level
http://www.blackwasp.co.uk/PessimisticLocking.aspx
Whatever language you are using should let you check the DB to see if a row is locked or not and send a message on the screen.
You can additionally setup your application with long polling to notify users when the request resource has become available. http://en.wikipedia.org/wiki/Push_technology
I am making a doctor appointment slot booking mechanism,where in doctor appointment slots will be divided into 30 mins slot each...i have achieved all the working code.. 1 problem i am facing is that..this booking is made at 2 places i.e 2 receptions..so when 1 selects a slot(radio button) not yet confirmed and saved in DB.other reception must not be able to select .how do i do it.any help on this...how do i go abt it.
This is a case of accessing "shared data". You'll need thread to make sure that only one thread has access to the data at a time to ensure it's integrity. The following might provide some ideas
http://www.alternateinterior.com/2007/05/communicating-with-threads-in-php.html
I would use some AJAX/AJAJ functions to periodically refresh data about free slots, or I would do that much more simple - when saving the appointment, just check it, if the slot will be taken, your app redirects user back to form to choose another slot.
In essence,
I will just ask for the slot timings upfront and the remaining details later.
In case the slot is available, it sends a request to the server to lock it, so that the other client cannot use it.
In case, it is not available, it will receive a small notification that this slot is unavailable, click to see available slots.
I would go with AJAX (if this is a web app). This is a distributed systems problem which resembles Blue Army - White Army problem.
Add a "Locked By" field to the table.
When booking a slot, do something like:
UPDATE tablename
SET LockedBy = userid, ...
WHERE LockedBy IS NULL
After the update, you can select to see if LockedBy is set to your userid.
If not, then someone else must have beaten you to the punch, and you need to tell the user to pick a different slot.