What is the best way to setup PHP api for cyclic calls?

Issue

This Content is from Stack Overflow. Question asked by Mattia Consiglio

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.
This 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.

Now I start the process by using shell_exec and for following requests I get the data from the database that I think is slower and more heavy for the server.

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)



Solution

This question is not yet answered, be the first one who answer using the comment. Later the confirmed answer will be published as the solution.

This Question and Answer are collected from stackoverflow and tested by JTuto community, is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?