I'm creating an app in PHP to create an API and in reactjs for the front-end.
The server-side is responsible for making calls to WHM/cPanel APIs by returning the processed result to the client-side.
Now I start the background process by using shell_exec (that is called once for “scan”) and for following requests (made by JS) I get the data from the database that I think is slower and more heavy for the server.
The background process can take up to a couple of minutes, and from the client-side I receive an update every second of the currently processed data.
The background process retrieves the list of cPanel accounts that will be stored in the database; and for each one, checks the email account(s) and stores some data in the database. This process could take more or less depending on the response time of the cPanel API, that is called once for the list of accounts, and for each account. Now the accounts are about 120.
There is another way to run a PHP process in background and access the variables of that process (without involving PHP server extensions)?
PHP
class Api
{
public function getInfo(int $id = null)
{
//check for running complete scans if id is not provided by user
$id = $id === null ? $this->db->select('scans', ['id'], ['status' => 'running', 'type' => 'complete', 'ORDER' => ['id' => 'DESC'], 'LIMIT' => 1])[0]['id'] : $id;
if (!$id) {
$this->db->insert('scans', [
'type' => 'complete',
'status' => 'running',
'start' => date('Y-m-d H:i:s.u')
]);
$id = $this->db->id();
/**Start the getting the info in background */
shell_exec("php " . __DIR__ . DS . "load-all-info.php " . $id . " > /dev/null 2>/dev/null &");
return ege(['status' => 'success', 'process_id' => $id, 'proc_status' => 'running']);
}
//get process status and end time
$query = $this->db->select('scans', ['status', 'scan_data'], ['id' => $id])[0];
$procStatus = $query['status'];
$scanData = $query['scan_data'];
if ($scanData) {
$scanData = json_decode($scanData, true);
return ege(['status' => 'success', 'process_id' => $id, 'proc_status' => $procStatus, 'data' => $scanData]);
}
//get disk infos
$cpusers = $this->db->select('cpusers', ['user', 'domain', 'plan', 'disk_total', 'disk_used', 'disk_perc'], ['scan_id' => $id]);
//get emails infos
$emails =
$this->db->select('emails', ['login', 'user', 'email_total', 'email_used', 'email_perc', 'cpuser'], ['scan_id' => $id, 'ORDER' => 'cpuser']);
//define array with disk infos and emails inside them
$data = array();
foreach ($cpusers as $cpuser) {
$arrEmails = [];
if (!empty($emails)) {
foreach ($emails as $email) {
if ($cpuser['user'] !== $email['cpuser']) {
continue;
}
$email += ['status' => $this->setStatus($email['email_perc'], $email['email_total'], $email['email_used'])];
array_push($arrEmails, $email);
}
}
$cpuser += ['status' => $this->setStatus($cpuser['disk_perc'], $cpuser['disk_total'], $cpuser['disk_used'])];
$cpuser += ['emails' => $arrEmails];
array_push($data, $cpuser);
}
if ($procStatus == 'complete' && !$scanData) {
$dbData = ['date' => date('Y-m-d H:i:s.u'), 'data' => $data];
$this->db->update('scans', [
'scan_data[JSON]' => $dbData
], ['id' => $id]);
}
return ege(['status' => 'success', 'process_id' => $id, 'proc_status' => $procStatus, 'data' => $data]);
}
JS
do {
startTime()
//genarate fetch request
await api
.get({ func: 'info', args: { scanId: scanId }, structure: '/{scanId}' })
.then(myJson => {
...
}
})
.catch(err => {})
diffTime()
//sleep for x ms
await new Promise(r => setTimeout(r, timeDiff))
} while (scanCompleted === false)