I have an automatic synchronization that send a CURL Request to an equipment and I do this request for every equipment that I have (like 60). The problem is:
- If the communication succeed everything works fine.
- But if the communication failed the web page will wait until the timeout is gone. So the client side crashes for 3-4 minutes... I have important grids that stop loading the data in that 3-4 minutes.
The automatic synchronization is a function in javascript that do an AJAX Request to call php controller below. How can I prevent this? I don't know what else to try... The AJAX is async , so I don't get it why the webpage stops.
Controller:
$list = $panels_repository->getNetwork();
$thread = new PollingThread($list);
$thread->start();
$thread->join();
$result = $thread->result;
$resultLength = sizeof($result);
//...
Thread:
class PollingThread extends Thread {
private $panels_list;
private $alarm_status;
public $result;
public function __construct($list) {
$this->panels_list = $list;
}
public function run() {
$panels_list = $this->panels_list;
$alarmsUpdated = array();
$panels = array();
foreach($panels_list as $panel) {
$alarms_list = $panel->getAlarmsList();
//Get updated alarms status
$panel->getDiagnosticStatus($alarms_list);
//Save the results
array_push($alarmsUpdated, $alarms_list);
}
$this->result = $alarmsUpdated;
}
getDiagnosticStatus
$input = "<?xml version='1.0' encoding='ISO-8859-1'?>
<?getParameters message?>
<displayMLRequest xmlns='http://www.peek.se/DisplayML/' version='1.12'
dateTime='2008-01-10T15:09:51+02:00'>
<getParameters/>
</displayMLRequest>";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url); //Set IP to communicate
//Set POST XML Input
curl_setopt( $ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch, CURLOPT_POSTFIELDS, $input);
//Return response as string & TimeOuts
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
//Execute
$output = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
Javascript:
$('#stations_tree').on('changed.jstree', function (e, data) {
//....
var dataObject = {
type: "Selected",
childrenID: childrenID_array,
parentsID: parentsID_array
};
$.ajax({
type: "POST",
url: "controllers/PanelsController/",
data: dataObject,
cache: false,
success: function ()
{
$("#dg_selected_stops").jsGrid("loadData");
$("#dg_selected_pids").jsGrid("loadData");
}
});
}).jstree({
plugins: ["checkbox", "state", "types"],
"types": {
"default": {
"icon" : false
}
},
core: {
data: {
url: "json/stations.json",
dataType: "json",
success: function () {
//Save Panels Network as session variable
var dataObject = {
type: "Network"
};
$.ajax({
type: "POST",
url: "controllers/PanelsController/",
data: dataObject,
cache: false,
success: function() {
//Get EquipmentStatus for each panel
var dataType = {
type: "Save"
};
$.ajax({
type: "POST",
url: "controllers/EquipmentStatusController/",
data: dataType,
cache: false,
success: function () {
//Status Unknown
changeTreeIcons();
loadAlarmsData();
polling();
}
});
}
});
}
}
}
});
Function polling() - Where the JS stops until timeout is gone
function polling() {
var dataObject = {
type: "Polling",
};
$.ajax({
type: 'POST',
url: "controllers/DatabaseController/",
data: dataObject,
success: function(response) {
//loadAlarmsData();
//changeTreeIcons();
}
});
}
EDIT: I have checked that if I try to do an AJAX Request after the polling as began, the webpage only do that request after php script is done. So the JS that blocks are tables that loadData with ajax requests. How can I resolve this?
It is not complete solution for copy/paste, but it can give you idea how to solve your problem. You can try next (php-fpm only).
On frontend side run synchronization using js and call your controller, on client side in controller send response for browser and call fastcgi_finish_request() before your CURL operation will start. This function flushes all response data to the client and finishes the request, but PHP script continue job.
...
$list = $panels_repository->getNetwork();
$key = 'my_unique_operation_key'; // it key need you for get data on client side
$resp = [
'status'=>'start',
'operation_key' => $key
];
echo json_encode($resp);
fastcgi_finish_request(); // close connection and continue ...
$thread = new PollingThread($list, $key); // send $key also
...
In PollingThread:
...
foreach($panels_list as $panel) {
$alarms_list = $panel->getAlarmsList();
//Get updated alarms status
$panel->getDiagnosticStatus($alarms_list);
//Save the results
array_push($alarmsUpdated, $alarms_list);
...
// save operation progress for example in memcache
$progressData = some data about progress and $alarmsUpdated, etc...
$memcache_obj->set('operation_'.$key, json_encode($progressData));
}
Somewhere In Controller add action which returns data parts:
function getDataPartially_action(){
$key = $_GET['key']; // not forget validate
...
$jsonData = $memcache_obj->get('operation_'.$key); // get current state from memcache by key
echo $jsonData;
exit();
}
On frontend side:
// call controller and start operation
$.ajax({
url: '/controller/uri/here',
beforeSend: function() {
// here you can place spinner or progress bar ...
},
success: function(json) {
// in json you get progress key after fastcgi_finish_request()
// and run visual progress
getDataPartially(key);
}
});
// load data partially
function getDataPartially(key){
var timerId = setInterval(function() {
$.ajax({
url: '/controller/uri/here/getDataPartially_action?key=' + key,
success: function(json) {
// in json you have data for grids and progress info
// if json contains finish info stop progress
clearInterval(timerId);
// hide progress bar and etc ...
}
});}, 2000);
}
p.s. In CURL function you can use CURLOPT_PROGRESSFUNCTION and get more info about progress:
$ch = curl_init();
curl_setopt ...
curl_setopt($curl, CURLOPT_PROGRESSFUNCTION, 'curl_progress_callback');
...
// where curl_progress_callback is:
function curl_progress_callback($dltotal, $dlnow, $ultotal, $ulnow){
$curlInfo = curl_getinfo($ch); // a lot info about connection
echo $curlInfo['connect_time'];
echo $curlInfo['http_code'] ...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With