Example #1
0
 private function connect()
 {
     // If we're in the process of connecting already return that same promise
     if ($this->connectPromisor) {
         return $this->connectPromisor->promise();
     }
     // If a read watcher exists we know we're already connected
     if ($this->readWatcher) {
         return new Success($this);
     }
     $this->state = self::STATE_CONNECTING;
     $this->connectPromisor = new Deferred();
     $socketPromise = connect($this->uri, ["timeout" => $this->timeout]);
     $onWrite = function ($watcherId) {
         if ($this->outputBufferLength === 0) {
             disable($watcherId);
             return;
         }
         $bytes = @fwrite($this->socket, $this->outputBuffer);
         if ($bytes === 0) {
             $this->state = self::STATE_DISCONNECTED;
             $this->onError(new ConnectException("Connection went away (write)", $code = 1));
         } else {
             $this->outputBuffer = (string) substr($this->outputBuffer, $bytes);
             $this->outputBufferLength -= $bytes;
         }
     };
     $socketPromise->when(function ($error, $socket) use($onWrite) {
         $connectPromisor = $this->connectPromisor;
         $this->connectPromisor = null;
         if ($error) {
             $this->state = self::STATE_DISCONNECTED;
             $connectPromisor->fail(new ConnectException("Connection attempt failed", $code = 0, $error));
             return;
         }
         $this->state = self::STATE_CONNECTED;
         $this->socket = $socket;
         foreach ($this->handlers["connect"] as $handler) {
             $pipelinedCommand = $handler();
             if (!empty($pipelinedCommand)) {
                 $this->outputBuffer = $pipelinedCommand . $this->outputBuffer;
                 $this->outputBufferLength += strlen($pipelinedCommand);
             }
         }
         $this->readWatcher = onReadable($this->socket, function () {
             $read = fread($this->socket, 8192);
             if ($read != "") {
                 $this->parser->append($read);
             } elseif (!is_resource($this->socket) || @feof($this->socket)) {
                 $this->state = self::STATE_DISCONNECTED;
                 $this->onError(new ConnectException("Connection went away (read)", $code = 2));
             }
         });
         $this->writeWatcher = onWritable($this->socket, $onWrite, ["enable" => !empty($this->outputBuffer)]);
         $connectPromisor->succeed();
     });
     return $this->connectPromisor->promise();
 }
Example #2
0
 /**
  * @return Promise
  */
 private function connect()
 {
     if ($this->promisor) {
         return $this->promisor->promise();
     }
     // Already connected
     if (is_resource($this->socket)) {
         return new Success();
     }
     $this->promisor = new \Amp\Deferred();
     /** @var $socketPromise Promise */
     $socketPromise = \Amp\Socket\connect($this->uri, ['timeout' => 1000]);
     $socketPromise->when(function ($error, $socket) {
         $promisor = $this->promisor;
         $this->promisor = null;
         $this->socket = $socket;
         $this->reader = \Amp\onReadable($this->socket, [$this, "onRead"]);
         $this->writer = \Amp\onWritable($this->socket, [$this, "onWrite"]);
         $promisor->succeed();
     });
     return $this->promisor->promise();
 }
Example #3
0
 /**
  * @param string $uri
  * @param array  $options
  */
 public function __construct($uri, array $options = null)
 {
     if (is_array($options) || func_num_args() === 2) {
         trigger_error("Using the options array is deprecated and will be removed in the next version. " . "Please use the URI to pass options like that: tcp://localhost:6379?database=3&password=abc", E_USER_DEPRECATED);
         $options = $options ?: [];
         if (isset($options["password"])) {
             $this->password = $options["password"];
         }
     }
     $this->applyUri($uri);
     $this->promisors = [];
     $this->patternPromisors = [];
     $this->connection = new Connection($this->uri);
     $this->connection->addEventHandler("response", function ($response) {
         if ($this->authPromisor) {
             if ($response instanceof Exception) {
                 $this->authPromisor->fail($response);
             } else {
                 $this->authPromisor->succeed($response);
             }
             $this->authPromisor = null;
             return;
         }
         switch ($response[0]) {
             case "message":
                 foreach ($this->promisors[$response[1]] as $promisor) {
                     $promisor->update($response[2]);
                 }
                 break;
             case "pmessage":
                 foreach ($this->patternPromisors[$response[1]] as $promisor) {
                     $promisor->update([$response[3], $response[2]]);
                 }
                 break;
             case "unsubscribe":
                 if ($response[1] === null) {
                     break;
                 }
                 foreach ($this->promisors[$response[1]] as $promisor) {
                     $promisor->succeed();
                 }
                 break;
             case "punsubscribe":
                 if ($response[1] === null) {
                     break;
                 }
                 foreach ($this->patternPromisors[$response[1]] as $promisor) {
                     $promisor->succeed();
                 }
                 break;
             default:
                 break;
         }
     });
     $this->connection->addEventHandler("error", function ($error) {
         if ($error) {
             // Fail any outstanding promises
             if ($this->authPromisor) {
                 $this->authPromisor->fail($error);
             }
             while ($this->promisors) {
                 $promisorGroup = array_shift($this->promisors);
                 while ($promisorGroup) {
                     $promisor = array_shift($promisorGroup);
                     $promisor->fail($error);
                 }
             }
             while ($this->patternPromisors) {
                 $promisorGroup = array_shift($this->patternPromisors);
                 while ($promisorGroup) {
                     $promisor = array_shift($promisorGroup);
                     $promisor->fail($error);
                 }
             }
         }
     });
     if (!empty($this->password)) {
         $this->connection->addEventHandler("connect", function () {
             // AUTH must be before any other command, so we unshift it here
             $this->authPromisor = new Deferred();
             return "*2\r\n\$4\r\rAUTH\r\n\$" . strlen($this->password) . "\r\n{$this->password}\r\n";
         });
     }
 }