Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use a Ratchet\Server\IoServer object after run executed?

I want to run a function that iterates through a generator class. The generator functions would run as long as the Ratchet connection is alive. All I need to do is to make this happen after the run method is executed:

use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Chat;

require dirname(__DIR__) . '/xxx/vendor/autoload.php';

 $server = IoServer::factory(

    new HttpServer(
        new WsServer(
            new Chat()
        )
    ),

    8180,
    '0.0.0.0'

);

$server->run();

This is the method I need to run in the server after it is started:

function generatorFunction()
{

$products = r\table("tableOne")->changes()->run($conn);
 foreach ($products as $product) {
   yield $product['new_val'];
 }

}

Previously I was calling the function before $server->run() like this:

for ( $gen = generatorFunction(); $gen->valid(); $gen->next()) {
 var_dump($gen->current());
}
$server->run();

But this doesn't allow the client to establish a connection to the Ratchet server. I suspect it never comes to $server->run() as the generator class is being iterated.

So now, I want to start the server first, then call this generator method so that it can keep listening to changes in rethinkdb.

How do I do that?

like image 210
112233 Avatar asked Mar 17 '18 14:03

112233


1 Answers

Let's start by example:

<?php

require 'vendor/autoload.php';

class Chat implements \Ratchet\MessageComponentInterface {
    function onOpen(\Ratchet\ConnectionInterface $conn) { echo "connected.\n"; }
    function onClose(\Ratchet\ConnectionInterface $conn) {}
    function onError(\Ratchet\ConnectionInterface $conn, \Exception $e) {}
    function onMessage(\Ratchet\ConnectionInterface $from, $msg) {}
}

$loop = \React\EventLoop\Factory::create(); // create EventLoop best for given environment
$socket = new \React\Socket\Server('0.0.0.0:8180', $loop); // make a new socket to listen to (don't forget to change 'address:port' string)
$server = new \Ratchet\Server\IoServer(
    /* same things that go into IoServer::factory */
    new \Ratchet\Http\HttpServer(
        new \Ratchet\WebSocket\WsServer(
            new Chat() // dummy chat to test things out
        )
    ), 
    /* our socket and loop objects */
    $socket, 
    $loop
);

$loop->addPeriodicTimer(1, function (\React\EventLoop\Timer\Timer $timer) {
    echo "echo from timer!\n";
});

$server->run();

To achieve what you need you don't have to run the loop before or after the $server->run() but it needs to be run simultaneously.

For that you need to get deeper than Ratchet - to ReactPHP and its EventLoop. If you have access to the loop interface then adding a timer (that executes once) or a periodic timer (every nth second) is a piece of cake.

like image 101
Michal Bieda Avatar answered Oct 05 '22 23:10

Michal Bieda