Example #1
0
 public function __construct()
 {
     $this->messageFactory = new MessageFactory();
     $this->questionFactory = new QuestionFactory();
     $this->encoder = (new EncoderFactory())->create();
     $this->decoder = (new DecoderFactory())->create();
     $this->arrayCache = new ArrayCache();
     $this->requestIdCounter = 1;
     $this->pendingRequests = [];
     $this->serverIdMap = [];
     $this->serverUriMap = [];
     $this->serverIdTimeoutMap = [];
     $this->now = \time();
     $this->serverTimeoutWatcher = \Amp\repeat(function ($watcherId) {
         $this->now = $now = \time();
         foreach ($this->serverIdTimeoutMap as $id => $expiry) {
             if ($now > $expiry) {
                 $this->unloadServer($id);
             }
         }
         if (empty($this->serverIdMap)) {
             \Amp\disable($watcherId);
         }
     }, 1000, $options = ["enable" => true, "keep_alive" => false]);
 }
Example #2
0
 /**
  * By using a rebound TTL watcher with a shared state object we're
  * able to use __destruct() for "normal" garbage collection of
  * both this instance and the reactor watcher callback. Otherwise
  * this object could only be GC'd when the TTL watcher was cancelled
  * at the event reactor layer.
  *
  * @param int $gcInterval The frequency in milliseconds at which expired
  *                        cache entries should be garbage collected
  */
 public function __construct($gcInterval = 5000)
 {
     $this->sharedState = $sharedState = new \StdClass();
     $sharedState->cache = [];
     $sharedState->cacheTimeouts = [];
     $sharedState->isSortNeeded = false;
     $ttlWatcher = function () {
         // xdebug doesn't seem to generate code coverage
         // for this closure ... it's annoying.
         // @codeCoverageIgnoreStart
         $now = \time();
         if ($this->isSortNeeded) {
             \asort($this->cacheTimeouts);
             $this->isSortNeeded = false;
         }
         foreach ($this->cacheTimeouts as $key => $expiry) {
             if ($now > $expiry) {
                 unset($this->cache[$key], $this->cacheTimeouts[$key]);
             } else {
                 break;
             }
         }
         // @codeCoverageIgnoreEnd
     };
     $ttlWatcher = $ttlWatcher->bind($ttlWatcher, $sharedState);
     $this->ttlWatcherId = \Amp\repeat($ttlWatcher, $gcInterval, $options = ["enable" => true, "keep_alive" => false]);
 }
Example #3
0
 public function __construct(Logger $logger)
 {
     parent::__construct($logger);
     $this->logger = $logger;
     $this->procGarbageWatcher = \Amp\repeat(function () {
         $this->collectProcessGarbage();
     }, 100, ["enable" => false]);
 }
Example #4
0
 public function test_amp_1()
 {
     echo "before run()\n";
     \Amp\run(function () {
         \Amp\repeat(function () {
             echo "tick\n";
         }, $msInterval = 1000);
         \Amp\once("\\Amp\\stop", $msDelay = 5000);
     });
     echo "after run()\n";
 }
 public function run(InputInterface $inputInterface, OutputInterface $outputInterface)
 {
     register_shutdown_function(array($this, 'terminate'), $inputInterface, $outputInterface);
     \Amp\run(function () use($inputInterface, $outputInterface) {
         \Amp\repeat(function () use($inputInterface, $outputInterface) {
             if ($leaking = $this->isLeaking()) {
                 $this->getContainer()->get('logger')->alert('Memory leaked.', $leaking);
             }
             parent::run($inputInterface, $outputInterface);
         }, 1);
         $outputInterface->writeln('The command has <info>successfully</info> started.');
     });
 }
Example #6
0
 public final function update(\SplSubject $subject) : Promise
 {
     switch ($subject->state()) {
         case Server::STARTED:
             $this->watcherId = \Amp\repeat([$this, "updateTime"], 1000);
             $this->updateTime();
             break;
         case Server::STOPPED:
             \Amp\cancel($this->watcherId);
             $this->watcherId = null;
             break;
     }
     return new Success();
 }
Example #7
0
 private static function init()
 {
     self::$isInitialized = true;
     self::$now = \time();
     \Amp\repeat(function () {
         self::$now = $now = \time();
         foreach (self::$cache as $path => $expiry) {
             if ($now > $expiry) {
                 unset(self::$cache[$path], self::$timeouts[$path]);
             } else {
                 break;
             }
         }
     }, 1000, ["keep_alive" => false]);
 }
Example #8
0
 private function registerSignalHandler()
 {
     if (php_sapi_name() === "phpdbg") {
         // phpdbg captures SIGINT so don't bother inside the debugger
         return;
     }
     $onSignal = coroutine([$this, "stop"]);
     if (\Amp\reactor() instanceof UvReactor) {
         \Amp\onSignal(\UV::SIGINT, $onSignal, ["keep_alive" => false]);
         \Amp\onSignal(\UV::SIGTERM, $onSignal, ["keep_alive" => false]);
     } elseif (extension_loaded("pcntl")) {
         \Amp\repeat("pcntl_signal_dispatch", 1000, ["keep_alive" => false]);
         pcntl_signal(\SIGINT, $onSignal);
         pcntl_signal(\SIGTERM, $onSignal);
     }
 }
