Long polling

Hi,

I am having some problems with long polling working on one of my projects.

i created this long polling function (it is a mix of jquery and js im going to change this)
//LONG POLLING
function messages_longpolling( timestamp, last_id, id){
   var t;
 
   if( typeof last_id == 'undefined' ){
      last_id = 0;
   }
 
   $.ajax({
      url: 'ajax/messages_main.php?message_id=' + id + '&timestamp=' + timestamp + '&last_id=' + last_id, 
      type: 'POST',
      dataType: 'json',
      success: function( payload ){
         clearInterval( t );
         if( payload.status == 'results' || payload.status == 'no-results' ){
            t=setTimeout( function(){
               messages_longpolling( payload.timestamp, payload.last_id                         );
            }, 1000 );
            if( payload.status == 'results' ){
				//UPDATE CONTENT
  					document.getElementById('message_thread').innerHTML=payload.content;
					document.getElementById('show_msg_form').style.display='block';
					
					//MAKE SURE THERE IS A SUBJECT AND IT IS NOT EMPTY
					if(payload.subject){
						//CHANGE HEADER TO SUBJECT
						document.getElementById('users_name_heading').innerHTML='Group Message: ' + payload.subject;
						
					}else{
						//DEFAULT SHOW NAMES
						document.getElementById('users_name_heading').innerHTML=payload.heading;
					}
					
					//EDIT FORM VALUES
					document.getElementById('msg_id').value =payload.msg_id; 	
					document.getElementById('msg_indi').value =payload.msg_indi; 	
					document.getElementById('msg_sub').value =payload.msg_sub; 
							
					//ADJUST THE SIDE PANEL SETTINGS
					var badge =document.getElementById('msg_badge'+id).innerHTML;
					if( badge =='unread'){
						document.getElementById('msg_badge'+id).innerHTML =payload.badge; 
					}
					//GO TO BOTTOM
					var div =document.getElementById('chat-content');
					div.scrollTop= div.scrollHeight;
					
					//STOP PROPIGRATION
					//a.stopPropagation();
					//a.cancelBubble = true	
                  
            }
         } else if( payload.status == 'error' ){
			 //THERE WAS AN ERROR 
			 alert('Ooops! Something has gone wrong. Please try again!'); 
			 
         }
      },
      error: function(payload){
         clearInterval( t );
         t=setTimeout( function(){
            messages_longpolling( payload.timestamp, payload.last_id );
         }, 15000 );
      }
   });
}

Open in new window


i then use an inline on click event to trigger the function like so
<a href="#" class="active" id="msg3" onclick="messages_longpolling( 1406321552,'',3); return false">  

Open in new window


the ajax code fires once someone has clicked one of the chats (there a different chats)

The ajax request gets the information using the following code

