1

I have a csv file that contains bulks of data. The goal is to import this data into the database. Initially the file is processed in the client side and then when it has been validated on the client side, it is sent to the server for database inserting.

On my server-side, I use cakephp 3 framework.

What I need is to give an update (i.e. percentage of inserted data) from the controller action to the client side.

I've done research and I've stumbled across Server Sent Events which could be used for the solution. If I get the the following code to work, I can figure out how to notify the client side of the progress. However when I tryout the sample code, I keep getting the 'error' event with readyState equal to EventSource.CONNECTING.

This is the sample code taken from a tutorial site for SSE, I just tried to apply it to cakephp 3:

index.ctp

<button id="btnStartTheClock">start</button>
<button id="btnStopTheClock">stop</button>
<div id="result"></div>


<script type="text/javascript">
var essSupport = false, es, result;
function init() {
    esSupport = (window.EventSource !== undefined);
    result = document.getElementById("result");
    document.getElementById("btnStartTheClock").onclick = startTheClock;
    document.getElementById("btnStopTheClock").onclick = stopTheClock;
}

window.onload = init;

function startTheClock() {
    if(esSupport) {
        if (es === undefined) {
            es = new EventSource("import-progress");
            es.addEventListener('message', function (event) {
                result.innerHTML += event.data + '<br/>';
            });
            es.addEventListener('open', function (e) {
                result.innerHTML += "<span style='color:green;'>SSE open</span><br/>";
            });
            es.addEventListener('error', function(e) {
                e = e || event, msg = '';

                switch( e.target.readyState ){
                // if reconnecting
                case EventSource.CONNECTING:
                    msg = 'Reconnecting…';
                    break;
                // if error was fatal
                case EventSource.CLOSED:
                    msg = 'Connection failed. Will not retry.';
                    break;
                }
                result.innerHTML += '<span style="color:red;">' + msg + "</span><br>";
            });
        }
    }
    else {
        result.innerHTML = "Your browser doesn't support server-sent events.";
    }
}

function stopTheClock() {
    if(esSupport) { 
        es.close(); 
        result.innerHTML += "Clock Stopped.<br>";
    }
}
</script>

SamplesController.php

<?php
namespace App\Controller;

use Cake\Controller\Controller;
use Cake\Controller\Component\RequestHandlerComponent;
use Cake\Event\Event;


class SamplesController extends AppController
{
    public function initialize()
    {
        parent::initialize();
        // $this->loadComponent('RequestHandler');
    }

    public function index()
    {
    }

    public function importProgress()
    {
        $this->set('datetime', date("h:i:s"));
    }
}

import_progress.ctp

<?php
    header('Content-Type: text/event-stream');
    header('Cache-Control: no-cache');
    header('Connection: keep-alive');

    echo "data: The server time is: {$datetime}\n\n";
    flush();
?>

If you please:

  • What do I need to look for or to understand in order to achieve this goal?
  • Can you suggest a different solution from this?

Side note:

  • I'm new to CakePHP
  • I'm new to Server Side Events

Thanks!

2 Answers2

0

I'd look into using websockets rather than SSE - it seems to have picked up much more traction - and then you are able to use eg. Ratchet or ReactPHP.

Another thing though - it might be easier to save the progress in your DB, and just do a AJAX request to an endpoint checking the status/progress of this job every x seconds.

Eg if you're using https://github.com/dereuromark/cakephp-queue - you can see an example of how to update a job's status here: https://github.com/dereuromark/cakephp-queue/tree/master/docs#updating-status

Spriz
  • 457
  • 2
  • 9
0

This is a old topic:

Show progress for long running PHP script

Remember to close the loop from the server side to prevent unnecessary loop. Websocket is mainly use for continuous persistent connection, not for one-time task such as this. No point running websocket listening loop for no reason.

Community
  • 1
  • 1