Example #1
0
 /**
  * @param RuntimeInterface $runtime
  * @param ChannelCompositeInterface $composite
  * @param ConfigInterface $config
  */
 private function registerRuntimeSupervision(RuntimeInterface $runtime, ChannelCompositeInterface $composite, ConfigInterface $config)
 {
     $timerCollection = new TimerCollection();
     $channel = $composite->bus('slave');
     $keepalive = $config->get('core.tolerance.child.keepalive');
     $channel->on('disconnect', function ($alias) use($runtime, $keepalive, $timerCollection) {
         if ($keepalive <= 0) {
             return;
         }
         $timer = $runtime->loop()->addTimer($keepalive, function () use($alias, $runtime, $timerCollection) {
             $timerCollection->removeTimer($alias);
             $runtime->fail(new ChildUnresponsiveException("Child runtime [{$alias}] is unresponsive."), ['origin' => $alias]);
         });
         $timerCollection->addTimer($alias, $timer);
     });
     $channel->on('connect', function ($alias) use($timerCollection) {
         if (($timer = $timerCollection->getTimer($alias)) !== null) {
             $timer->cancel();
             $timerCollection->removeTimer($alias);
         }
     });
     $channel = $composite->bus('master');
     $keepalive = $config->get('core.tolerance.parent.keepalive');
     $channel->on('disconnect', function ($alias) use($runtime, $keepalive, $timerCollection) {
         if ($keepalive <= 0) {
             return;
         }
         $timer = $runtime->loop()->addTimer($keepalive, function () use($alias, $runtime, $timerCollection) {
             $timerCollection->removeTimer($alias);
             $runtime->fail(new ParentUnresponsiveException("Parent runtime [{$alias}] is unresponsive."), ['origin' => $alias]);
         });
         $timerCollection->addTimer($alias, $timer);
     });
     $channel->on('connect', function ($alias) use($timerCollection) {
         if (($timer = $timerCollection->getTimer($alias)) !== null) {
             $timer->cancel();
             $timerCollection->removeTimer($alias);
         }
     });
 }
Example #2
0
 /**
  * @param string $alias
  * @param string|null $name
  * @param int $flags
  * @return PromiseInterface
  */
 public function createThread($alias, $name, $flags = Runtime::CREATE_DEFAULT)
 {
     if (isset($this->threads[$alias])) {
         if ($name === null) {
             $name = $this->threads[$alias]->name;
         }
         if ($flags === Runtime::CREATE_FORCE_SOFT) {
             $manager = $this;
             return $this->destroyThread($alias, Runtime::DESTROY_FORCE_SOFT)->then(function () use($manager, $alias, $name) {
                 return $manager->createThread($alias, $name);
             });
         } else {
             if ($flags === Runtime::CREATE_FORCE_HARD) {
                 $manager = $this;
                 return $this->destroyThread($alias, Runtime::DESTROY_FORCE_HARD)->then(function () use($manager, $alias, $name) {
                     return $manager->createThread($alias, $name);
                 });
             } else {
                 if ($flags === Runtime::CREATE_FORCE) {
                     $manager = $this;
                     return $this->destroyThread($alias, Runtime::DESTROY_FORCE)->then(function () use($manager, $alias, $name) {
                         return $manager->createThread($alias, $name);
                     });
                 } else {
                     return Promise::doReject(new ResourceDefinedException('Thread with such alias already exists.'));
                 }
             }
         }
     } else {
         if ($name === null) {
             return Promise::doReject(new InvalidArgumentException('Name of new thread cannot be null.'));
         }
     }
     $controller = new ThreadController();
     $wrapper = new ThreadWrapper($controller, $this->runtime->core()->dataPath(), $this->runtime->alias(), $alias, $name);
     $wrapper->start(PTHREADS_INHERIT_ALL);
     $this->allocateThread($alias, $wrapper);
     $req = new Request($this->channel, $alias, new RuntimeCommand('cmd:ping'));
     return $req->call()->then(function () {
         return 'Thread has been created.';
     }, function ($reason) use($alias) {
         $this->freeThread($alias);
         return $reason;
     }, function ($reason) use($alias) {
         $this->freeThread($alias);
         return $reason;
     });
 }
Example #3
0
 /**
  * @param RuntimeInterface $runtime
  * @param ChannelBaseInterface $channel
  * @param string|null $receiver
  */
 public function __construct(RuntimeInterface $runtime, ChannelBaseInterface $channel, $receiver = null)
 {
     $this->runtime = $runtime;
     $this->channel = $channel;
     $this->receiver = $receiver !== null ? $receiver : $runtime->parent();
 }
