Long polling JQUERY chat using sleep() - php

The following code makes the web loading for like 10 minutes and I dont know why!
function chatheartbeat(){
include("config.php");
$useradn = $_SESSION['displayname'];
$query = "select * from chat where (userbdn = '".$useradn."' AND isread = 1) order by id ASC";
$result = mysql_query($query , $link);
$num_rows = mysql_num_rows($result);
if ($num_rows >= 1) {
$items = array();
$i='1';
while($chat = mysql_fetch_array($result)){
$items[$i]['from']=$chat['useradn'];
$items[$i]['msg']=$chat['msg'];
$items[$i]['timee']=date("H:i" ,$chat['timee']);
$i++;
}
$query = "update chat set isread = 0 where userbdn = '".$useradn."' and isread = 1";
mysql_query($query , $link);
header('Content-type: application/json');
echo json_encode($items);
exit;
}else{
sleep(2);
chatheartbeat();
}
}
Any suggestions?

The function will never return until there are some results from the first select.
I would suggest that you return after n runs through (e.g. 5), even if there are no results. The client can then re-issue the ajax call to poll again.
Also, it's not a great idea to do this in a recursive manner. I would suggest doing this in a for loop instead.

You are calling your function recursively and as the session variable does not change between the function calls, if it goes to the else part the first time, it will go there every time, creating a never ending loop.
By the way, if you want to use polling, you should set a timer in the client part (javascript) and not use a recursive function on the server side.

There are a few things you want to look at when performing any long polling techniques.
You need to exit after some predefined time period. Waiting on the server until you have something to respond with will lead you to execution timeouts.
Know what is going on with your SESSION data. PHP by default will use file based sessions and locks the file during the course of the request (unless you intervine)

Related

PHP While Loop with MySQL Has Inconsistent Execution Time, How Can I Fix This?

My problem is simple. On my website I'm loading several results from MySQL tables inside a while loop in PHP and for some reason the execution time varies from reasonably short (0.13s) or to confusingly long (11s) and I have no idea why. Here is a short version of the code:
<?php
$sql =
"SELECT * FROM test_users, image_uploads
WHERE test_users.APPROVAL = 'granted'
AND test_users.NAME = image_uploads.OWNER
".$checkmember."
".$checkselected."
ORDER BY " . $sortingstring . " LIMIT 0, 27
";
$result = mysqli_query($mysqli, $sql);
$data = "";
$c = 0;
$start = microtime(true);
while($value = mysqli_fetch_array($result)) {
$files_key = $value["KEY"];
$file_hidden = "no";
$inner_query = "SELECT * FROM my_table WHERE KEY = '".$files_key."' AND HIDDEN = '".$file_hidden."'";
$inner_result = mysqli_query($mysqli, $inner_query);
while ($row = mysqli_fetch_array($inner_result)) {
// getting all variables with row[n]
}
$sql = "SELECT * FROM some_other_table WHERE THM=? AND MEMBER=?";
$fstmt = $mysqli->prepare($sql);
$fstmt->bind_param("ss", $value['THM'], 'username');
$fstmt->execute();
$fstmt->store_result();
if($fstmt->num_rows > 0) {
$part0 = 'some elaborate string';
} else {
$part0 = 'some different string';
}
$fstmt->close();
// generate a document using the gathered data
include "../data.php"; // produces $partsMerged
// save to data string
$data .= $partsMerged;
$c++;
}
$time_elapsed_secs = substr(microtime(true) - $start, 0, 5);
// takes sometimes only 0.13 seconds
// and other times up to 11 seconds and more
?>
I was wondering where the problem could be.
Does it have to do with my db connection or is my code flawed? I haven't had this problem at the beginning when I first implemented it but since a few months it's behaving strangely. Sometimes it loads very fast other times as I said it takes 11 seconds or even more.
How can I fix this?
There's a few ways to debug this.
Firstly, any dynamic variables that form part of your query (e.g. $checkmember) - we have no way of knowing here whether these are the same or different each time you're executing the query. If they're different then each time you are executing a different query! So it goes without saying it may take longer depending on what query is being run.
Regardless of the answer, try running the SQL through the MySQL command line and see how long that query takes.
If it's similar (i.e. not an 11 second range) then the answer is it's nothing to do with the actual query itself.
You need to say whether the environment you're running this in is a web server, e.g. accessing the PHP script via a browser, or executing the script via a command line.
There isn't enough information to answer your question. But you need to at least establish some of these things first.
The rule of thumb is that if your raw SQL executes on a MySQL command line in a similar amount of time on subsequent attempts, the problem area is elsewhere (e.g. connection to a web server via a browser). This can be monitored in the Network tab of your browser.

PHP/MySQL - Run actions from background / Dealing with a longer-running method

I have a form in PHP that saves some data into a database. However, after a successful insert, the PHP function below executes to arrange every entry by a "visible" ID column (called correlativo in this case).
function ordenar_ids()
{
$sql = "SELECT DISTINCT(DATE_FORMAT(fecha, '%Y')) FROM emergencias ORDER BY fecha";
$results = mysql_query($sql);
$anios = [];
while ($row = mysql_fetch_array($results))
array_push($anios, $row[0]);
foreach($anios as $anio)
{
$sql = "SELECT id_emergencia FROM emergencias WHERE fecha LIKE '".$anio."%' ORDER BY fecha ASC;";
$results = mysql_query($sql);
$correlativo = 1;
while ($row = mysql_fetch_array($results))
{
$sql = "UPDATE emergencias SET correlativo = $correlativo WHERE id_emergencia = '".$row[0]."';";
mysql_query($sql);
$correlativo++;
}
}
return 1;
}
Initial (local) tests were successful, however when we tested this in a production environment we noticed this process is taking way too long (about 15 seconds on average) which is detrimental to the user experience.
Is it possible to run this function in the background after the user has submitted the form? If it's not possible, how can we work around this problem?
Additional Data:
The user doesn't need a return value of this function, nor it's needed for the following actions that happens after.
You can't easily run a mysql query in the background. But xou could start a new php script in background: http://php.net/manual/de/function.exec.php#86329
But better would be to improve the script performance itself. I think, you can improve it by using one "update ... select" query, avoiding LIKE % or using mysql triggers.

