I am building a simple auction solution on Laravel. The below code is some extract test code that is suppose to act as the auctioneer.
The problem is that when it's running it locks up access to the Auctionbid Postgres table and users can't bid while it's running. My testing is on localhost running a few users in auction as well as the auctioneer process all on same box/same IP<--might be making issue worse (not sure).
I've read all about the issues on SO about sleep(), downsides of polling and PHP sessions and have dug into Websockets a bit to see if I should go there. It also would also allow me to replace Pusher.
However, the issue I see is that an auction is all about timing and what events are NOT happening (if no bid in 3 seconds tell users "Fair Warning") and the Websocket implementations I've read about seem to be about what events ARE happening.
Questions:
- Would a websockets implementation possibly be a solution? Every article I've looked at seems to be about the events that ARE happening. Maybe the classes on negative space are hindering my ability to see the solution :-)
- Is having this all run on the same box/IP the issue? And/Or is sleep() just a bad way moving forward - as pointed out in at least 100 SO posts...
- What are other possible solutions that allow me to check for what events are NOT happening?
public function RunTheAuction($auction_item_id, $auction_id)
{
set_time_limit(300);
$options = array(
'cluster' => env('PUSHER_APP_CLUSTER'),
'encrypted' => true
);
$pusher = new Pusher(
env('PUSHER_APP_KEY'),
env('PUSHER_APP_SECRET'),
env('PUSHER_APP_ID'),
$options
);
$bidIncrementResetCounter = 0;
$lastBidderId = 0;
$currentWinnerBidAmount = 0;
$lastBidderBidAmount = 0;
$count = 0;
while(true){
$auctionbid = Auctionbid::select('id', 'bid', 'bid_timestamp', 'auction_bidder_id')
->where('auction_item_id', '=', $auction_item_id)
->where('auction_id', '=', $auction_id)
->orderBy('bid', 'desc')
->orderBy('bid_timestamp', 'asc')
->first();
if ($auctionbid) { //there is a bid on the item
$currentWinnerId = $auctionbid->id;
$currentWinnerBidAmount = $auctionbid->bid;
if (($lastBidderId == $currentWinnerId) && ($lastBidderBidAmount == $currentWinnerBidAmount)) { //it's the same bidder
if ($bidIncrementResetCounter == 1) {
$message = "Fair Warning!";
$pusher->trigger('bids_channel', 'bid-warning', $message);
}
if ($bidIncrementResetCounter == 2) {
$message = "Going once... Going twice...";
$pusher->trigger('bids_channel', 'bid-warning', $message);
}
if ($bidIncrementResetCounter == 3) {
$message = "We have a winner!";
$pusher->trigger('bids_channel', 'bid-warning', $message);
break;
}
$bidIncrementResetCounter++;
} else {
$bidIncrementResetCounter = 0;
}
}
else{
$currentWinnerId = 0;
}
$lastBidderId = $currentWinnerId;
$lastBidderBidAmount = $currentWinnerBidAmount;
sleep(10); //<-----------------------------ISSUE
$count++;
if($count == 12){break;}
} //end loop
} //end function RunTheAuction