Example #9
0
 public function update(Server $server) : Promise
 {
     switch ($this->state = $server->state()) {
         case Server::STARTING:
             $result = $this->application->onStart($this->proxy);
             if ($result instanceof \Generator) {
                 return resolve($result);
             }
             break;
         case Server::STARTED:
             $f = (new \ReflectionClass($this))->getMethod("timeout")->getClosure($this);
             $this->timeoutWatcher = \Amp\repeat($f, 1000);
             break;
         case Server::STOPPING:
             $result = $this->application->onStop();
             if ($result instanceof \Generator) {
                 $promise = resolve($result);
             } elseif ($result instanceof Promise) {
                 $promise = $result;
             } else {
                 $promise = new Success();
             }
             $promise->when(function () {
                 $code = Code::GOING_AWAY;
                 $reason = "Server shutting down!";
                 foreach ($this->clients as $client) {
                     $this->close($client->id, $code, $reason);
                 }
             });
             \Amp\cancel($this->timeoutWatcher);
             $this->timeoutWatcher = null;
             return $promise;
         case Server::STOPPED:
             $promises = [];
             // we are not going to wait for a proper self::OP_CLOSE answer (because else we'd need to timeout for 3 seconds, not worth it), but we will ensure to at least *have written* it
             foreach ($this->clients as $client) {
                 // only if we couldn't successfully send it in STOPPING
                 $code = Code::GOING_AWAY;
                 $reason = "Server shutting down!";
                 $result = $this->doClose($client, $code, $reason);
                 if ($result instanceof \Generator) {
                     $promise[] = resolve($result);
                 }
                 if (!empty($client->writeDeferredControlQueue)) {
                     $promise = end($client->writeDeferredControlQueue)->promise();
                     if ($promise) {
                         $promises[] = $promise;
                     }
                 }
             }
             $promise = any($promises);
             $promise->when(function () {
                 foreach ($this->clients as $client) {
                     $this->unloadClient($client);
                 }
             });
             return $promise;
     }
     return new Success();
 }
Example #10
0
function __init()
{
    $state = new \StdClass();
    $state->messageFactory = new MessageFactory();
    $state->questionFactory = new QuestionFactory();
    $state->encoder = (new EncoderFactory())->create();
    $state->decoder = (new DecoderFactory())->create();
    $state->arrayCache = new ArrayCache();
    $state->requestIdCounter = 1;
    $state->pendingRequests = [];
    $state->serverIdMap = [];
    $state->serverUriMap = [];
    $state->serverIdTimeoutMap = [];
    $state->now = \time();
    $state->serverTimeoutWatcher = \Amp\repeat(function ($watcherId) use($state) {
        $state->now = $now = \time();
        foreach ($state->serverIdTimeoutMap as $id => $expiry) {
            if ($now > $expiry) {
                __unloadServer($state, $id);
            }
        }
        if (empty($state->serverIdMap)) {
            \Amp\disable($watcherId);
        }
    }, 1000, $options = ["enable" => true, "keep_alive" => false]);
    $state->config = (yield \Amp\resolve(__loadResolvConf()));
    (yield new CoroutineResult($state));
}
Example #11
0
<?php

require __DIR__ . '/../vendor/autoload.php';
$i = 0;
\Amp\repeat(function () use(&$i) {
    echo "\n{$i} iterations";
    $i = 0;
}, 1000);
\Amp\once(function () {
    \Amp\stop();
}, 5000);
\Amp\once(function () {
    \Amp\stop();
}, 10000);
echo "##### SET OP/S";
\Amp\run(function () use(&$i) {
    $memcached = new \Edo\Memcached();
    $memcached->addServer('tcp://127.0.0.1', 11211);
    while (true) {
        $stats = (yield $memcached->set('key', 'value_key'));
        $i++;
    }
});
echo "\n##### GET OP/S";
\Amp\run(function () use(&$i) {
    $memcached = new \Edo\Memcached();
    $memcached->addServer('tcp://127.0.0.1', 11211);
    while (true) {
        $stats = (yield $memcached->get('key'));
        $i++;
    }
 private function addWatchers()
 {
     \Amp\repeat(function () {
         $previousMemory = $this->memory;
         $this->memory = memory_get_peak_usage(true);
         $leakage = $this->memory - $previousMemory;
         $this->logger->info('Memory consumption', ['memory' => $this->memory / 1024 / 1024, 'increase' => $leakage]);
     }, self::TIMER_LOGGER, $options = ['keep_alive' => self::TIMER_KEEP_ALIVE]);
     return true;
 }
Example #13
-2
 /**
  * @throws \Exception
  */
 public function run()
 {
     if (!is_callable($this->updateCallback)) {
         throw new NotCallableException(sprintf('"%s" is not a callable function. Set it via "%s".', 'updateCallback', 'onUpdate'));
     }
     \Amp\run(function () {
         \Amp\repeat(function () {
             foreach ($this->getUpdates() as $update) {
                 $this->runCallback($update);
                 $this->incrementOffset($update);
             }
         }, $this->getTimeout());
     });
 }