Run a detached endless job in Symfony
Asked Answered
B

0

0
  • 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

Blane answered 26/11, 2018 at 21:58 Comment(9)
If your host doesn't give you shell access they're for damn sure not going to let you run custom daemons/services, nor are they going to like you trying to fork off orphans for the same purpose. Get a VPS or better and write a system service definition for your daemon.Evangelina
@Evangelina The host I'm using does allow exec, shell_exec, proc_open and things like that. I was hoping that would do the trick somehowBlane
Can you run arbitrary commands so you can start a GNU screen session in detached mode and run your program in it?Toplevel
@EmilyE. If I understand you correctly, you want me to run commands in a subshell? I believe this won't work either for the same reason > /dev/null 2>&1 & doesn't work. All processes in my terminal session are terminated once the user's request ends. This includes subshells.Blane
@EmilyE. In case it would work. wouldn't it become increasingly difficult to track the running process? The goal here is to be able to do everything from within a symfony controller/service/commandBlane
take a look at sexpect. it's like Expect but u can use sexpect with bash code. it can start a command on a pty in the background and still u have full control of it.Palmy
@Palmy that might solve the tracking problem, but this still wouldn't solve issue 2. Most webhosting services don't give you access to the terminal. good to know though!Blane
@Blane Is there any solution you found or recommend?, I am in exactly same situation with ratchet socketAssail
@MayankTiwari Hi, well... actually... yes and no. I couldn't run this in a terminal, because of the nature of terminals it would timeout or break for whatever reason. Plus not all web hosting services provide you with sufficient shell access to tinker. I eventually ended up using chronjobs or windows task manager - depending on what OS you're running. The upside is that you can configure tasks to restart should they failBlane

© 2022 - 2024 — McMap. All rights reserved.