Timer Server in ReactPHP

In many applications such as auctions, you need a dynamic collection of timers, such that you can add timers, and cancel timers.

We found ReactPHP superior for this. This sweet and simple server sets a new timer specified by a timeout and a task to be performed on timeout. For example sake, the task is just a string to be printed.

The server has three endpoints:

  • GET /timers - list the active timers

  • POST /add - add a timer, and returns a timer index for future reference

  • POST /cancel - delete a timer by its index

Assuming you have installed ReactPHP using:

composer install react/event-loop

composer install react/http

Composer install nikic/fast-route

The server is:

require __DIR__ . '/vendor/autoload.php';

use React\Http\Server;

use React\Http\Response;

use React\EventLoop\Factory;

use Psr\Http\Message\ServerRequestInterface;

$counter = 0;

$timers = [];

$loop = Factory::create();

$server = new Server(function (ServerRequestInterface $request) use (&$timers, &$loop, &$counter) {

  $path = $request->getUri()->getPath();

  $method = $request->getMethod();

  if ($path === '/timers' && $method === 'GET') {

    return new Response(200, ['Content-Type' => 'text/plain'],  implode(PHP_EOL, $tasks));

  } else if ($path == '/add' && $method === 'POST') {

       var_dump($request->getParsedBody());

    $task = $request->getParsedBody()['task'] ?? null;

    if ($task) {

      $timer = $loop->addPeriodicTimer($time, function() use(&$task) {

        echo "task:" . $task . "Timeout \n";

      });

              $timers[$counter++] = $timer;

      return new Response(201, $counter);

    }

    return new Response(400, ['Content-Type' => 'text/plain'], 'Task field is required');

  } else if ($path === '/cancel' && $method === 'POST') {

    $index = $request->getParsedBody()['index'] ?? null;

    if ($index) {

      $loop->cancelTimer($tasks[$index]);

    }

    return new Response(201);

  }

  return new Response(404, ['Content-Type' => 'text/plain'],  'Not found');

});

$socket = new \React\Socket\Server('127.0.0.1:8000', $loop);

$server->listen($socket);

echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . "\n";

$loop->run();