Sending status updates of action via Ratchet\ReactPHP

204 Views Asked by At

I have a secure websocket set up and working with a combination of Ratchet and ReactPHP. Part of what I want to accomplish, is to allow the user to action something which would be sent to the server, and get notification of each parts completion - something along the lines of:

public function process()
{
    $this->currentconnection->send("Doing 1 of 3");
    // action first part of process
    $this->currentconnection->send("Doing 2 of 3");
    // uses output of first part to perform second
    $this->currentconnection->send("Doing 3 of 3");
    // uses output of second to perform third
    $this->currentconnection->send("Complete!");
}

However this is effectively creating a blocking function, as when this runs the messages aren't sent through to the connection until the function has finished processing.

Previously I had accomplished this via ajax requests back and forth between the browser and the PHP backend, but thought I might be able to accomplish this without the back-and-forth and make use of the websocket (that I'm using for other functionality) to accomplish this.

I've been looking through examples and trying different things to try and achieve this, but I'm really struggling and can't find any examples of this being accomplished elsewhere. Right now it feels like I'd need to run this as a child process and then (somehow) poll it, but I'm finding that tricky as well.

As such if anyone has suggestions, example logic, or a pointer of where I should be looking to create this asynchronous function/class that can report back on its process, that would be amazing. Thank you.

1

There are 1 best solutions below

0
On

I've managed to resolve my issue by making use of the $loop->futureTick functionality. I created a class wherein the actions are split into methods, and should the method end it makes use of the futureTick method to queue up the next action. An example of what I mean is as follows:

class Actions
{
    public function __construct(ConnectionInterface $conn, $loop)
    {
        $this->connection = $conn;
        $this->loop = $loop;
    }

    public function action1()
    {
        // ... do action ...
        if ($fail) {
            $this->connection->send('Action 1 failed');
        } else {
            $this->connection->send('Action 1 success');
            $this->loop->futureTick(function() {
                $this->action2();
            });
        }
    }

    public function action2()
    {
        ...
        $this->loop->futureTick(function() {
            $this->action3();
        });
    }
}

This allows for each of the actions to be done via the loop, and each time a function completes the client is informed of it.

It might not be the ideal way of achieving this, so I'd still be open for suggestions as to if (for instance) the actions should be created as a separate process and the connection told as that progresses. I'm just unsure how that might be achieved currently.