Example #1
0
 public function __construct(Client $client, Mutex $mutex)
 {
     $this->client = $client;
     $this->mutex = $mutex;
     $this->locks = [];
     $this->repeatTimer = repeat(function () {
         foreach ($this->locks as $id => $token) {
             $this->mutex->renew($id, $token);
         }
     }, $this->mutex->getTTL() / 2);
 }
Example #2
0
 /**
  * @param string $root
  * @param \Amp\File\Driver $filesystem
  * @param \Amp\Reactor $reactor
  * @throws \DomainException On invalid root path
  */
 public function __construct(string $root, file\Driver $filesystem = null)
 {
     $root = \str_replace("\\", "/", $root);
     if (!(\is_readable($root) && \is_dir($root))) {
         throw new \DomainException("Document root requires a readable directory");
     }
     $this->root = \rtrim(\realpath($root), "/");
     $this->filesystem = $filesystem ?: file\filesystem();
     $this->multipartBoundary = \uniqid("", true);
     $this->cacheWatcher = amp\repeat(function () {
         $this->now = $now = time();
         foreach ($this->cacheTimeouts as $path => $timeout) {
             if ($now <= $timeout) {
                 break;
             }
             $fileInfo = $this->cache[$path];
             unset($this->cache[$path], $this->cacheTimeouts[$path]);
             $this->bufferedFileCount -= isset($fileInfo->buffer);
             $this->cacheEntryCount--;
         }
     }, 1000, $options = ["enable" => false]);
 }
Example #3
0
 public function enableForRoom(Room $room, bool $persist = true)
 {
     repeat(function () use($room) {
         return $this->checkStatusChange($room);
     }, 150000);
 }
Example #4
0
 /**
  * Constructs a new Mutex instance. A single instance can be used to create as many locks as you need.
  *
  * @param string $uri URI of the Redis server instance, e.g. tcp://localhost:6379
  * @param array $options {
  *      General options for this instance.
  *
  * @type string|null $password password for the Redis server
  * @type int $max_connections maximum of concurrent Redis connections waiting for a lock with blocking commands
  * @type int timeout timeout for blocking lock wait
  * @type int $ttl key ttl for created locks and lock renews
  * }
  */
 public function __construct(string $uri, array $options)
 {
     $this->uri = $uri;
     $this->options = $options;
     $this->std = new Client($uri, isset($options["password"]) ? ["password" => $options["password"]] : []);
     $this->maxConnections = $options["max_connections"] ?? 0;
     $this->ttl = $options["ttl"] ?? 1000;
     $this->timeout = (int) (($options["timeout"] ?? 1000) / 1000);
     $this->readyConnections = [];
     $this->busyConnections = [];
     $this->busyConnectionMap = [];
     $this->watcher = repeat(function () {
         $now = time();
         $unused = $now - 60;
         foreach ($this->readyConnections as $key => list($time, $connection)) {
             if ($time > $unused) {
                 break;
             }
             unset($this->readyConnections[$key]);
             $connection->close();
         }
     }, 5000);
 }
Example #5
0
 private function connect(Request $request)
 {
     $promise = httpClient()->request($request, [HttpClient::OP_DISCARD_BODY => true, HttpClient::OP_MS_TRANSFER_TIMEOUT => null]);
     // yes, yes not spec compliant but it *gets the job done* until we can implement something better
     $chunkCombiner = new JsonChunkCombiner();
     $stats = new Stats();
     $logger = $this->logger;
     $callback = function (array $notifyData) use($chunkCombiner, $stats, $logger) {
         $event = array_shift($notifyData);
         if ($event === Notify::REQUEST_SENT) {
             $stats->increment('connectionAttempts');
             $msg = "Connection request #{$stats->connectionAttempts()} sent";
             $logger->info($msg);
         }
         if ($event === Notify::RESPONSE_HEADERS) {
             $stats->streamEstablished();
             $prettyTime = date('Y-m-d H:i:s', $stats->startTime());
             $logger->info("Twitter responded at {$prettyTime} UTC");
         }
         if ($event === Notify::RESPONSE_BODY_DATA) {
             $data = trim($notifyData[0]);
             if (!empty($data)) {
                 $chunkCombiner->push($data);
                 if ($chunkCombiner->isValidJson()) {
                     // TODO pass $json to Storage when implemented
                     $json = $chunkCombiner->getCombinedChunksAsJson();
                     $chunkCombiner->clearChunks();
                     $stats->increment('statusUpdates');
                 }
             }
         }
     };
     $promise->watch($callback);
     $promise->when(function ($err, $response) use($logger) {
         if ($err) {
             $exceptionType = get_class($err);
             $msg = "{$exceptionType}('{$err->getMessage()}') in {$err->getFile()} on L{$err->getLine()}";
             $logger->critical($msg);
             // TODO if an exception was thrown should decide if we want to stop execution; this should probably not happen in normal circumstances
         } else {
             $msg = "Connection ended: {$response->getStatus()} {$response->getReason()}";
             $logger->error($msg);
         }
         // TODO remove this when we have the reconnection/backoff implemented
         \Amp\stop();
     });
     $statUpdate = function () use($stats) {
         $runningTime = time() - $stats->startTime();
         $this->logger->info("Stats: {$stats->statusUpdates()} statuses. Running for {$runningTime} seconds.");
     };
     $statUpdate = $statUpdate->bindTo($this, $this);
     repeat($statUpdate, 15000);
 }