How to show a link counter change live?

What this code does is taking links from the db and compare it to a keyword, if it compares then KeywordCounter++, and in every time LinkCounter++
I want to type LinkCounter after every link it goes through but in the code I wrote it only shows me after the loop ends (after all the links crosses). How can I see the LinkCounter every time a link is checked?
How will I be able to see live the counter jumps?
<?php //holdes the db connection include('Connect.php');
$KeyWord = 'googoo';
$LinkCounter = "0";
$KeywordCounter = "0";
$query = mysql_query("SELECT * FROM doalgo where Pass != '0'") or die(mysql_error());
while ($info = mysql_fetch_array($query)) {
$id = $info['id'];
$link = $info['link'];
$num_rows = mysql_num_rows($query);
mysql_query("UPDATE doalgo SET Pass = '1' WHERE id = '$id'");
$CurrentFile = file_get_contents($link);
if (!strpos($CurrentFile, $KeyWord)) {
//nothing
} else {
mysql_query("UPDATE doalgo SET Posted = '1' WHERE id = '$id'");
$KeywordCounter++;
}
$LinkCounter++;
if ($id == $num_rows) {
die();
}
}
echo "<br />KeywordCounter: ".$KeywordCounter;
echo "<br />LinkCounter: ".$LinkCounter;
? >
Its better you calculate the average speed of update (for example number of updates per hour) and send just a single integer to the browser every 1 hour.
using jquery you can change the value shown to user with that speed.
If I understand your question correctly, you want the web page to display immediately, then constantly update the LinkCounter display as the SQL queries progress?
If this is a correct understanding, to do this requires AJAX. Your server has to send constant updates to the web browser every time $LinkCounter is updated, then the JavaScript running in the browser will update the display with that information. Obviously, it's a much more complicated thing to do than what your script currently does. It's an entirely different design pattern.
If this is truly something you want to learn to do, there are many books on the subject of AJAX, or google can help you, too.

mysql_fetch_array() timing out

I am trying to query a database, but it seems to just load for an age and not do anything. It's a simple query and shouldnt take longer than a millisecond.
while($row = mysql_fetch_array(getWallPosts($userid)))
{
}
Now when I replace this code with:
echo mysql_num_rows(getWallPosts($userid));
It just displays '1' in fact there's only one record in the DB and it's just a simple SELECT statement.
Here's the getWallPosts function:
function getWallPosts($userid, $limit = "10")
{
$result = dbquery("SELECT * FROM commentpost
WHERE userID = ".$userid."
ORDER BY commentPostID DESC LIMIT 0, ".$limit);
return $result;
}
Also, when I put the SQL string that it's executing into MySQL's query browser. It takes no time at all.
Any ideas?
You appear to be looping indefinitely because you're retrieving a new set (one record) of data each time.
$result = getWallPosts($userid);
while ($row = mysql_fetch_array($result)) {
//printf($row[0]);
}
You need to get the data once and loop through it. Your code is getting the data, running the loop and then getting the data again.
Try:
$posts = getWallPosts($userid);
while($row = mysql_fetch_array($posts))
{
//Code to execute
}
Its an infinite loop. The expression in the while always executes so it will always be true.
You're returning a new result set each time the while statement executes. You should call getWallPosts first, assign it to $results, and then loop over it.

PHP question regarding a while statement for a loop

I asked someone to code up a loop for me, although I asked for the loop to run constantly as it should be doing checks. Say I wanted it to run for 2 hours in a loop.
They created this;
$result = select_query ('tbltest', 'id,userid,test');
while ($data = mysql_fetch_array ($result))
{
$userid = $data['userid'];
$id = $data['id'];
$test = $data['test'];
}
I don't know much about PHP, but it seems to me that once there are no more rows to go through and place in an array, it will end the loop.
How can I go about fetching the rows, but continuing in a loop for the next 2 hours?
Thanks!
I have no idea why you want to continue looping for 2 hours and doing nothing, but here's a solution (albeit a stupid one, if it serves your purpose):
set_time_limit(0);
$time = time();
while (time()<$time+7200)
{
if ($data = mysql_fetch_array ($result))
{
$userid = $data['userid'];
$id = $data['id'];
$test = $data['test'];
}
sleep(1); // so PHP doesn't consume too much resources
}
If you want to check something for a set amount of time, you should setup a cronjob to run a PHP script every X minutes rather than have a PHP script looping continuously.
you can't. when you do the select_query it actually returns a pointer of the full resultset as of that moment. the $data = mysql_fetch_array ($result) can only iterate over that values that were present in the resultset at the time of the initial select_query ('tbltest', 'id,userid,test');
call.. not to mention that I can't think of any properly configured PHP server that's going to let you leave a script running for 2 hours without timing out. perhaps what you want is a front-page with a AJAX script that re-checks the database for you in a loop. so that you would have your $.GET, and on the successfull return of your data you'd fire off another $.GET...
Can't you put the original database query inside stillstanding's loop?
set_time_limit(0);
$time = time();
while (time()<$time+7200)
{
$result = select_query ('tbltest', 'id,userid,test');
if ($data = mysql_fetch_array ($result))
{
$userid = $data['userid'];
$id = $data['id'];
$test = $data['test'];
}
sleep(1); // so PHP doesn't consume too much resources
}

Categories