From 82d25240891c0fedc95d6fb6da0373babd4b5eef Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Tue, 27 Jun 2017 18:04:29 +0300 Subject: [PATCH 01/11] Add gearman transport. --- bin/test | 1 + composer.json | 5 + docker-compose.yml | 5 + docker/Dockerfile | 7 +- docker/php/cli.ini | 2 - phpunit.xml.dist | 4 + pkg/enqueue/functions.php | 10 + pkg/gearman/.travis.yml | 21 ++ pkg/gearman/GearmanConnectionFactory.php | 94 ++++++ pkg/gearman/GearmanConsumer.php | 97 ++++++ pkg/gearman/GearmanContext.php | 128 ++++++++ pkg/gearman/GearmanDestination.php | 46 +++ pkg/gearman/GearmanMessage.php | 304 ++++++++++++++++++ pkg/gearman/GearmanProducer.php | 44 +++ pkg/gearman/LICENSE | 20 ++ pkg/gearman/README.md | 26 ++ .../Spec/GearmanConnectionFactoryTest.php | 17 + pkg/gearman/Tests/Spec/GearmanContextTest.php | 20 ++ pkg/gearman/Tests/Spec/GearmanMessageTest.php | 17 + pkg/gearman/Tests/Spec/GearmanQueueTest.php | 17 + .../GearmanSendToAndReceiveFromQueueTest.php | 34 ++ ...manSendToAndReceiveNoWaitFromQueueTest.php | 30 ++ ...rmanSendToTopicAndReceiveFromQueueTest.php | 45 +++ ...ndToTopicAndReceiveNoWaitFromQueueTest.php | 45 +++ pkg/gearman/Tests/Spec/GearmanTopicTest.php | 17 + pkg/gearman/composer.json | 41 +++ pkg/pheanstalk/PheanstalkMessage.php | 2 +- 27 files changed, 1092 insertions(+), 7 deletions(-) create mode 100644 pkg/gearman/.travis.yml create mode 100644 pkg/gearman/GearmanConnectionFactory.php create mode 100644 pkg/gearman/GearmanConsumer.php create mode 100644 pkg/gearman/GearmanContext.php create mode 100644 pkg/gearman/GearmanDestination.php create mode 100644 pkg/gearman/GearmanMessage.php create mode 100644 pkg/gearman/GearmanProducer.php create mode 100644 pkg/gearman/LICENSE create mode 100644 pkg/gearman/README.md create mode 100644 pkg/gearman/Tests/Spec/GearmanConnectionFactoryTest.php create mode 100644 pkg/gearman/Tests/Spec/GearmanContextTest.php create mode 100644 pkg/gearman/Tests/Spec/GearmanMessageTest.php create mode 100644 pkg/gearman/Tests/Spec/GearmanQueueTest.php create mode 100644 pkg/gearman/Tests/Spec/GearmanSendToAndReceiveFromQueueTest.php create mode 100644 pkg/gearman/Tests/Spec/GearmanSendToAndReceiveNoWaitFromQueueTest.php create mode 100644 pkg/gearman/Tests/Spec/GearmanSendToTopicAndReceiveFromQueueTest.php create mode 100644 pkg/gearman/Tests/Spec/GearmanSendToTopicAndReceiveNoWaitFromQueueTest.php create mode 100644 pkg/gearman/Tests/Spec/GearmanTopicTest.php create mode 100644 pkg/gearman/composer.json diff --git a/bin/test b/bin/test index c3d2930bb..bcee4d6e7 100755 --- a/bin/test +++ b/bin/test @@ -24,6 +24,7 @@ waitForService rabbitmq 5672 50 waitForService mysql 3306 50 waitForService redis 6379 50 waitForService beanstalkd 11300 +waitForService gearmand 4730 php pkg/job-queue/Tests/Functional/app/console doctrine:database:create php pkg/job-queue/Tests/Functional/app/console doctrine:schema:update --force diff --git a/composer.json b/composer.json index 5cc11dfd3..1c557ec8c 100644 --- a/composer.json +++ b/composer.json @@ -14,6 +14,7 @@ "enqueue/dbal": "*@dev", "enqueue/sqs": "*@dev", "enqueue/pheanstalk": "*@dev", + "enqueue/gearman": "*@dev", "enqueue/enqueue-bundle": "*@dev", "enqueue/job-queue": "*@dev", "enqueue/simple-client": "*@dev", @@ -90,6 +91,10 @@ "type": "path", "url": "pkg/pheanstalk" }, + { + "type": "path", + "url": "pkg/gearman" + }, { "type": "path", "url": "pkg/simple-client" diff --git a/docker-compose.yml b/docker-compose.yml index fba4ac60f..dacec14aa 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,6 +9,7 @@ services: - mysql - redis - beanstalkd + - gearmand volumes: - './:/mqdev' environment: @@ -34,6 +35,7 @@ services: - BEANSTALKD_HOST=beanstalkd - BEANSTALKD_PORT=11300 - BEANSTALKD_DSN=beanstalk://beanstalkd:11300 + - GEARMAN_DSN=gearman://gearmand:4730 rabbitmq: image: enqueue/rabbitmq:latest @@ -48,6 +50,9 @@ services: beanstalkd: image: 'schickling/beanstalkd' + gearmand: + image: 'artefactual/gearmand' + redis: image: 'redis:3' ports: diff --git a/docker/Dockerfile b/docker/Dockerfile index 531ff8016..a7c4258b7 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,16 +1,15 @@ -FROM ubuntu:16.04 +FROM formapro/nginx-php-fpm:latest-all-exts ## libs RUN set -x && \ apt-get update && \ - apt-get install -y --no-install-recommends wget curl openssl ca-certificates nano netcat && \ - apt-get install -y --no-install-recommends php php-mysql php-redis php-curl php-intl php-mbstring php-zip php-mcrypt php-xdebug php-bcmath php-xml php-amqp + apt-get install -y --no-install-recommends wget curl openssl ca-certificates nano netcat ## confis # RUN rm -f /etc/php/7.0/cli/conf.d/*xdebug.ini -COPY ./php/cli.ini /etc/php/7.0/cli/conf.d/1-dev_cli.ini +COPY ./php/cli.ini /etc/php/7.1/cli/conf.d/1-dev_cli.ini COPY ./bin/dev_entrypoiny.sh /usr/local/bin/entrypoint.sh RUN chmod u+x /usr/local/bin/entrypoint.sh diff --git a/docker/php/cli.ini b/docker/php/cli.ini index 3154c04a4..e308fbb9d 100644 --- a/docker/php/cli.ini +++ b/docker/php/cli.ini @@ -4,5 +4,3 @@ memory_limit = 2G max_execution_time=0 date.timezone=UTC variables_order="EGPCS" - -extension=amqp.so \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 420daae7f..e5d73f068 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -53,6 +53,10 @@ pkg/pheanstalk/Tests + + pkg/gearman/Tests + + pkg/enqueue-bundle/Tests diff --git a/pkg/enqueue/functions.php b/pkg/enqueue/functions.php index aa76c57a6..770fe0df7 100644 --- a/pkg/enqueue/functions.php +++ b/pkg/enqueue/functions.php @@ -6,7 +6,9 @@ use Enqueue\Consumption\QueueConsumer; use Enqueue\Dbal\DbalConnectionFactory; use Enqueue\Fs\FsConnectionFactory; +use Enqueue\Gearman\GearmanConnectionFactory; use Enqueue\Null\NullConnectionFactory; +use Enqueue\Pheanstalk\PheanstalkConnectionFactory; use Enqueue\Psr\PsrConnectionFactory; use Enqueue\Psr\PsrContext; @@ -48,6 +50,14 @@ function dsn_to_connection_factory($dsn) $map['pdo_sqlite'] = DbalConnectionFactory::class; } + if (class_exists(GearmanConnectionFactory::class)) { + $map['gearman'] = GearmanConnectionFactory::class; + } + + if (class_exists(PheanstalkConnectionFactory::class)) { + $map['beanstalk'] = PheanstalkConnectionFactory::class; + } + list($scheme) = explode('://', $dsn); if (false == $scheme || false === strpos($dsn, '://')) { throw new \LogicException(sprintf('The scheme could not be parsed from DSN "%s"', $dsn)); diff --git a/pkg/gearman/.travis.yml b/pkg/gearman/.travis.yml new file mode 100644 index 000000000..42374ddc7 --- /dev/null +++ b/pkg/gearman/.travis.yml @@ -0,0 +1,21 @@ +sudo: false + +git: + depth: 1 + +language: php + +php: + - '5.6' + - '7.0' + +cache: + directories: + - $HOME/.composer/cache + +install: + - composer self-update + - composer install --prefer-source + +script: + - vendor/bin/phpunit --exclude-group=functional diff --git a/pkg/gearman/GearmanConnectionFactory.php b/pkg/gearman/GearmanConnectionFactory.php new file mode 100644 index 000000000..db0e9c37f --- /dev/null +++ b/pkg/gearman/GearmanConnectionFactory.php @@ -0,0 +1,94 @@ + 'localhost', + * 'port' => 11300 + * ] + * + * or + * + * gearman://host:port + * + * @param array|string $config + */ + public function __construct($config = 'gearman://') + { + if (empty($config) || 'gearman://' === $config) { + $config = []; + } elseif (is_string($config)) { + $config = $this->parseDsn($config); + } elseif (is_array($config)) { + } else { + throw new \LogicException('The config must be either an array of options, a DSN string or null'); + } + + $this->config = array_replace($this->defaultConfig(), $config); + } + + /** + * {@inheritdoc} + * + * @return GearmanContext + */ + public function createContext() + { + return new GearmanContext($this->config); + } + + /** + * @param string $dsn + * + * @return array + */ + private function parseDsn($dsn) + { + $dsnConfig = parse_url(https://github.com/$dsn); + if (false === $dsnConfig) { + throw new \LogicException(sprintf('Failed to parse DSN "%s"', $dsn)); + } + + $dsnConfig = array_replace([ + 'scheme' => null, + 'host' => null, + 'port' => null, + 'user' => null, + 'pass' => null, + 'path' => null, + 'query' => null, + ], $dsnConfig); + + if ('gearman' !== $dsnConfig['scheme']) { + throw new \LogicException(sprintf('The given DSN scheme "%s" is not supported. Could be "gearman" only.', $dsnConfig['scheme'])); + } + + return [ + 'port' => $dsnConfig['port'], + 'host' => $dsnConfig['host'], + ]; + } + + /** + * @return array + */ + private function defaultConfig() + { + return [ + 'host' => \GEARMAN_DEFAULT_TCP_HOST, + 'port' => \GEARMAN_DEFAULT_TCP_PORT, + ]; + } +} diff --git a/pkg/gearman/GearmanConsumer.php b/pkg/gearman/GearmanConsumer.php new file mode 100644 index 000000000..745561653 --- /dev/null +++ b/pkg/gearman/GearmanConsumer.php @@ -0,0 +1,97 @@ +worker = $worker; + $this->destination = $destination; + } + + /** + * {@inheritdoc} + * + * @return GearmanDestination + */ + public function getQueue() + { + return $this->destination; + } + + /** + * {@inheritdoc} + * + * @return GearmanMessage + */ + public function receive($timeout = 0) + { + set_error_handler(function ($severity, $message, $file, $line) { + throw new \ErrorException($message, 0, $severity, $file, $line); + }); + + $this->worker->setTimeout($timeout); + + try { + $message = null; + + $this->worker->addFunction($this->destination->getName(), function (\GearmanJob $job) use (&$message) { + $message = GearmanMessage::jsonUnserialize($job->workload()); + }); + + while ($this->worker->work()); + } finally { + restore_error_handler(); + } + + return $message; + } + + /** + * {@inheritdoc} + */ + public function receiveNoWait() + { + return $this->receive(100); + } + + /** + * {@inheritdoc} + */ + public function acknowledge(PsrMessage $message) + { + } + + /** + * {@inheritdoc} + */ + public function reject(PsrMessage $message, $requeue = false) + { + } + + /** + * @return \GearmanWorker + */ + public function getWorker() + { + return $this->worker; + } +} diff --git a/pkg/gearman/GearmanContext.php b/pkg/gearman/GearmanContext.php new file mode 100644 index 000000000..a7434b8d1 --- /dev/null +++ b/pkg/gearman/GearmanContext.php @@ -0,0 +1,128 @@ +config = $config; + } + + /** + * {@inheritdoc} + * + * @return GearmanMessage + */ + public function createMessage($body = '', array $properties = [], array $headers = []) + { + return new GearmanMessage($body, $properties, $headers); + } + + /** + * {@inheritdoc} + * + * @return GearmanDestination + */ + public function createTopic($topicName) + { + return new GearmanDestination($topicName); + } + + /** + * {@inheritdoc} + */ + public function createQueue($queueName) + { + return new GearmanDestination($queueName); + } + + /** + * {@inheritdoc} + */ + public function createTemporaryQueue() + { + throw new \LogicException('Not implemented'); + } + + /** + * {@inheritdoc} + * + * @return GearmanProducer + */ + public function createProducer() + { + return new GearmanProducer($this->getClient()); + } + + /** + * {@inheritdoc} + * + * @param GearmanDestination $destination + * + * @return GearmanConsumer + */ + public function createConsumer(PsrDestination $destination) + { + InvalidDestinationException::assertDestinationInstanceOf($destination, GearmanDestination::class); + + $this->consumers[] = $consumer = new GearmanConsumer($this->createWorker(), $destination); + + return $consumer; + } + + public function close() + { + $this->getClient()->clearCallbacks(); + + foreach ($this->consumers as $consumer) { + $consumer->getWorker()->unregisterAll(); + } + } + + /** + * @return \GearmanClient + */ + public function getClient() + { + if (false == $this->client) { + $this->client = new \GearmanClient(); + $this->client->addServer($this->config['host'], $this->config['port']); + } + + return $this->client; + } + + /** + * @return \GearmanWorker + */ + public function createWorker() + { + $worker = new \GearmanWorker(); + $worker->addServer($this->config['host'], $this->config['port']); + + return $worker; + } +} diff --git a/pkg/gearman/GearmanDestination.php b/pkg/gearman/GearmanDestination.php new file mode 100644 index 000000000..557312d2b --- /dev/null +++ b/pkg/gearman/GearmanDestination.php @@ -0,0 +1,46 @@ +destinationName = $destinationName; + } + + /** + * @return string + */ + public function getName() + { + return $this->destinationName; + } + + /** + * {@inheritdoc} + */ + public function getQueueName() + { + return $this->getName(); + } + + /** + * {@inheritdoc} + */ + public function getTopicName() + { + return $this->getName(); + } +} diff --git a/pkg/gearman/GearmanMessage.php b/pkg/gearman/GearmanMessage.php new file mode 100644 index 000000000..8f2aa1a85 --- /dev/null +++ b/pkg/gearman/GearmanMessage.php @@ -0,0 +1,304 @@ +body = $body; + $this->properties = $properties; + $this->headers = $headers; + $this->redelivered = false; + } + + /** + * @param string $body + */ + public function setBody($body) + { + $this->body = $body; + } + + /** + * {@inheritdoc} + */ + public function getBody() + { + return $this->body; + } + + /** + * @param array $properties + */ + public function setProperties(array $properties) + { + $this->properties = $properties; + } + + /** + * {@inheritdoc} + */ + public function getProperties() + { + return $this->properties; + } + + /** + * {@inheritdoc} + */ + public function setProperty($name, $value) + { + $this->properties[$name] = $value; + } + + /** + * {@inheritdoc} + */ + public function getProperty($name, $default = null) + { + return array_key_exists($name, $this->properties) ? $this->properties[$name] : $default; + } + + /** + * @param array $headers + */ + public function setHeaders(array $headers) + { + $this->headers = $headers; + } + + /** + * {@inheritdoc} + */ + public function getHeaders() + { + return $this->headers; + } + + /** + * {@inheritdoc} + */ + public function setHeader($name, $value) + { + $this->headers[$name] = $value; + } + + /** + * {@inheritdoc} + */ + public function getHeader($name, $default = null) + { + return array_key_exists($name, $this->headers) ? $this->headers[$name] : $default; + } + + /** + * @return bool + */ + public function isRedelivered() + { + return $this->redelivered; + } + + /** + * @param bool $redelivered + */ + public function setRedelivered($redelivered) + { + $this->redelivered = $redelivered; + } + + /** + * {@inheritdoc} + */ + public function setCorrelationId($correlationId) + { + $this->setHeader('correlation_id', (string) $correlationId); + } + + /** + * {@inheritdoc} + */ + public function getCorrelationId() + { + return $this->getHeader('correlation_id'); + } + + /** + * {@inheritdoc} + */ + public function setMessageId($messageId) + { + $this->setHeader('message_id', (string) $messageId); + } + + /** + * {@inheritdoc} + */ + public function getMessageId() + { + return $this->getHeader('message_id'); + } + + /** + * {@inheritdoc} + */ + public function getTimestamp() + { + $value = $this->getHeader('timestamp'); + + return $value === null ? null : (int) $value; + } + + /** + * {@inheritdoc} + */ + public function setTimestamp($timestamp) + { + $this->setHeader('timestamp', $timestamp); + } + + /** + * @param string|null $replyTo + */ + public function setReplyTo($replyTo) + { + $this->setHeader('reply_to', $replyTo); + } + + /** + * @return string|null + */ + public function getReplyTo() + { + return $this->getHeader('reply_to'); + } + + /** + * @param int $time + */ + public function setTimeToRun($time) + { + $this->setHeader('ttr', $time); + } + + /** + * @return int + */ + public function getTimeToRun() + { + return $this->getHeader('ttr', Pheanstalk::DEFAULT_TTR); + } + + /** + * @param int $priority + */ + public function setPriority($priority) + { + $this->setHeader('priority', $priority); + } + + /** + * @return int + */ + public function getPriority() + { + return $this->getHeader('priority', Pheanstalk::DEFAULT_PRIORITY); + } + + /** + * @param int $delay + */ + public function setDelay($delay) + { + $this->setHeader('delay', $delay); + } + + /** + * @return int + */ + public function getDelay() + { + return $this->getHeader('delay', Pheanstalk::DEFAULT_DELAY); + } + + /** + * {@inheritdoc} + */ + public function jsonSerialize() + { + return [ + 'body' => $this->getBody(), + 'properties' => $this->getProperties(), + 'headers' => $this->getHeaders(), + ]; + } + + /** + * @param string $json + * + * @return self + */ + public static function jsonUnserialize($json) + { + $data = json_decode($json, true); + if (JSON_ERROR_NONE !== json_last_error()) { + throw new \InvalidArgumentException(sprintf( + 'The malformed json given. Error %s and message %s', + json_last_error(), + json_last_error_msg() + )); + } + + return new self($data['body'], $data['properties'], $data['headers']); + } + +// /** +// * @return \GearmanJob +// */ +// public function getJob() +// { +// return $this->job; +// } +// +// /** +// * @param \GearmanJob $job +// */ +// public function setJob(\GearmanJob $job) +// { +// $this->job = $job; +// } +} diff --git a/pkg/gearman/GearmanProducer.php b/pkg/gearman/GearmanProducer.php new file mode 100644 index 000000000..d6340e1db --- /dev/null +++ b/pkg/gearman/GearmanProducer.php @@ -0,0 +1,44 @@ +client = $client; + } + + /** + * {@inheritdoc} + * + * @param GearmanDestination $destination + * @param GearmanMessage $message + */ + public function send(PsrDestination $destination, PsrMessage $message) + { + InvalidDestinationException::assertDestinationInstanceOf($destination, GearmanDestination::class); + InvalidMessageException::assertMessageInstanceOf($message, GearmanMessage::class); + + $this->client->doBackground($destination->getName(), json_encode($message)); + + $code = $this->client->returnCode(); + if (\GEARMAN_SUCCESS !== $code) { + throw new \GearmanException(sprintf('The return code is not %s (GEARMAN_SUCCESS) but %s', \GEARMAN_SUCCESS, $code)); + } + } +} diff --git a/pkg/gearman/LICENSE b/pkg/gearman/LICENSE new file mode 100644 index 000000000..d9736f8bf --- /dev/null +++ b/pkg/gearman/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) +Copyright (c) 2017 Kotliar Maksym + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/pkg/gearman/README.md b/pkg/gearman/README.md new file mode 100644 index 000000000..55cdc2bab --- /dev/null +++ b/pkg/gearman/README.md @@ -0,0 +1,26 @@ +# Gearman Transport + +[![Gitter](https://badges.gitter.im/php-enqueue/Lobby.svg)](https://gitter.im/php-enqueue/Lobby) +[![Build Status](https://travis-ci.org/php-enqueue/gearman.png?branch=master)](https://travis-ci.org/php-enqueue/gearman) +[![Total Downloads](https://poser.pugx.org/enqueue/gearman/d/total.png)](https://packagist.org/packages/enqueue/gearman) +[![Latest Stable Version](https://poser.pugx.org/enqueue/gearman/version.png)](https://packagist.org/packages/enqueue/gearman) + +This is an implementation of the queue specification. It allows you to send and consume message from Gearman broker. + +## Resources + +* [Documentation](https://github.com/php-enqueue/enqueue-dev/blob/master/docs/index.md) +* [Questions](https://gitter.im/php-enqueue/Lobby) +* [Issue Tracker](https://github.com/php-enqueue/enqueue-dev/issues) + +## Developed by Forma-Pro + +Forma-Pro is a full stack development company which interests also spread to open source development. +Being a team of strong professionals we have an aim an ability to help community by developing cutting edge solutions in the areas of e-commerce, docker & microservice oriented architecture where we have accumulated a huge many-years experience. +Our main specialization is Symfony framework based solution, but we are always looking to the technologies that allow us to do our job the best way. We are committed to creating solutions that revolutionize the way how things are developed in aspects of architecture & scalability. + +If you have any questions and inquires about our open source development, this product particularly or any other matter feel free to contact at opensource@forma-pro.com + +## License + +It is released under the [MIT License](LICENSE). \ No newline at end of file diff --git a/pkg/gearman/Tests/Spec/GearmanConnectionFactoryTest.php b/pkg/gearman/Tests/Spec/GearmanConnectionFactoryTest.php new file mode 100644 index 000000000..fdfc1b911 --- /dev/null +++ b/pkg/gearman/Tests/Spec/GearmanConnectionFactoryTest.php @@ -0,0 +1,17 @@ +createContext(); + } +} diff --git a/pkg/gearman/Tests/Spec/GearmanMessageTest.php b/pkg/gearman/Tests/Spec/GearmanMessageTest.php new file mode 100644 index 000000000..7149faa28 --- /dev/null +++ b/pkg/gearman/Tests/Spec/GearmanMessageTest.php @@ -0,0 +1,17 @@ +createContext(); + } + + /** + * @param PsrContext $context + * @param string $queueName + * + * @return PsrQueue + */ + protected function createQueue(PsrContext $context, $queueName) + { + return $context->createQueue($queueName.time()); + } +} diff --git a/pkg/gearman/Tests/Spec/GearmanSendToAndReceiveNoWaitFromQueueTest.php b/pkg/gearman/Tests/Spec/GearmanSendToAndReceiveNoWaitFromQueueTest.php new file mode 100644 index 000000000..8eb94429c --- /dev/null +++ b/pkg/gearman/Tests/Spec/GearmanSendToAndReceiveNoWaitFromQueueTest.php @@ -0,0 +1,30 @@ +createContext(); + } + + /** + * {@inheritdoc} + */ + protected function createQueue(PsrContext $context, $queueName) + { + return $context->createQueue($queueName.time()); + } +} diff --git a/pkg/gearman/Tests/Spec/GearmanSendToTopicAndReceiveFromQueueTest.php b/pkg/gearman/Tests/Spec/GearmanSendToTopicAndReceiveFromQueueTest.php new file mode 100644 index 000000000..daabaa962 --- /dev/null +++ b/pkg/gearman/Tests/Spec/GearmanSendToTopicAndReceiveFromQueueTest.php @@ -0,0 +1,45 @@ +time = time(); + } + + /** + * {@inheritdoc} + */ + protected function createContext() + { + $factory = new GearmanConnectionFactory(getenv('GEARMAN_DSN')); + + return $factory->createContext(); + } + + /** + * {@inheritdoc} + */ + protected function createQueue(PsrContext $context, $queueName) + { + return $context->createQueue($queueName.$this->time); + } + + /** + * {@inheritdoc} + */ + protected function createTopic(PsrContext $context, $topicName) + { + return $context->createTopic($topicName.$this->time); + } +} diff --git a/pkg/gearman/Tests/Spec/GearmanSendToTopicAndReceiveNoWaitFromQueueTest.php b/pkg/gearman/Tests/Spec/GearmanSendToTopicAndReceiveNoWaitFromQueueTest.php new file mode 100644 index 000000000..a47e0d2c6 --- /dev/null +++ b/pkg/gearman/Tests/Spec/GearmanSendToTopicAndReceiveNoWaitFromQueueTest.php @@ -0,0 +1,45 @@ +time = time(); + } + + /** + * {@inheritdoc} + */ + protected function createContext() + { + $factory = new GearmanConnectionFactory(getenv('GEARMAN_DSN')); + + return $factory->createContext(); + } + + /** + * {@inheritdoc} + */ + protected function createQueue(PsrContext $context, $queueName) + { + return $context->createQueue($queueName.$this->time); + } + + /** + * {@inheritdoc} + */ + protected function createTopic(PsrContext $context, $topicName) + { + return $context->createTopic($topicName.$this->time); + } +} diff --git a/pkg/gearman/Tests/Spec/GearmanTopicTest.php b/pkg/gearman/Tests/Spec/GearmanTopicTest.php new file mode 100644 index 000000000..21c7c6802 --- /dev/null +++ b/pkg/gearman/Tests/Spec/GearmanTopicTest.php @@ -0,0 +1,17 @@ +=5.6", + "ext-gearman": "^1.1", + "enqueue/psr-queue": "^0.5@dev" + }, + "require-dev": { + "phpunit/phpunit": "~5.4.0", + "enqueue/test": "^0.5@dev", + "enqueue/enqueue": "^0.5@dev", + "enqueue/null": "^0.5@dev", + "symfony/dependency-injection": "^2.8|^3", + "symfony/config": "^2.8|^3" + }, + "autoload": { + "psr-4": { "Enqueue\\Gearman\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "suggest": { + "enqueue/enqueue": "If you'd like to use advanced features like Client abstract layer or Symfony integration features" + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "0.5.x-dev" + } + } +} diff --git a/pkg/pheanstalk/PheanstalkMessage.php b/pkg/pheanstalk/PheanstalkMessage.php index 2ce6d0685..f1709ac7a 100644 --- a/pkg/pheanstalk/PheanstalkMessage.php +++ b/pkg/pheanstalk/PheanstalkMessage.php @@ -271,7 +271,7 @@ public function jsonSerialize() /** * @param string $json * - * @return PheanstalkMessage + * @return self */ public static function jsonUnserialize($json) { From 4bc8ecf8d891c7a7b5348dda370585cf6942d3c6 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Tue, 27 Jun 2017 18:11:38 +0300 Subject: [PATCH 02/11] [gearman] Add docs --- README.md | 2 +- docs/transport/gearman.md | 84 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 docs/transport/gearman.md diff --git a/README.md b/README.md index 5543efb70..4fd2345f5 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Features: * [Feature rich](docs/quick_tour.md). * [JMS](https://docs.oracle.com/javaee/7/api/javax/jms/package-summary.html) like transport [abstraction](https://github.com/php-enqueue/psr-queue). -* Supports transports [AMQP (RabbitMQ, ActiveMQ)](docs/transport/amqp.md), [Beanstalk (Pheanstalk)](docs/transport/pheanstalk.md), [STOMP](docs/transport/stomp.md), [Amazon SQS](docs/transport/sqs.md), [Redis](docs/transport/redis.md), [Doctrine DBAL](docs/transport/dbal.md), [Filesystem](docs/transport/filesystem.md), [Null](docs/transport/null.md). +* Supported transports [AMQP](docs/transport/amqp.md) (RabbitMQ, ActiveMQ), [Beanstalk](docs/transport/pheanstalk.md), [STOMP](docs/transport/stomp.md), [Amazon SQS](docs/transport/sqs.md), [Redis](docs/transport/redis.md), [Gearman](docs/transport/gearman.md), [Doctrine DBAL](docs/transport/dbal.md), [Filesystem](docs/transport/filesystem.md), [Null](docs/transport/null.md). * [Symfony bundle](https://github.com/php-enqueue/enqueue-dev/blob/master/docs/bundle/quick_tour.md) * [Magento1 extension](https://github.com/php-enqueue/enqueue-dev/blob/master/docs/magento/quick_tour.md) * [Message bus](http://www.enterpriseintegrationpatterns.com/patterns/messaging/MessageBus.html) support. diff --git a/docs/transport/gearman.md b/docs/transport/gearman.md new file mode 100644 index 000000000..01bb3a11e --- /dev/null +++ b/docs/transport/gearman.md @@ -0,0 +1,84 @@ +# Gearman (Gearman) transport + +The transport uses [Gearman](http://gearman.org/) job manager. +The transport uses [Gearman PHP extension](http://php.net/manual/en/book.gearman.php) internally. + +* [Installation](#installation) +* [Create context](#create-context) +* [Send message to topic](#send-message-to-topic) +* [Send message to queue](#send-message-to-queue) +* [Consume message](#consume-message) + +## Installation + +```bash +$ composer require enqueue/gearman +``` + + +## Create context + +```php + 'example', + 'port' => 5555 +]); +``` + +## Send message to topic + +```php +createTopic('aTopic'); +$message = $psrContext->createMessage('Hello world!'); + +$psrContext->createProducer()->send($fooTopic, $message); +``` + +## Send message to queue + +```php +createQueue('aQueue'); +$message = $psrContext->createMessage('Hello world!'); + +$psrContext->createProducer()->send($fooQueue, $message); +``` + +## Consume message: + +```php +createQueue('aQueue'); +$consumer = $psrContext->createConsumer($fooQueue); + +$message = $consumer->receive(2000); // wait for 2 seconds + +$message = $consumer->receiveNoWait(); // fetch message or return null immediately + +// process a message + +$consumer->acknowledge($message); +// $consumer->reject($message); +``` + +[back to index](../index.md) \ No newline at end of file From 85c81b11afc348e08024c7963f7cfa65fc77b674 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Tue, 27 Jun 2017 18:11:56 +0300 Subject: [PATCH 03/11] [gearman] Add requeue support. --- pkg/gearman/GearmanConsumer.php | 18 +++++++++++++++--- pkg/gearman/GearmanContext.php | 2 +- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/pkg/gearman/GearmanConsumer.php b/pkg/gearman/GearmanConsumer.php index 745561653..9a59b6cd1 100644 --- a/pkg/gearman/GearmanConsumer.php +++ b/pkg/gearman/GearmanConsumer.php @@ -18,13 +18,22 @@ class GearmanConsumer implements PsrConsumer private $destination; /** - * @param \GearmanWorker $worker + * @var GearmanContext + */ + private $context; + + /** + * @param GearmanContext $context * @param GearmanDestination $destination + * + * @internal param \GearmanWorker $worker */ - public function __construct(\GearmanWorker $worker, GearmanDestination $destination) + public function __construct(GearmanContext $context, GearmanDestination $destination) { - $this->worker = $worker; + $this->context = $context; $this->destination = $destination; + + $this->worker = $context->createWorker(); } /** @@ -85,6 +94,9 @@ public function acknowledge(PsrMessage $message) */ public function reject(PsrMessage $message, $requeue = false) { + if ($requeue) { + $this->context->createProducer()->send($this->destination, $message); + } } /** diff --git a/pkg/gearman/GearmanContext.php b/pkg/gearman/GearmanContext.php index a7434b8d1..c751921d3 100644 --- a/pkg/gearman/GearmanContext.php +++ b/pkg/gearman/GearmanContext.php @@ -88,7 +88,7 @@ public function createConsumer(PsrDestination $destination) { InvalidDestinationException::assertDestinationInstanceOf($destination, GearmanDestination::class); - $this->consumers[] = $consumer = new GearmanConsumer($this->createWorker(), $destination); + $this->consumers[] = $consumer = new GearmanConsumer($this, $destination); return $consumer; } From 93c2e84d6d426ab49fa3a221b49a798dd59429c1 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Tue, 27 Jun 2017 18:39:37 +0300 Subject: [PATCH 04/11] [gearman] add tests. --- docs/transport/gearman.md | 2 +- pkg/gearman/GearmanMessage.php | 38 +++---- .../GearmanConnectionFactoryConfigTest.php | 103 ++++++++++++++++++ pkg/gearman/Tests/GearmanContextTest.php | 42 +++++++ pkg/gearman/Tests/GearmanDestinationTest.php | 31 ++++++ pkg/gearman/Tests/GearmanMessageTest.php | 22 ++++ pkg/gearman/Tests/GearmanProducerTest.php | 76 +++++++++++++ .../PheanstalkConnectionFactoryConfigTest.php | 2 - .../Tests/PheanstalkDestinationTest.php | 4 +- 9 files changed, 296 insertions(+), 24 deletions(-) create mode 100644 pkg/gearman/Tests/GearmanConnectionFactoryConfigTest.php create mode 100644 pkg/gearman/Tests/GearmanContextTest.php create mode 100644 pkg/gearman/Tests/GearmanDestinationTest.php create mode 100644 pkg/gearman/Tests/GearmanMessageTest.php create mode 100644 pkg/gearman/Tests/GearmanProducerTest.php diff --git a/docs/transport/gearman.md b/docs/transport/gearman.md index 01bb3a11e..a9dc0dc24 100644 --- a/docs/transport/gearman.md +++ b/docs/transport/gearman.md @@ -1,4 +1,4 @@ -# Gearman (Gearman) transport +# Gearman transport The transport uses [Gearman](http://gearman.org/) job manager. The transport uses [Gearman PHP extension](http://php.net/manual/en/book.gearman.php) internally. diff --git a/pkg/gearman/GearmanMessage.php b/pkg/gearman/GearmanMessage.php index 8f2aa1a85..58ed62774 100644 --- a/pkg/gearman/GearmanMessage.php +++ b/pkg/gearman/GearmanMessage.php @@ -27,10 +27,10 @@ class GearmanMessage implements PsrMessage, \JsonSerializable */ private $redelivered; -// /** -// * @var \GearmanJob -// */ -// private $job; + /** + * @var \GearmanJob + */ + private $job; /** * @param string $body @@ -286,19 +286,19 @@ public static function jsonUnserialize($json) return new self($data['body'], $data['properties'], $data['headers']); } -// /** -// * @return \GearmanJob -// */ -// public function getJob() -// { -// return $this->job; -// } -// -// /** -// * @param \GearmanJob $job -// */ -// public function setJob(\GearmanJob $job) -// { -// $this->job = $job; -// } + /** + * @return \GearmanJob + */ + public function getJob() + { + return $this->job; + } + + /** + * @param \GearmanJob $job + */ + public function setJob(\GearmanJob $job) + { + $this->job = $job; + } } diff --git a/pkg/gearman/Tests/GearmanConnectionFactoryConfigTest.php b/pkg/gearman/Tests/GearmanConnectionFactoryConfigTest.php new file mode 100644 index 000000000..0fc7f7214 --- /dev/null +++ b/pkg/gearman/Tests/GearmanConnectionFactoryConfigTest.php @@ -0,0 +1,103 @@ +expectException(\LogicException::class); + $this->expectExceptionMessage('The config must be either an array of options, a DSN string or null'); + + new GearmanConnectionFactory(new \stdClass()); + } + + public function testThrowIfSchemeIsNotGearmanAmqp() + { + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('The given DSN scheme "http" is not supported. Could be "gearman" only.'); + + new GearmanConnectionFactory('http://example.com/'); + } + + public function testThrowIfDsnCouldNotBeParsed() + { + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Failed to parse DSN "gearman://:@/"'); + + new GearmanConnectionFactory('gearman://:@/'); + } + + /** + * @dataProvider provideConfigs + * + * @param mixed $config + * @param mixed $expectedConfig + */ + public function testShouldParseConfigurationAsExpected($config, $expectedConfig) + { + $factory = new GearmanConnectionFactory($config); + + $this->assertAttributeEquals($expectedConfig, 'config', $factory); + } + + public static function provideConfigs() + { + yield [ + null, + [ + 'host' => \GEARMAN_DEFAULT_TCP_HOST, + 'port' => \GEARMAN_DEFAULT_TCP_PORT, + ], + ]; + + yield [ + 'gearman://', + [ + 'host' => \GEARMAN_DEFAULT_TCP_HOST, + 'port' => \GEARMAN_DEFAULT_TCP_PORT, + ], + ]; + + yield [ + [], + [ + 'host' => \GEARMAN_DEFAULT_TCP_HOST, + 'port' => \GEARMAN_DEFAULT_TCP_PORT, + ], + ]; + + yield [ + 'gearman://theHost:1234', + [ + 'host' => 'theHost', + 'port' => 1234, + ], + ]; + + yield [ + ['host' => 'theHost', 'port' => 1234], + [ + 'host' => 'theHost', + 'port' => 1234, + ], + ]; + + yield [ + ['host' => 'theHost'], + [ + 'host' => 'theHost', + 'port' => \GEARMAN_DEFAULT_TCP_PORT, + ], + ]; + } +} diff --git a/pkg/gearman/Tests/GearmanContextTest.php b/pkg/gearman/Tests/GearmanContextTest.php new file mode 100644 index 000000000..ae778791f --- /dev/null +++ b/pkg/gearman/Tests/GearmanContextTest.php @@ -0,0 +1,42 @@ +assertClassImplements(PsrContext::class, GearmanContext::class); + } + + public function testCouldBeConstructedWithConnectionConfigAsFirstArgument() + { + new GearmanContext(['host' => 'aHost', 'port' => 'aPort']); + } + + public function testThrowNotImplementedOnCreateTemporaryQueue() + { + $context = new GearmanContext(['host' => 'aHost', 'port' => 'aPort']); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Not implemented'); + $context->createTemporaryQueue(); + } + + public function testThrowInvalidDestinationIfInvalidDestinationGivenOnCreateConsumer() + { + $context = new GearmanContext(['host' => 'aHost', 'port' => 'aPort']); + + $this->expectException(InvalidDestinationException::class); + $context->createConsumer(new NullQueue('aQueue')); + } +} diff --git a/pkg/gearman/Tests/GearmanDestinationTest.php b/pkg/gearman/Tests/GearmanDestinationTest.php new file mode 100644 index 000000000..00a75e79f --- /dev/null +++ b/pkg/gearman/Tests/GearmanDestinationTest.php @@ -0,0 +1,31 @@ +assertClassImplements(PsrQueue::class, GearmanDestination::class); + } + + public function testShouldImplementPsrTopicInterface() + { + $this->assertClassImplements(PsrTopic::class, GearmanDestination::class); + } + + public function testShouldAllowGetNameSetInConstructor() + { + $destination = new GearmanDestination('theDestinationName'); + + $this->assertSame('theDestinationName', $destination->getName()); + } +} diff --git a/pkg/gearman/Tests/GearmanMessageTest.php b/pkg/gearman/Tests/GearmanMessageTest.php new file mode 100644 index 000000000..d1a6b8fc6 --- /dev/null +++ b/pkg/gearman/Tests/GearmanMessageTest.php @@ -0,0 +1,22 @@ +setJob($job); + + $this->assertSame($job, $message->getJob()); + } +} diff --git a/pkg/gearman/Tests/GearmanProducerTest.php b/pkg/gearman/Tests/GearmanProducerTest.php new file mode 100644 index 000000000..4b6cf95e8 --- /dev/null +++ b/pkg/gearman/Tests/GearmanProducerTest.php @@ -0,0 +1,76 @@ +createGearmanClientMock()); + } + + public function testThrowIfDestinationInvalid() + { + $producer = new GearmanProducer($this->createGearmanClientMock()); + + $this->expectException(InvalidDestinationException::class); + $this->expectExceptionMessage('The destination must be an instance of Enqueue\Gearman\GearmanDestination but got Enqueue\Null\NullQueue.'); + $producer->send(new NullQueue('aQueue'), new GearmanMessage()); + } + + public function testThrowIfMessageInvalid() + { + $producer = new GearmanProducer($this->createGearmanClientMock()); + + $this->expectException(InvalidMessageException::class); + $this->expectExceptionMessage('The message must be an instance of Enqueue\Gearman\GearmanMessage but it is Enqueue\Null\NullMessage.'); + $producer->send(new GearmanDestination('aQueue'), new NullMessage()); + } + + public function testShouldJsonEncodeMessageAndPutToExpectedTube() + { + $message = new GearmanMessage('theBody', ['foo' => 'fooVal'], ['bar' => 'barVal']); + + $gearman = $this->createGearmanClientMock(); + $gearman + ->expects($this->once()) + ->method('doBackground') + ->with( + 'theQueueName', + '{"body":"theBody","properties":{"foo":"fooVal"},"headers":{"bar":"barVal"}}' + ) + ; + $gearman + ->expects($this->once()) + ->method('returnCode') + ->willReturn(\GEARMAN_SUCCESS) + ; + + $producer = new GearmanProducer($gearman); + + $producer->send( + new GearmanDestination('theQueueName'), + $message + ); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject|\GearmanClient + */ + private function createGearmanClientMock() + { + return $this->createMock(\GearmanClient::class); + } +} diff --git a/pkg/pheanstalk/Tests/PheanstalkConnectionFactoryConfigTest.php b/pkg/pheanstalk/Tests/PheanstalkConnectionFactoryConfigTest.php index 0859a2386..239dae68f 100644 --- a/pkg/pheanstalk/Tests/PheanstalkConnectionFactoryConfigTest.php +++ b/pkg/pheanstalk/Tests/PheanstalkConnectionFactoryConfigTest.php @@ -62,8 +62,6 @@ public static function provideConfigs() ], ]; - // some examples from Appendix A: Examples (https://www.rabbitmq.com/uri-spec.html) - yield [ 'beanstalk://', [ diff --git a/pkg/pheanstalk/Tests/PheanstalkDestinationTest.php b/pkg/pheanstalk/Tests/PheanstalkDestinationTest.php index bd52ef577..c7417fa04 100644 --- a/pkg/pheanstalk/Tests/PheanstalkDestinationTest.php +++ b/pkg/pheanstalk/Tests/PheanstalkDestinationTest.php @@ -24,8 +24,8 @@ public function testShouldImplementPsrTopicInterface() public function testShouldAllowGetNameSetInConstructor() { - $destionation = new PheanstalkDestination('theDestinationName'); + $destination = new PheanstalkDestination('theDestinationName'); - $this->assertSame('theDestinationName', $destionation->getName()); + $this->assertSame('theDestinationName', $destination->getName()); } } From 29a93858d9b0aed87eee3553a49e7a3e70892081 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Tue, 27 Jun 2017 18:49:04 +0300 Subject: [PATCH 05/11] [gearman] Run all tests as func, because it's hard to install php gearman ext on travis. --- pkg/gearman/Tests/GearmanConnectionFactoryConfigTest.php | 2 ++ pkg/gearman/Tests/GearmanContextTest.php | 3 +++ pkg/gearman/Tests/GearmanDestinationTest.php | 3 +++ pkg/gearman/Tests/GearmanMessageTest.php | 3 +++ pkg/gearman/Tests/GearmanProducerTest.php | 3 +++ pkg/gearman/Tests/Spec/GearmanConnectionFactoryTest.php | 3 +++ pkg/gearman/Tests/Spec/GearmanMessageTest.php | 3 +++ pkg/gearman/Tests/Spec/GearmanQueueTest.php | 3 +++ pkg/gearman/Tests/Spec/GearmanTopicTest.php | 3 +++ 9 files changed, 26 insertions(+) diff --git a/pkg/gearman/Tests/GearmanConnectionFactoryConfigTest.php b/pkg/gearman/Tests/GearmanConnectionFactoryConfigTest.php index 0fc7f7214..672b63a34 100644 --- a/pkg/gearman/Tests/GearmanConnectionFactoryConfigTest.php +++ b/pkg/gearman/Tests/GearmanConnectionFactoryConfigTest.php @@ -8,6 +8,8 @@ /** * The class contains the factory tests dedicated to configuration. + * + * @group functional */ class GearmanConnectionFactoryConfigTest extends TestCase { diff --git a/pkg/gearman/Tests/GearmanContextTest.php b/pkg/gearman/Tests/GearmanContextTest.php index ae778791f..d7f41a7b0 100644 --- a/pkg/gearman/Tests/GearmanContextTest.php +++ b/pkg/gearman/Tests/GearmanContextTest.php @@ -9,6 +9,9 @@ use Enqueue\Test\ClassExtensionTrait; use PHPUnit\Framework\TestCase; +/** + * @group functional + */ class GearmanContextTest extends TestCase { use ClassExtensionTrait; diff --git a/pkg/gearman/Tests/GearmanDestinationTest.php b/pkg/gearman/Tests/GearmanDestinationTest.php index 00a75e79f..c31951e57 100644 --- a/pkg/gearman/Tests/GearmanDestinationTest.php +++ b/pkg/gearman/Tests/GearmanDestinationTest.php @@ -8,6 +8,9 @@ use Enqueue\Test\ClassExtensionTrait; use PHPUnit\Framework\TestCase; +/** + * @group functional + */ class GearmanDestinationTest extends TestCase { use ClassExtensionTrait; diff --git a/pkg/gearman/Tests/GearmanMessageTest.php b/pkg/gearman/Tests/GearmanMessageTest.php index d1a6b8fc6..ac669d502 100644 --- a/pkg/gearman/Tests/GearmanMessageTest.php +++ b/pkg/gearman/Tests/GearmanMessageTest.php @@ -6,6 +6,9 @@ use Enqueue\Test\ClassExtensionTrait; use PHPUnit\Framework\TestCase; +/** + * @group functional + */ class GearmanMessageTest extends TestCase { use ClassExtensionTrait; diff --git a/pkg/gearman/Tests/GearmanProducerTest.php b/pkg/gearman/Tests/GearmanProducerTest.php index 4b6cf95e8..6e0c59f96 100644 --- a/pkg/gearman/Tests/GearmanProducerTest.php +++ b/pkg/gearman/Tests/GearmanProducerTest.php @@ -12,6 +12,9 @@ use Enqueue\Test\ClassExtensionTrait; use PHPUnit\Framework\TestCase; +/** + * @group functional + */ class GearmanProducerTest extends TestCase { use ClassExtensionTrait; diff --git a/pkg/gearman/Tests/Spec/GearmanConnectionFactoryTest.php b/pkg/gearman/Tests/Spec/GearmanConnectionFactoryTest.php index fdfc1b911..b3a3d1605 100644 --- a/pkg/gearman/Tests/Spec/GearmanConnectionFactoryTest.php +++ b/pkg/gearman/Tests/Spec/GearmanConnectionFactoryTest.php @@ -5,6 +5,9 @@ use Enqueue\Gearman\GearmanConnectionFactory; use Enqueue\Psr\Spec\PsrConnectionFactorySpec; +/** + * @group functional + */ class GearmanConnectionFactoryTest extends PsrConnectionFactorySpec { /** diff --git a/pkg/gearman/Tests/Spec/GearmanMessageTest.php b/pkg/gearman/Tests/Spec/GearmanMessageTest.php index 7149faa28..155e395f2 100644 --- a/pkg/gearman/Tests/Spec/GearmanMessageTest.php +++ b/pkg/gearman/Tests/Spec/GearmanMessageTest.php @@ -5,6 +5,9 @@ use Enqueue\Gearman\GearmanMessage; use Enqueue\Psr\Spec\PsrMessageSpec; +/** + * @group functional + */ class GearmanMessageTest extends PsrMessageSpec { /** diff --git a/pkg/gearman/Tests/Spec/GearmanQueueTest.php b/pkg/gearman/Tests/Spec/GearmanQueueTest.php index 48517d05b..aa1dbf046 100644 --- a/pkg/gearman/Tests/Spec/GearmanQueueTest.php +++ b/pkg/gearman/Tests/Spec/GearmanQueueTest.php @@ -5,6 +5,9 @@ use Enqueue\Gearman\GearmanDestination; use Enqueue\Psr\Spec\PsrQueueSpec; +/** + * @group functional + */ class GearmanQueueTest extends PsrQueueSpec { /** diff --git a/pkg/gearman/Tests/Spec/GearmanTopicTest.php b/pkg/gearman/Tests/Spec/GearmanTopicTest.php index 21c7c6802..523483d93 100644 --- a/pkg/gearman/Tests/Spec/GearmanTopicTest.php +++ b/pkg/gearman/Tests/Spec/GearmanTopicTest.php @@ -5,6 +5,9 @@ use Enqueue\Gearman\GearmanDestination; use Enqueue\Psr\Spec\PsrTopicSpec; +/** + * @group functional + */ class GearmanTopicTest extends PsrTopicSpec { /** From 781e11d0e3acfd12f84ee43f35351a47f17392a1 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Tue, 27 Jun 2017 20:10:40 +0300 Subject: [PATCH 06/11] [gearman] fix tests. --- .../GearmanConnectionFactoryConfigTest.php | 17 ++++++++--------- pkg/gearman/Tests/GearmanContextTest.php | 1 + pkg/gearman/Tests/GearmanDestinationTest.php | 4 +--- pkg/gearman/Tests/GearmanMessageTest.php | 4 +--- pkg/gearman/Tests/GearmanProducerTest.php | 4 +--- ...kipIfGearmanExtensionIsNotInstalledTrait.php | 15 +++++++++++++++ .../Tests/Spec/GearmanConnectionFactoryTest.php | 6 +++--- pkg/gearman/Tests/Spec/GearmanMessageTest.php | 6 +++--- pkg/gearman/Tests/Spec/GearmanQueueTest.php | 6 +++--- pkg/gearman/Tests/Spec/GearmanTopicTest.php | 6 +++--- 10 files changed, 39 insertions(+), 30 deletions(-) create mode 100644 pkg/gearman/Tests/SkipIfGearmanExtensionIsNotInstalledTrait.php diff --git a/pkg/gearman/Tests/GearmanConnectionFactoryConfigTest.php b/pkg/gearman/Tests/GearmanConnectionFactoryConfigTest.php index 672b63a34..75c61591e 100644 --- a/pkg/gearman/Tests/GearmanConnectionFactoryConfigTest.php +++ b/pkg/gearman/Tests/GearmanConnectionFactoryConfigTest.php @@ -8,12 +8,11 @@ /** * The class contains the factory tests dedicated to configuration. - * - * @group functional */ class GearmanConnectionFactoryConfigTest extends TestCase { use ClassExtensionTrait; + use SkipIfGearmanExtensionIsNotInstalledTrait; public function testThrowNeitherArrayStringNorNullGivenAsConfig() { @@ -57,24 +56,24 @@ public static function provideConfigs() yield [ null, [ - 'host' => \GEARMAN_DEFAULT_TCP_HOST, - 'port' => \GEARMAN_DEFAULT_TCP_PORT, + 'host' => 'localhost', + 'port' => 4730, ], ]; yield [ 'gearman://', [ - 'host' => \GEARMAN_DEFAULT_TCP_HOST, - 'port' => \GEARMAN_DEFAULT_TCP_PORT, + 'host' => 'localhost', + 'port' => 4730, ], ]; yield [ [], [ - 'host' => \GEARMAN_DEFAULT_TCP_HOST, - 'port' => \GEARMAN_DEFAULT_TCP_PORT, + 'host' => 'localhost', + 'port' => 4730, ], ]; @@ -98,7 +97,7 @@ public static function provideConfigs() ['host' => 'theHost'], [ 'host' => 'theHost', - 'port' => \GEARMAN_DEFAULT_TCP_PORT, + 'port' => 4730, ], ]; } diff --git a/pkg/gearman/Tests/GearmanContextTest.php b/pkg/gearman/Tests/GearmanContextTest.php index d7f41a7b0..2a6b0b2bd 100644 --- a/pkg/gearman/Tests/GearmanContextTest.php +++ b/pkg/gearman/Tests/GearmanContextTest.php @@ -15,6 +15,7 @@ class GearmanContextTest extends TestCase { use ClassExtensionTrait; + use SkipIfGearmanExtensionIsNotInstalledTrait; public function testShouldImplementPsrContextInterface() { diff --git a/pkg/gearman/Tests/GearmanDestinationTest.php b/pkg/gearman/Tests/GearmanDestinationTest.php index c31951e57..5b10aa301 100644 --- a/pkg/gearman/Tests/GearmanDestinationTest.php +++ b/pkg/gearman/Tests/GearmanDestinationTest.php @@ -8,12 +8,10 @@ use Enqueue\Test\ClassExtensionTrait; use PHPUnit\Framework\TestCase; -/** - * @group functional - */ class GearmanDestinationTest extends TestCase { use ClassExtensionTrait; + use SkipIfGearmanExtensionIsNotInstalledTrait; public function testShouldImplementPsrQueueInterface() { diff --git a/pkg/gearman/Tests/GearmanMessageTest.php b/pkg/gearman/Tests/GearmanMessageTest.php index ac669d502..5eaa8f070 100644 --- a/pkg/gearman/Tests/GearmanMessageTest.php +++ b/pkg/gearman/Tests/GearmanMessageTest.php @@ -6,12 +6,10 @@ use Enqueue\Test\ClassExtensionTrait; use PHPUnit\Framework\TestCase; -/** - * @group functional - */ class GearmanMessageTest extends TestCase { use ClassExtensionTrait; + use SkipIfGearmanExtensionIsNotInstalledTrait; public function testShouldAllowGetJobPreviouslySet() { diff --git a/pkg/gearman/Tests/GearmanProducerTest.php b/pkg/gearman/Tests/GearmanProducerTest.php index 6e0c59f96..68b20b633 100644 --- a/pkg/gearman/Tests/GearmanProducerTest.php +++ b/pkg/gearman/Tests/GearmanProducerTest.php @@ -12,12 +12,10 @@ use Enqueue\Test\ClassExtensionTrait; use PHPUnit\Framework\TestCase; -/** - * @group functional - */ class GearmanProducerTest extends TestCase { use ClassExtensionTrait; + use SkipIfGearmanExtensionIsNotInstalledTrait; public function testCouldBeConstructedWithGearmanClientAsFirstArgument() { diff --git a/pkg/gearman/Tests/SkipIfGearmanExtensionIsNotInstalledTrait.php b/pkg/gearman/Tests/SkipIfGearmanExtensionIsNotInstalledTrait.php new file mode 100644 index 000000000..99419eb15 --- /dev/null +++ b/pkg/gearman/Tests/SkipIfGearmanExtensionIsNotInstalledTrait.php @@ -0,0 +1,15 @@ +markTestSkipped('The gearman extension is not installed'); + } + + parent::setUp(); + } +} diff --git a/pkg/gearman/Tests/Spec/GearmanConnectionFactoryTest.php b/pkg/gearman/Tests/Spec/GearmanConnectionFactoryTest.php index b3a3d1605..8e7036b88 100644 --- a/pkg/gearman/Tests/Spec/GearmanConnectionFactoryTest.php +++ b/pkg/gearman/Tests/Spec/GearmanConnectionFactoryTest.php @@ -3,13 +3,13 @@ namespace Enqueue\Gearman\Tests\Spec; use Enqueue\Gearman\GearmanConnectionFactory; +use Enqueue\Gearman\Tests\SkipIfGearmanExtensionIsNotInstalledTrait; use Enqueue\Psr\Spec\PsrConnectionFactorySpec; -/** - * @group functional - */ class GearmanConnectionFactoryTest extends PsrConnectionFactorySpec { + use SkipIfGearmanExtensionIsNotInstalledTrait; + /** * {@inheritdoc} */ diff --git a/pkg/gearman/Tests/Spec/GearmanMessageTest.php b/pkg/gearman/Tests/Spec/GearmanMessageTest.php index 155e395f2..cd5a8a074 100644 --- a/pkg/gearman/Tests/Spec/GearmanMessageTest.php +++ b/pkg/gearman/Tests/Spec/GearmanMessageTest.php @@ -3,13 +3,13 @@ namespace Enqueue\Gearman\Tests\Spec; use Enqueue\Gearman\GearmanMessage; +use Enqueue\Gearman\Tests\SkipIfGearmanExtensionIsNotInstalledTrait; use Enqueue\Psr\Spec\PsrMessageSpec; -/** - * @group functional - */ class GearmanMessageTest extends PsrMessageSpec { + use SkipIfGearmanExtensionIsNotInstalledTrait; + /** * {@inheritdoc} */ diff --git a/pkg/gearman/Tests/Spec/GearmanQueueTest.php b/pkg/gearman/Tests/Spec/GearmanQueueTest.php index aa1dbf046..c26e7661b 100644 --- a/pkg/gearman/Tests/Spec/GearmanQueueTest.php +++ b/pkg/gearman/Tests/Spec/GearmanQueueTest.php @@ -3,13 +3,13 @@ namespace Enqueue\Gearman\Tests\Spec; use Enqueue\Gearman\GearmanDestination; +use Enqueue\Gearman\Tests\SkipIfGearmanExtensionIsNotInstalledTrait; use Enqueue\Psr\Spec\PsrQueueSpec; -/** - * @group functional - */ class GearmanQueueTest extends PsrQueueSpec { + use SkipIfGearmanExtensionIsNotInstalledTrait; + /** * {@inheritdoc} */ diff --git a/pkg/gearman/Tests/Spec/GearmanTopicTest.php b/pkg/gearman/Tests/Spec/GearmanTopicTest.php index 523483d93..d431b6731 100644 --- a/pkg/gearman/Tests/Spec/GearmanTopicTest.php +++ b/pkg/gearman/Tests/Spec/GearmanTopicTest.php @@ -3,13 +3,13 @@ namespace Enqueue\Gearman\Tests\Spec; use Enqueue\Gearman\GearmanDestination; +use Enqueue\Gearman\Tests\SkipIfGearmanExtensionIsNotInstalledTrait; use Enqueue\Psr\Spec\PsrTopicSpec; -/** - * @group functional - */ class GearmanTopicTest extends PsrTopicSpec { + use SkipIfGearmanExtensionIsNotInstalledTrait; + /** * {@inheritdoc} */ From 06681ae82b0225481e7160828ab94f2681af4cdb Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Tue, 27 Jun 2017 20:33:53 +0300 Subject: [PATCH 07/11] readd php-redis ext to dockerfile --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index a7c4258b7..f6affdda8 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -3,7 +3,7 @@ FROM formapro/nginx-php-fpm:latest-all-exts ## libs RUN set -x && \ apt-get update && \ - apt-get install -y --no-install-recommends wget curl openssl ca-certificates nano netcat + apt-get install -y --no-install-recommends wget curl openssl ca-certificates nano netcat php-redis ## confis From 49b187ffb96551881685abe1360e1623815593b1 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Tue, 27 Jun 2017 20:34:01 +0300 Subject: [PATCH 08/11] add gearman to subtree split --- bin/subtree-split | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/subtree-split b/bin/subtree-split index 65bd32eb2..ec3be14ed 100755 --- a/bin/subtree-split +++ b/bin/subtree-split @@ -49,6 +49,7 @@ remote simple-client git@github.com:php-enqueue/simple-client.git remote stomp git@github.com:php-enqueue/stomp.git remote amqp-ext git@github.com:php-enqueue/amqp-ext.git remote pheanstalk git@github.com:php-enqueue/pheanstalk.git +remote gearman git@github.com:php-enqueue/gearman.git remote fs git@github.com:php-enqueue/fs.git remote redis git@github.com:php-enqueue/redis.git remote dbal git@github.com:php-enqueue/dbal.git @@ -64,6 +65,7 @@ split 'pkg/simple-client' simple-client split 'pkg/stomp' stomp split 'pkg/amqp-ext' amqp-ext split 'pkg/pheanstalk' pheanstalk +split 'pkg/gearman' gearman split 'pkg/fs' fs split 'pkg/redis' redis split 'pkg/dbal' dbal From b2d8cfb768bebdf49f851c9f225ff08bedc56551 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Tue, 27 Jun 2017 20:39:18 +0300 Subject: [PATCH 09/11] add gearman to release script. --- bin/release | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/release b/bin/release index 236be3c35..996d02c68 100755 --- a/bin/release +++ b/bin/release @@ -14,7 +14,7 @@ fi CURRENT_BRANCH=`git rev-parse --abbrev-ref HEAD` -for REMOTE in origin psr-queue stomp amqp-ext pheanstalk sqs fs redis dbal null enqueue simple-client enqueue-bundle job-queue test +for REMOTE in origin psr-queue stomp amqp-ext pheanstalk gearman sqs fs redis dbal null enqueue simple-client enqueue-bundle job-queue test do echo "" echo "" From 768e6246fb4e33848f5b073df845c6bfac0ffa36 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Tue, 27 Jun 2017 20:39:50 +0300 Subject: [PATCH 10/11] Release 5.0.1 --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b2b2f154..7e347cd6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Change Log +## [5.0.1](https://github.com/php-enqueue/enqueue-dev/tree/5.0.1) (2017-06-27) +[Full Changelog](https://github.com/php-enqueue/enqueue-dev/compare/0.5.0...5.0.1) + +- \[doc\] add a doc for client message scopes [\#56](https://github.com/php-enqueue/enqueue-dev/issues/56) + +- \[client\] Command, Event segregation. [\#105](https://github.com/php-enqueue/enqueue-dev/issues/105) + +- Add Gearman transport. [\#125](https://github.com/php-enqueue/enqueue-dev/pull/125) ([makasim](https://github.com/makasim)) + ## [0.5.0](https://github.com/php-enqueue/enqueue-dev/tree/0.5.0) (2017-06-26) [Full Changelog](https://github.com/php-enqueue/enqueue-dev/compare/0.4.20...0.5.0) From a2b68b7ebe388225036c3216ba9aee800972f946 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Tue, 27 Jun 2017 20:40:47 +0300 Subject: [PATCH 11/11] Release 0.5.1 --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e347cd6a..150718c8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Change Log -## [5.0.1](https://github.com/php-enqueue/enqueue-dev/tree/5.0.1) (2017-06-27) -[Full Changelog](https://github.com/php-enqueue/enqueue-dev/compare/0.5.0...5.0.1) +## [0.5.1](https://github.com/php-enqueue/enqueue-dev/tree/0.5.1) (2017-06-27) +[Full Changelog](https://github.com/php-enqueue/enqueue-dev/compare/0.5.0...0.5.1) - \[doc\] add a doc for client message scopes [\#56](https://github.com/php-enqueue/enqueue-dev/issues/56)