Example #4
0
 /**
  * @param RuntimeInterface $runtime
  * @param ChannelCompositeInterface $composite
  * @param ChannelBaseInterface $console
  */
 private function applyRootRouting(RuntimeInterface $runtime, ChannelCompositeInterface $composite, ChannelBaseInterface $console)
 {
     $master = $composite->bus('master');
     $slave = $composite->bus('slave');
     $router = $composite->input();
     $router->addAnchor(new RuleHandler(function ($params) {
         return true;
     }));
     $router = $composite->output();
     $router->addAnchor(function ($receiver, ChannelProtocolInterface $protocol, $flags, callable $success = null, callable $failure = null, callable $cancel = null, $timeout = 0.0) use($runtime, $slave, $console) {
         if ($receiver === Runtime::RESERVED_CONSOLE_CLIENT || $protocol->getDestination() === Runtime::RESERVED_CONSOLE_CLIENT) {
             $console->push(Runtime::RESERVED_CONSOLE_CLIENT, $protocol, $flags, $success, $failure, $cancel, $timeout);
         } else {
             if ($runtime->manager()->existsRuntime($receiver) || $slave->isConnected($receiver)) {
                 $slave->push($receiver, $protocol, $flags, $success, $failure, $cancel, $timeout);
             } else {
                 $slave->push($slave->getConnected(), $protocol, $flags, $success, $failure, $cancel, $timeout);
             }
         }
     });
     $router = $master->input();
     $router->addRule(new RuleMatchDestination($master->name()), new RuleHandler(function ($params) use($composite) {
         $this->executeProtocol($composite, $params['protocol']);
     }));
     $router->addAnchor(new RuleHandler(function ($params) use($slave) {
         $slave->push($slave->getConnected(), $params['protocol'], $params['flags']);
     }));
     $router = $slave->input();
     $router->addRule(new RuleMatchDestination($slave->name()), new RuleHandler(function ($params) use($composite) {
         $this->executeProtocol($composite, $params['protocol']);
     }));
     $router->addAnchor(new RuleHandler(function ($params) use($runtime, $slave, $console) {
         $receiver = $params['alias'];
         $protocol = $params['protocol'];
         if ($receiver === Runtime::RESERVED_CONSOLE_CLIENT || $protocol->getDestination() === Runtime::RESERVED_CONSOLE_CLIENT) {
             $console->push(Runtime::RESERVED_CONSOLE_CLIENT, $protocol, $params['flags']);
         } else {
             $slave->push($slave->getConnected(), $params['protocol'], $params['flags']);
         }
     }));
     $router = $master->output();
     $router->addAnchor(function ($sender, ChannelProtocolInterface $protocol, $flags, callable $success = null, callable $failure = null, callable $cancel = null, $timeout = 0.0) use($master) {
         $master->push($sender, $protocol, $flags, $success, $failure, $cancel, $timeout);
     });
     $router = $slave->output();
     $router->addAnchor(function ($sender, ChannelProtocolInterface $protocol, $flags, callable $success = null, callable $failure = null, callable $cancel = null, $timeout = 0.0) use($slave) {
         $slave->push($sender, $protocol, $flags, $success, $failure, $cancel, $timeout);
     });
 }
Example #5
0
 /**
  * @param string $alias
  * @param string|null $name
  * @param int $flags
  * @return PromiseInterface
  */
 public function createProcess($alias, $name, $flags = Runtime::CREATE_DEFAULT)
 {
     if (isset($this->processes[$alias])) {
         if ($name === null || $name === 'null') {
             $name = $this->processes[$alias]['name'];
         }
         if ($flags === Runtime::CREATE_DEFAULT && $this->processes[$alias]['verified'] === false) {
             $manager = $this;
             $req = new Request($this->channel, $alias, new RuntimeCommand('cmd:ping'));
             return $req->call()->then(function ($response) {
                 return 'Process has been created.';
             }, function () use($manager, $alias, $name) {
                 return $manager->createProcess($alias, $name, Runtime::CREATE_FORCE_HARD);
             });
         } else {
             if ($flags === Runtime::CREATE_FORCE_SOFT) {
                 $manager = $this;
                 return $this->destroyProcess($alias, Runtime::DESTROY_FORCE_SOFT)->then(function () use($manager, $alias, $name) {
                     return $manager->createProcess($alias, $name);
                 });
             } else {
                 if ($flags === Runtime::CREATE_FORCE_HARD) {
                     $manager = $this;
                     return $this->destroyProcess($alias, Runtime::DESTROY_FORCE_HARD)->then(function () use($manager, $alias, $name) {
                         return $manager->createProcess($alias, $name);
                     });
                 } else {
                     if ($flags === Runtime::CREATE_FORCE) {
                         $manager = $this;
                         return $this->destroyProcess($alias, Runtime::DESTROY_FORCE)->then(function () use($manager, $alias, $name) {
                             return $manager->createProcess($alias, $name);
                         });
                     } else {
                         return Promise::doReject(new ResourceDefinedException('Process with such alias already exists.'));
                     }
                 }
             }
         }
     } else {
         if ($name === null) {
             return Promise::doReject(new InvalidArgumentException('Name of new process cannot be null.'));
         }
     }
     $pid = $this->system->run($this->phpCommand('surume.process', [$this->runtime->alias(), $alias, $name]));
     if (!$this->system->existsPid($pid)) {
         return Promise::doReject(new ResourceDefinedException('Process could not be created.'));
     }
     if (!$this->allocateProcess($alias, $name, $pid)) {
         return Promise::doReject(new ResourceDefinedException('Process could not be created because of storage failure.'));
     }
     $req = new Request($this->channel, $alias, new RuntimeCommand('cmd:ping'));
     return $req->call()->then(function ($response) {
         return 'Process has been created.';
     }, function ($reason) use($alias) {
         $this->freeProcess($alias);
         throw $reason;
     }, function ($reason) use($alias) {
         $this->freeProcess($alias);
         return $reason;
     });
 }