I'm building a chat web application and using interval polling. However, sometimes the messages sent by client A is not received by client B. This happens like once in 20 messages sent or so. A page refresh on client B would of course, cause the message to be loaded.
This is how it works :
I'm using sessions to store the time client A last polled the server. When I do the next poll, the server checks the database for messages with time(precise up to microseconds) greater than the last Polled time. After doing stuffs with the latest messages, the server will save the current time in a session data to be used as last polled time on the next, coming poll.
I understand that sessions save data privately so other users can't access it. So two clients are always polling the same server at different time.
What went wrong? Should I use cache as an alternative so that both clients poll the same server at the same time? P.s., I'm using Apache server and MySQL database.
Here's the polling code in laravel :
public function index(){
$currentPoll = round(microtime(true) * 1000);//calculate the current time in microseconds
//if the session variable doesn't exist, set the lastPoll variable to 0
if(!($lastPoll = Session::get('lastPoll'))){
$lastPoll = 0;
}
$selectedMsgExists = Input::get('selectedMsgExists');//check whether messages exist in currently opened conversation
//check if conversation is opened or not
if(Input::has('selectedID')){
$selectedID = Input::get('selectedID');
}
else{
$selectedID = false;
}
$loginuser = User::find(Auth::user()->id);//get the currently logged in user
if($selectedMsgExists=='false'&&$selectedID){
//if messages has not been loaded but conversation exists, we take the first ten messages of the opened conversation.
$allMessages = $loginuser->messages()->select('users.name')->join('users',function($join){
$join->on('users.id','=','messages.user_id');
})->where('conv_id','LIKE',$selectedID)->orderBy('microseconds','desc')->take(10);
Session::put('lastPoll',$currentPoll);//save the session
return array(false,$allMessages->get()->reverse());//return the latest messages. False is to indicate that the data returned is NOT a conversation
}
}
Use ID, not time!
I'll give credit to judereid in his comments above.
Another thing to consider... I would be most suspicious of querying by a timestamp
here. If for some reason there's even as much as a 1 microsecond overlap you could
miss a message. Perhaps instead of logging the time you could log the last
retrieved ID (assuming you have incrementing ids on the messages) and then poll
for messages with ID greater than that – judereid
After some adjustments, there don't seem to be any messages amiss. I guess the problem was really with using time to obtain the latest messages.