1

I'm trying to build a small application which will do a few things.

A main class will spawn, destroy, listen to, and manage workers...

<?php

  namespace Queue;

  class Controller extends Process
  {
    public $workers = array();
    function __construct()
    {
      //Run the Process constructor before doing anything else.
      parent::__construct();
    }
    function spawnWorker($businessId)
    {
      $this->workers[$businessId] = new \React\ChildProcess\Process("php index.php worker $businessId");
      $this->workers[$businessId]->start($this->loop);
      $this->workers[$businessId]->stdout->on("data", function($output) use(&$businessId)  {
        $this->channels->out->write("Child $businessId Said: " . $output);
      });
    }
    function outputToWorker($businessId, $string)
    {
      $this->workers[$businessId]->stdin->write($string);
    }
    function run()
    {
      $this->loop->run();
    }
  }

A bunch of workers managed by the controller (eventually they will have a long running process which manages a queue defined in the database)...

<?php

  namespace Queue;

  class Worker extends Process
  {
    function __construct($businessId)
    {
      //Run the Process constructor before doing anything else.
      parent::__construct();
      // Assign a business to this worker.
      $this->businessId = $businessId;
      // Create a queue object for this worker.
      $this->queue = new \stdClass;
    }
    function run()
    {
      $this->channels->in->on("data", function($input) {
        $this->sendOutput($input);
      });
      $this->loop->run();
    }
  }

However, I ran across a situation where code did not do what I expected...

// Based on command line argument, decide which kind of process to spawn.
  if (!isset($argv[1]) || $argv[1] === "controller")
  {
    $controller = new Controller;
    $controller->spawnWorker(1);
    $controller->outputToWorker(1, "Before Run");
    $controller->run();
    $controller->outputToWorker(1, "After Run");
  } else if (strtolower($argv[1]) === "worker" && isset($argv[2]))
  {
    $worker = new Worker($argv[1]);
    $worker->run();
  }

This last bit of code is the file which I actually run to start the application. It routes which kind of process should be spawned based on command line arguments. (This way I don't have to have a file for a bunch of different kinds of processes.)

The worker is spawned correctly, and the first message (Child 1 Said: Before Run) is sent to the worker, the worker sends it to stdout and the controller hears that event and sends it to it's own stdout.

However, it seems the listener is a one-time listener, and the event loop is not reprocessing it over an over. Meaning, anytime after the initial run() on controller it will not respond to stdout events from the worker.

Do I have to create my own explicit listeners with timers?

Allenph
  • 1,875
  • 27
  • 46
  • Where does `$this->loop` come from? I don't see it set anywhere. – kelunik Jan 28 '17 at 17:46
  • I should have added that. Both the worker and the Controller extend process which creates properties and instances for each class's loop and communication channels. – Allenph Jan 28 '17 at 18:26
  • Please add it to your code, I guess you have two loops somewhere. – kelunik Jan 29 '17 at 08:34

0 Answers0