diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9a16954 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +phpunit/ +vendor/ +composer.lock + +.idea/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..ad41cf1 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: php + +php: + - 7.0 + +before_script: + - composer --prefer-source --dev install + +script: phpunit --coverage-text --verbose diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5deaa17 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2016 Dominik Zogg + +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/README.md b/README.md new file mode 100644 index 0000000..389ada2 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# saxulum-message-queue + +[![Build Status](https://api.travis-ci.org/saxulum/saxulum-message-queue.png?branch=master)](https://travis-ci.org/saxulum/saxulum-message-queue) +[![Total Downloads](https://poser.pugx.org/saxulum/saxulum-message-queue/downloads.png)](https://packagist.org/packages/saxulum/saxulum-message-queue) +[![Latest Stable Version](https://poser.pugx.org/saxulum/saxulum-message-queue/v/stable.png)](https://packagist.org/packages/saxulum/saxulum-message-queue) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/saxulum/saxulum-message-queue/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/saxulum/saxulum-message-queue/?branch=master) + +## Description + +A simple to use messaging queue abstraction. + +## Requirements + + * php: ~7.0 + +## Installation + +Through [Composer](http://getcomposer.org) as [saxulum/saxulum-message-queue][1]. + +## Usage + +[1]: https://packagist.org/packages/saxulum/saxulum-message-queue + +## Copyright + +Dominik Zogg 2016 diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..be32eb3 --- /dev/null +++ b/composer.json @@ -0,0 +1,26 @@ +{ + "name": "saxulum/saxulum-message-queue", + "description": "Saxulum Message Queue", + "keywords": ["saxulum", "message-queue", "system-v"], + "license": "MIT", + "authors": [ + { + "name": "Dominik Zogg", + "email": "dominik.zogg@gmail.com" + } + ], + "require": { + "php": "~7.0" + }, + "require-dev": { + "phpunit/phpunit": "~5.0" + }, + "autoload": { + "psr-4": { "Saxulum\\MessageQueue\\": "src/" } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..f094de0 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,26 @@ + + + + + ./tests + + + + + ./src + + + + + + diff --git a/src/MessageInterface.php b/src/MessageInterface.php new file mode 100644 index 0000000..42658f1 --- /dev/null +++ b/src/MessageInterface.php @@ -0,0 +1,17 @@ +messageClass = $messageClass; + $this->queue = msg_get_queue($key); + $this->type = $type; + } + + /** + * @return null|MessageInterface + * @throws \Exception + */ + public function receive() + { + $type = null; + $json = null; + $error = null; + + $status = msg_receive($this->queue, $this->type, $type, 1048576, $json, false, MSG_IPC_NOWAIT, $error); + + if (false === $status) { + // we do not wait for a message (prevent lock) + if (MSG_ENOMSG === $error) { + return null; + } + + throw new \Exception(sprintf('Can\'t receive message, error code %d', $error)); + } + + /** @var MessageInterface $messageClass */ + $messageClass = $this->messageClass; + + return $messageClass::fromJson($json); + } +} diff --git a/src/SystemV/SystemVSend.php b/src/SystemV/SystemVSend.php new file mode 100644 index 0000000..a745ef1 --- /dev/null +++ b/src/SystemV/SystemVSend.php @@ -0,0 +1,45 @@ +queue = msg_get_queue($key); + $this->type = $type; + } + + /** + * @param MessageInterface $message + * @return MessageSendInterface + * @throws \Exception + */ + public function send(MessageInterface $message): MessageSendInterface + { + $json = $message->toJson(); + if (false === msg_send($this->queue, $this->type, $json, false)) { + throw new \Exception(sprintf('Cant send message : %s', $json)); + } + + return $this; + } +} diff --git a/tests/Resources/SampleMessage.php b/tests/Resources/SampleMessage.php new file mode 100644 index 0000000..377b1bf --- /dev/null +++ b/tests/Resources/SampleMessage.php @@ -0,0 +1,99 @@ +context, $rawMessage->total, $rawMessage->success, $rawMessage->failed); + } + + /** + * @return string + */ + public function toJson(): string + { + return json_encode([ + 'context' => $this->context, + 'total' => $this->total, + 'success' => $this->success, + 'failed' => $this->failed, + ]); + } + + /** + * @param string $context + * @param int $total + * @param int $success + * @param int $failed + */ + public function __construct(string $context, int $total, int $success, int $failed) + { + $this->context = $context; + $this->total = $total; + $this->success = $success; + $this->failed = $failed; + } + + /** + * @return string + */ + public function getContext(): string + { + return $this->context; + } + + /** + * @return int + */ + public function getTotal(): int + { + return $this->total; + } + + /** + * @return int + */ + public function getSuccess(): int + { + return $this->success; + } + + /** + * @return int + */ + public function getFailed(): int + { + return $this->failed; + } +} diff --git a/tests/SystemVTest.php b/tests/SystemVTest.php new file mode 100644 index 0000000..ace36ef --- /dev/null +++ b/tests/SystemVTest.php @@ -0,0 +1,71 @@ +send($sampleMessage1); + $sender1->send($sampleMessage2); + $sender1->send($sampleMessage3); + $sender2->send($sampleMessage4); + $sender2->send($sampleMessage5); + + $receivedMessages1 = []; + while(null !== $receivedMessage = $receiver->receive()) { + $receivedMessages1[] = $receivedMessage; + } + + self::assertCount(5, $receivedMessages1); + + self::assertEquals($sampleMessage1, $receivedMessages1[0]); + self::assertEquals($sampleMessage2, $receivedMessages1[1]); + self::assertEquals($sampleMessage3, $receivedMessages1[2]); + self::assertEquals($sampleMessage4, $receivedMessages1[3]); + self::assertEquals($sampleMessage5, $receivedMessages1[4]); + + $sender1->send($sampleMessage6); + $sender2->send($sampleMessage7); + $sender3->send($sampleMessage8); + $sender4->send($sampleMessage9); + $sender5->send($sampleMessage10); + + $receivedMessages2 = []; + while(null !== $receivedMessage = $receiver->receive()) { + $receivedMessages2[] = $receivedMessage; + } + + self::assertCount(5, $receivedMessages2); + + self::assertEquals($sampleMessage6, $receivedMessages2[0]); + self::assertEquals($sampleMessage7, $receivedMessages2[1]); + self::assertEquals($sampleMessage8, $receivedMessages2[2]); + self::assertEquals($sampleMessage9, $receivedMessages2[3]); + self::assertEquals($sampleMessage10, $receivedMessages2[4]); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..ed5fd81 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,4 @@ +setPsr4('Saxulum\Tests\MessageQueue\\', __DIR__);