4

I did an implementation of Server Sent Event (SSE) with StreamedResponse in Symfony. So when an event occurs a message is saved in the session, this message will be notified to the user. The problem is when the page that contains the client code is executed, it blocks all web requests to the application until the SSE connection is closed due to Maximum execution time.

Server side code:

public function notificationAction() {
    $response = new StreamedResponse(function() {
        while(true) {
            $message = "";

            $messagesNotification = $this->get('session')->getFlashBag()->get('message_notification');; // code that search notifications from session
            if(count($messagesNotification)>0){
                foreach ( $messagesNotification as $messageNotification ) {
                    $message .= "data: " . messageNotification  . PHP_EOL;
                }
                $message .= PHP_EOL;
                echo $message;
                ob_flush();
                flush();

            }
            sleep(8);
        };

    });

    $response->headers->set('Content-Type', 'text/event-stream');
    $response->headers->set('Cache-Control', 'no-cache');
    return $response;
}

Client side code:

<script>
    var path = '/path';
    var source = new EventSource(path);
    source.onmessage = function(e) {
        // notification html
    };
    source.onerror = function(e) {
        // notification html
    };
</script>

I would like to know if this is a good implementation of SSE, and how to make the SSE call not to block requests.

I'm using symfony 2.6 and Firefox as the browser.

Thanks in advance for your help.

jherencia
  • 71
  • 1
  • 4

2 Answers2

5

session_start() that you use implicity with $this->get('session') will locks the session's file (if you use the native file session handler, by default) until you write it with

$this->get('session')->save()

Only then the file will be unlocked. Try to use it above sleep(8);.

Federkun
  • 36,084
  • 8
  • 78
  • 90
  • Hi, Thanks for your answer, it works, the requests aren't blocked anymore. There are other issues, on the client side when it receives the notification (onmessage) automatically there is a onerror triggered. And after some time a error message is shown in the console: "Firefox ne peut établir de connexion avec le serveur à l'adresse ...". Do you have any idea why is it happening? – jherencia Oct 26 '15 at 20:15
  • Federico, is this the symfony equivalent of `session_write_close()` then? (see, e.g. http://stackoverflow.com/a/30878764/841830 ) – Darren Cook Oct 28 '15 at 09:09
  • @jherencia Best to ask that in a new question (also, accept this answer if it solves the "blocks requests" question for you). It'd be worth translating the error message into English, and also trying it in another browser, such as Chrome, to see if it is Firefox-specific. – Darren Cook Oct 28 '15 at 09:11
  • 1
    @DarrenCook, [yes](https://github.com/symfony/http-foundation/blob/master/Session/Storage/NativeSessionStorage.php#L216) it is – Federkun Oct 28 '15 at 10:57
  • @Federico, I'm sorry for the message non translated. The translated message is "Firefox can not establish a connection to the server at the address...". I tried in Chrome, it just gives an error after some time without giving a message like Firefox does. This was the first time that I publish a question, so I didn't have the enough points to mark it as a useful answer. Thanks. – jherencia Oct 28 '15 at 14:16
  • what if I have different session handler like mysql? – Ramratan Gupta Oct 16 '17 at 10:03
  • If I remember correctly, other session handlers like PdoSessionHandler will use locks to serialize access too. – Federkun Oct 17 '17 at 05:54
1

If you want to use sse technology you don't need to put your code in a loop to be able to listen continuously because permanent listening is implicit in sse technology. then remove the loop it is not necessary. however this technology is not compatible with Symfony instead using the mercury protocol which is built on sse technology and which is very well integrated with symfony, unless you plan to modify the sources of symfony sse will not work. link in the symfony doc for mercury https://symfony.com/doc/current/mercure.html

senssen
  • 11
  • 2