Run a detached endless job in Symfony

2019-08-28 05:55发布

  • Symfony: 4.1
  • PHP: 7.1

I have working websocket server using Ratchet. The websocket itself works fin. I can run it from the terminal using Symfony's commands

php bin/console app:websocket:execute

I'm having trouble getting around some of these issues:

  1. You need to dedicate a terminal to running this command
  2. Most webhosting services don't give you access to the terminal
  3. I want admins to be able to toggle the websocket server on and off
  4. Admins aren't required to know what a terminal is

For issue 1, I try to use this "detaching" cheat, but it doesn't solve issue 2:

php bin/console app:websocket:execute > /dev/null 2>&1 &

In order to tackle all four issues. I have tried using a process. but the issues with this approach is:

  • $process->run() - running a process with php bin/console always ends in a timeout
  • $process-start() - starting a process means it runs asynchronously, but it also means the process is terminated once the request ends, terminating my websocket server too.

Here is an example

$process = new Process("php bin/console");
$process->setWorkingDirectory(getcwd() . "/../");
$process->setTimeout(10);
$process->run(); // Stalls for 10 seconds, then throws timeout exception
$process-start(); // Doesn't stall, but terminates at end of request

// $process->run() ==== unreachable code
if (!$process->isSuccessful()) {
    throw new ProcessFailedException($process);
}

I have tried creating a console application, and run the command from there. but the same issues as a process apply here.

$application = new Application($this->kernel);
$application->setAutoExit(false);

$input = new ArrayInput(array(
    'command' => 'app:websocket:execute'
));

try {
    $ob = new BufferedOutput();
    $application->run($input, $ob);
    $output = $ob->fetch();
} catch (\Exception $e) {
    return null;
}

As a final resort, I tried a bundle called DtcQueueBundle, because it mentions the following:

Ease of Use

  • Kickoff background tasks with a line of code or two
  • Easily add background worker services
  • Turn any code into background task with a few lines

So I did what they asked, created a worker and tried to run it as a "background task"

use App\Ratchet\ForumUpdater;
use Ratchet\Http\HttpServer;
use Ratchet\Server\IoServer;
use Ratchet\WebSocket\WsServer;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class SocketWorker extends \Dtc\QueueBundle\Model\Worker
{
    public function execute()
    {
        $server = IoServer::factory(
            new HttpServer(
                new WsServer(
                    new ForumUpdater()
                )
            ),
            8080
        );

        $server->run();

        return "Websocket started";
    }

    public function getName()
    {
        return "websocket-server";
    }
}

Their docs are the absolute worst! I even tried to dig into their code to start jobs from inside my controller. But I couldn't get it to run in a detached manner.

Whatever happens, I believe my command isn't running because it highjacks my PHP thread. I would like to know, is it possible to detach this endless process? Is it even possible to run two PHP instances together? I would think so!

Thanks for any help, sorry for the long post

0条回答
登录 后发表回答