function get_all_messages($sql, $array){
	//SET THE GLOBALS
	global $conn;
	
	//SETUP SOME STANDARD VARS
	$messages='';
	$heading='';
	$all_senders='';
	$count=0;
	$dir=$_SERVER['SERVER_NAME'].'/profile/images/profile_pics/'; //profile directory path
	$timestamp = (int) trim( $_GET['timestamp'] );
	$last_id = isset( $_GET['last_id'] ) && !empty( $_GET['last_id'] ) ? $_GET['last_id'] : 0;
	$time_wasted = 0;
	$last_id = '';	
	$data=array();
		
	//PREPARE SQL
	$prep=$conn->prepare($sql);
	$ex=$prep->execute($array);
	
	//CHECK IF THERE ARE ZERO ENTRIES
	$num = $prep->rowCount();
	if($num <=0){
		//CHANGE HEADING
		$heading='<li class="conversation-divider"><span>* No Messages * </span></li>';
		
		//PERFORM SOME CHECKS
		while($num <=0){
			if($num <=0){
				if($time_wasted>=60){
					//CREATE JSON ARRAY
					$data=array(
						"status"=>"no results", 
						"timestamp"=>time(),
						"last_id"=>0, 
					);
				}
				
				//SLOW DOWN PROCESS TO LIMIT SYSTEM RESOURCES
				sleep(1);
				
				//CHECK MESSAGES AGAIN
				$ex=$prep->execute($array);
				$num = $prep->rowCount();
				$time_wasted++;
			}
		}
	
	//EXECUTE REMAINING FUNCTIONS IF TEST PASSES
	}else{
		
		//THERE ARE NEW MESSAGES
		if($num>=1){
			//GET NEW MESSAGES
			
			//SETUP THE SQL FOR GETTING PEOPLE INFORMATION
			$ppl='SELECT user_nickname, avatar FROM bb_users WHERE username=(:user) LIMIT 1';
			$ppl_prep=$conn->prepare($ppl);
	
			while($fetch= $prep->fetch(PDO::FETCH_ASSOC)){
				//SETUP VARS
				$id=isset($fetch['id'])?$fetch['id']:'';	
				$original_id=isset($fetch['original_id'])?$fetch['original_id']:'';	
				$composed_date=isset($fetch['composed_date'])?date("F j Y, g:i a",strtotime($fetch['composed_date'])):'';
				$sender=isset($fetch['sender'])?$fetch['sender']:'';
				$recipient=isset($fetch['recipient'])?$fetch['recipient']:'';
				$subject=isset($fetch['subject'])?$fetch['subject']:'';
				$message=isset($fetch['message'])?$fetch['message']:'';
				$heading=' <li class="conversation-divider"><span>Conversation started at '.$composed_date.'</span></li>';
				$individuals=isset($fetch['individuals'])?$fetch['individuals']:'';
				$avatar=$_SESSION['avatar'];
				$nickname=$_SESSION['user_nickname'];
				$sent_class='sent';
						
				//TEST TO SEE IF SENDER AND RECIPIENT ARE EQUAL
				if(($sender !== $recipient)){
					//THE USER VIEWING IS NOT THE SENDER
					$ppl_array=array(":user"=> $sender);
					$ppl_ex=$ppl_prep->execute($ppl_array);
					
					//GET THE DATA
					if($person = $ppl_prep->fetch(PDO::FETCH_ASSOC)){
						$avatar=$person['avatar'];
						$nickname=$person['user_nickname'];
						$sent_class='receive';
						
						//GET ALL RECIPIENTS
						$all_senders[]=$nickname;
					}
				}	
				
				//CREATE THE START OF THE MESSAGE
				if($count==0){
					//ADD HEADER TO START OF MESSAGE THREAD
					$messages.=$heading;
					
				}elseif($count % 20 ==0){
					//ADD THE DATE OF THE TENTH POST
					$sub_date=date("F Y", strtotime($composed_date));
					$messages.='<li class="conversation-divider"><span>'.$sub_date.'</span></li>';
				}
				
				//DISPLAY TO CONTENT
				$messages.='
					<li class="message '.$sent_class.'">
					  <div class="media">
						<div class="pull-left user-avatar">
						  <img class="media-object img-circle" src="//'.$dir.$avatar.'">
						</div>
						<div class="media-body">
						  <p class="media-heading"><a href="#">'.ucwords($nickname).'</a> <span class="time">'.$composed_date.'</span></p>
						  '.$message.'
						</div>
					  </div>
					</li>
							
				';
						
				//INCREASE COUNT
				$count++;	
				
			}
			
			//CONVERT ALL_SENDERS INTO A STRING
			if(is_array($all_senders)){
				//REMOVE DUPLICATES
				$all_senders=array_unique($all_senders);
					
				//CONVERT TO STING
				$all_senders= implode(", ",$all_senders);
			
			}
			
			//SETUP ARRAY
			$data=array(
				'status'=> 'results',
				'timestamp'=>time(),
				'last_id'=>$id,
				'heading'=> ucwords($all_senders),
				'subject' => $subject,
				'content'=> $messages,
				'badge'=>'',
				'msg_id'=> $original_id,
				'msg_indi'=> $individuals,
				'msg_sub'=> $subject,
			);
			
		}

	}
	
	//JSON ENCODE
	$data=json_encode($data);
	
	//DISPLAY DATA
	die( $data);
}

Open in new window


declared in messages_main.php
       $sql='SELECT * FROM messages WHERE original_id=(:msg_id) AND recipient=(:user) AND composed_date>=(:time) ORDER BY id ASC LIMIT 100';
	$array=array(":msg_id"=>$ID, ":user"=>$_SESSION['username'], ":time"=>time());
	get_all_messages($sql, $array);

