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]); }
/** * 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]); }
public function __construct(Logger $logger) { parent::__construct($logger); $this->logger = $logger; $this->procGarbageWatcher = \Amp\repeat(function () { $this->collectProcessGarbage(); }, 100, ["enable" => false]); }
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.'); }); }
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(); }
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]); }
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); } }
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(); }
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)); }
<?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; }
/** * @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()); }); }