Open in new window



since using the code my project takes considerably longer to load. and im not getting a "real" time response

When i let my page site and wait and pull up google console i get the following errrors

http://www.bushbrigade.com/bushbase/system/ajax/messages_main.php?message_id=undefined×tamp=undefined&last_id=0 
where have i gone wrong and what can i do to make this work?

if you would like to see a working example it can be found here

http://www.bushbrigade.com/bushbase/system/messages.php

user: expert-exchange
pass: 3XP3rt!!!!

thanks

Jayme
LVL 6
J NUnicorn wranglerAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

GaryCommented:
Login not working and is this link where the problem is?
0
J NUnicorn wranglerAuthor Commented:
Hi,

looks like someone change the password i have changed it back and it works now



Yes the link is the page i would i am using.
0
GaryCommented:
Here you are not passing the msg.id - should you be?

            t=setTimeout( function(){
               messages_longpolling( payload.timestamp, payload.last_id                         );
            }, 1000 );

Open in new window

0
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

J NUnicorn wranglerAuthor Commented:
Yea I noticed that too

I adjusted that to include payload.msg_I'd

Still really slow and no response
 And get the undefined for message_id
0
GaryCommented:
In the error function of your ajax call you are rerunning the ajax call but you have invalid values which ends up in a continual loop with errors.

      error: function(payload){
         clearInterval( t );
         t=setTimeout( function(){
            messages_longpolling( payload.timestamp, payload.last_id, payload.msg_id );
         }, 15000 );

Open in new window

0
J NUnicorn wranglerAuthor Commented:
So what should I adjust it too mine looks just like the one u just posted. I still have funny stuff happening
0
GaryCommented:
That is your code, I was pointing out where the problem is.
As to what to do - I'm not sure as I haven't figured out your logic flow yet but I would guess you have some default values there that it can fall back to if there is an error
0
Ray PaseurCommented:
No points for this please.  I don't want to rain on anyone's parade, but PHP is really built for HTTP client/server work in a RESTful environment.  The requests are atomic, complete and stateless and the responses are complete and usually instantaneous.  If you're using Apache It may be the wrong tool for a long-polling application, since the Apache threads can be eaten up pretty quickly.  

These seem to be built for long-polling:
http://www.tornadoweb.org/en/stable/
http://cometdproject.dojotoolkit.org/

I don't know what a good PHP answer might be.
0
GaryCommented:
Ray is right - Apache is not built for this.
You may want to look at nGinx or node.js for handling your long polling - both are single threaded and can easily handle thousands of concurrent connections without belching.
If you know js then using node.js will be relatively easy
nGinx requires a bit more hands on work

I personally use nGinx and after the initial 'How the hell do you do...' its pretty easy to get on with.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
J NUnicorn wranglerAuthor Commented:
Hi,

i have considered using node.js however i would need to switch my server and im not interested in doing this right now.

the app im building is small so i would like to keep php

ive updated my js however im not getting my desired results

//LONG POLLING
function messages_longpolling( timestamp, last_id, msg_id){
   var t;
 
   if( typeof last_id == 'undefined' ){
      last_id = 0;
   }
 
   $.ajax({
      url: 'ajax/messages_main.php?message_id=' + msg_id + '&timestamp=' + timestamp + '&last_id=' + last_id, 
      type: 'GET',
      dataType: 'json',
      success: function( payload ){
         clearInterval( t );
         if( payload.status == 'results' || payload.status == 'no-results' ){
            t=setTimeout( function(){
               messages_longpolling( payload.timestamp, payload.last_id , payload.msg_id);
            }, 1000 );
            if( payload.status == 'results' ){
		 //UPDATE CONTENT
  					
                  
            }
      },
      error: function(payload){
         clearInterval( t );
		 alert('error');
         t=setTimeout( function(){
            messages_longpolling( payload.timestamp, payload.last_id, payload.msg_id );
		  
         }, 15000 );
      }
   });
}

Open in new window


i didnt make the code i got it from a website and then adapted it to my stuff. im not really sure how i can change it to get the desired output. the one big item is that my app has multiple chats and not one large one.

the website i used is http://webcooker.net/ajax-polling-requests-php-jquery/
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Languages and Standards

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.