From 38e53692d008afca96d44c07645ad4e33a68f41b Mon Sep 17 00:00:00 2001 From: Li Zhineng Date: Mon, 23 Dec 2024 10:32:05 +0800 Subject: [PATCH 1/9] install acs-sdk-php --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 06602e3..a231d1c 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,8 @@ "php": "^8.0", "illuminate/contracts": "^10.0", "illuminate/queue": "^10.0", - "dew-serverless/mns": "^1.1" + "dew-serverless/mns": "^1.1", + "dew-serverless/acs-sdk-php": "dev-mns-queue" }, "require-dev": { "pestphp/pest": "^2.23", From d48ca6cf2c95914a1a034dc884b47ca3d68d97ac Mon Sep 17 00:00:00 2001 From: Li Zhineng Date: Tue, 24 Dec 2024 20:13:40 +0800 Subject: [PATCH 2/9] replace sdk --- phpstan-baseline.neon | 7 ++ phpstan.neon | 1 + src/MnsConnector.php | 62 ++++++++++------ src/MnsJob.php | 43 +++++------ src/MnsQueue.php | 157 +++++++++++++++++++++++------------------ tests/MnsJobTest.php | 69 ++++++++---------- tests/MnsQueueTest.php | 157 ++++++++++++++++++----------------------- 7 files changed, 249 insertions(+), 247 deletions(-) create mode 100644 phpstan-baseline.neon diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000..d754edb --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,7 @@ +parameters: + ignoreErrors: + - + message: '#^Parameter \#1 \$arguments of method Dew\\Acs\\MnsOpen\\QueueClient\:\:sendMessage\(\) expects array\{QueueName\: string, Message\: array\{MessageBody\: string, DelaySeconds\?\: int\}\}, array\{QueueName\: string, Message\: non\-empty\-array\\} given\.$#' + identifier: argument.type + count: 1 + path: src/MnsQueue.php diff --git a/phpstan.neon b/phpstan.neon index 5722f37..76b4973 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,6 @@ includes: - vendor/phpstan/phpstan-strict-rules/rules.neon + - phpstan-baseline.neon parameters: level: max diff --git a/src/MnsConnector.php b/src/MnsConnector.php index ffe0412..475b961 100644 --- a/src/MnsConnector.php +++ b/src/MnsConnector.php @@ -2,17 +2,18 @@ namespace Dew\MnsDriver; -use Dew\Mns\MnsClient; -use Dew\Mns\Versions\V20150606\Queue; +use Dew\Acs\MnsOpen\MnsOpenClient; +use Dew\Acs\MnsOpen\QueueClient; use Illuminate\Queue\Connectors\ConnectorInterface; /** - * @phpstan-type Config array{ - * endpoint: string, - * key: string, - * secret: string, - * queue: string, - * http?: array + * @phpstan-type TConfig array{ + * key: string, + * secret: string, + * region: string, + * endpoint: string, + * queue: string, + * console_endpoint?: string * } */ class MnsConnector implements ConnectorInterface @@ -25,25 +26,44 @@ class MnsConnector implements ConnectorInterface */ public function connect(array $config) { - /** @var Config $config */ - $mns = new MnsClient($config['endpoint'], $config['key'], $config['secret']); - - $mns->configure($this->withDefaultConfiguration($config['http'] ?? [])); + /** @var TConfig $config */ + return new MnsQueue( + $this->makeConsoleClient($config), + $this->makeQueueClient($config), + $config['queue'] + ); + } - return new MnsQueue(new Queue($mns), $config['queue']); + /** + * Make a MNS console client. + * + * @param TConfig $config + */ + private function makeConsoleClient(array $config): MnsOpenClient + { + return new MnsOpenClient(array_filter([ + 'credentials' => [ + 'key' => $config['key'], + 'secret' => $config['secret'], + ], + 'region' => $config['region'], + 'endpoint' => $config['console_endpoint'] ?? null, + ], fn (mixed $value): bool => $value !== null)); } /** - * Build a configuration with default one. + * Make a MNS queue client. * - * @param array $config - * @return array + * @param TConfig $config */ - protected function withDefaultConfiguration(array $config = []): array + private function makeQueueClient(array $config): QueueClient { - // timeout: receiving messages could take up to 30 seconds. - return array_merge([ - 'timeout' => 60.0, - ], $config); + return new QueueClient([ + 'credentials' => [ + 'key' => $config['key'], + 'secret' => $config['secret'], + ], + 'endpoint' => $config['endpoint'], + ]); } } diff --git a/src/MnsJob.php b/src/MnsJob.php index cc9d5c3..e717664 100644 --- a/src/MnsJob.php +++ b/src/MnsJob.php @@ -2,8 +2,8 @@ namespace Dew\MnsDriver; -use Dew\Mns\Versions\V20150606\Queue; -use Dew\Mns\Versions\V20150606\Results\ReceiveMessageResult; +use Dew\Acs\MnsOpen\Models\ReceiveMessage; +use Dew\Acs\MnsOpen\QueueClient; use Illuminate\Container\Container; use Illuminate\Contracts\Queue\Job as JobContract; use Illuminate\Queue\Jobs\Job; @@ -13,12 +13,12 @@ class MnsJob extends Job implements JobContract /** * Create a new job instance. * - * @param \Dew\Mns\Versions\V20150606\Queue $mns + * @param \Dew\Acs\MnsOpen\QueueClient $mns */ public function __construct( Container $container, protected $mns, - protected ReceiveMessageResult $job, + protected ReceiveMessage $job, string $connectionName, string $queue ) { @@ -37,15 +37,11 @@ public function release($delay = 0) { parent::release($delay); - $result = $this->mns->changeMessageVisibility( - $this->queue, (string) $this->job->receiptHandle(), $delay - ); - - if ($result->failed()) { - throw new MnsQueueException(sprintf('Release the job with error [%s] %s', - $result->errorCode(), $result->errorMessage() - )); - } + $this->mns->changeMessageVisibility([ + 'QueueName' => $this->queue, + 'ReceiptHandle' => $this->job->receiptHandle, + 'VisibilityTimeout' => $delay, + ]); } /** @@ -57,13 +53,10 @@ public function delete() { parent::delete(); - $result = $this->mns->deleteMessage($this->queue, (string) $this->job->receiptHandle()); - - if ($result->failed()) { - throw new MnsQueueException(sprintf('Delete the job with error [%s] %s', - $result->errorCode(), $result->errorMessage() - )); - } + $this->mns->deleteMessage([ + 'QueueName' => $this->queue, + 'ReceiptHandle' => $this->job->receiptHandle, + ]); } /** @@ -73,7 +66,7 @@ public function delete() */ public function attempts() { - return (int) $this->job->dequeueCount(); + return $this->job->dequeueCount; } /** @@ -83,7 +76,7 @@ public function attempts() */ public function getJobId() { - return (string) $this->job->messageId(); + return $this->job->messageId; } /** @@ -93,13 +86,13 @@ public function getJobId() */ public function getRawBody() { - return (string) $this->job->messageBody(); + return $this->job->messageBody; } /** * Get the underlying MNS queue instance. */ - public function getMns(): Queue + public function getMns(): QueueClient { return $this->mns; } @@ -107,7 +100,7 @@ public function getMns(): Queue /** * Get the underlying raw MNS job. */ - public function getMnsJob(): ReceiveMessageResult + public function getMnsJob(): ReceiveMessage { return $this->job; } diff --git a/src/MnsQueue.php b/src/MnsQueue.php index 06c0984..c28c230 100644 --- a/src/MnsQueue.php +++ b/src/MnsQueue.php @@ -2,8 +2,9 @@ namespace Dew\MnsDriver; -use Dew\Mns\Versions\V20150606\Models\Message; -use Dew\Mns\Versions\V20150606\Results\BatchReceiveMessageResult; +use Dew\Acs\MnsOpen\Models\ReceiveMessage; +use Dew\Acs\MnsOpen\QueueException; +use Dew\Acs\MnsOpen\Results\BatchReceiveMessageResult; use Illuminate\Contracts\Queue\ClearableQueue; use Illuminate\Contracts\Queue\Queue as QueueContract; use Illuminate\Queue\Queue; @@ -13,10 +14,12 @@ class MnsQueue extends Queue implements ClearableQueue, QueueContract /** * Create a new MNS queue instance. * - * @param \Dew\Mns\Versions\V20150606\Queue $mns + * @param \Dew\Acs\MnsOpen\MnsOpenClient $console + * @param \Dew\Acs\MnsOpen\QueueClient $client */ public function __construct( - protected $mns, + protected $console, + protected $client, protected string $default ) { // @@ -30,17 +33,20 @@ public function __construct( */ public function size($queue = null) { - $result = $this->mns->getQueueAttributes($this->getQueue($queue)); + $result = $this->console->getQueueAttributes([ + 'QueueName' => $this->getQueue($queue), + ]); - if ($result->failed()) { - throw new MnsQueueException(sprintf('Get the size of the queue with error [%s] %s', - $result->errorCode(), $result->errorMessage() - )); - } + $active = $result->get('Data.ActiveMessages'); + $active = is_int($active) ? $active : 0; + + $inactive = $result->get('Data.InactiveMessages'); + $inactive = is_int($inactive) ? $inactive : 0; + + $delayed = $result->get('Data.DelayMessages'); + $delayed = is_int($delayed) ? $delayed : 0; - return (int) $result->activeMessages() - + (int) $result->inactiveMessages() - + (int) $result->delayMessages(); + return $active + $inactive + $delayed; } /** @@ -74,18 +80,12 @@ public function push($job, $data = '', $queue = null) */ public function pushRaw($payload, $queue = null, array $options = []) { - /** @var array */ - $opts = ['MessageBody' => $payload, ...$options]; - - $result = $this->mns->sendMessage($this->getQueue($queue), $opts); - - if ($result->failed()) { - throw new MnsQueueException(sprintf('Push job to queue with error [%s] %s', - $result->errorCode(), $result->errorMessage() - )); - } + $result = $this->client->sendMessage([ + 'QueueName' => $this->getQueue($queue), + 'Message' => ['MessageBody' => $payload, ...$options], + ]); - return $result->messageId(); + return $result->message()->messageId; } /** @@ -144,20 +144,20 @@ public function bulk($jobs, $data = '', $queue = null) */ public function pop($queue = null) { - $result = $this->mns->receiveMessage($queue = $this->getQueue($queue)); - - if ($result->failed() && $result->errorCode() === 'MessageNotExist') { - return null; - } + try { + $result = $this->client->receiveMessage([ + 'QueueName' => $queue = $this->getQueue($queue), + ]); + } catch (QueueException $e) { + if ($e->getCode() === 'MessageNotExist') { + return null; + } - if ($result->failed()) { - throw new MnsQueueException(sprintf('Pop job off of queue with error [%s] %s', - $result->errorCode(), $result->errorMessage() - )); + throw $e; } return new MnsJob( - $this->container, $this->mns, $result, + $this->container, $this->client, $result->message(), $this->connectionName, $queue ); } @@ -181,13 +181,9 @@ public function clear($queue) break; } - /** @var \Dew\Mns\Versions\V20150606\Models\Message[] */ - $messages = $result->messages(); - - /** @var array */ - $receipts = array_filter( - array_map(fn (Message $message) => $message->receiptHandle(), $messages), - fn (?string $handle) => is_string($handle) + $receipts = array_map( + fn (ReceiveMessage $message) => $message->receiptHandle, + $result->messages() ); $deleted += $this->deleteMessages($queue, $receipts); @@ -201,46 +197,67 @@ public function clear($queue) */ protected function retrieveMessages(string $queue): BatchReceiveMessageResult|bool { - $result = $this->mns->batchReceiveMessage($queue, [ - 'numOfMessages' => '16', // max messages we could get at a time - 'waitseconds' => '30', // max timeout - ]); - - if ($result->failed() && $result->errorCode() === 'MessageNotExist') { - return false; - } + try { + return $this->client->batchReceiveMessage([ + 'QueueName' => $queue, + 'numOfMessages' => 16, // max messages we could get at a time + 'waitseconds' => 30, // max timeout + ]); + } catch (QueueException $e) { + if ($e->getCode() === 'MessageNotExist') { + return false; + } - if ($result->failed()) { - throw new MnsQueueException(sprintf('Retrieve the messages with error [%s] %s', - $result->errorCode(), $result->errorMessage() - )); + throw $e; } - - return $result; } /** * Delete the messages from queue. * - * @param array $receipts + * @param string[] $handles */ - protected function deleteMessages(string $queue, array $receipts): int + protected function deleteMessages(string $queue, array $handles): int { - $result = $this->mns->batchDeleteMessage($queue, $receipts); + try { + $this->client->batchDeleteMessage([ + 'QueueName' => $queue, + 'ReceiptHandles' => [ + 'ReceiptHandle' => $handles, + ], + ]); + + return count($handles); + } catch (QueueException $e) { + $errors = $e->getResult()?->list('Errors.Error'); + + if ($errors === null || $errors === []) { + throw $e; + } - if ($result->failed()) { - throw new MnsQueueException(sprintf('Delete the messages with error [%s] %s', - $result->errorCode(), $result->errorMessage() - )); - } + $failed = 0; - $errors = $result->errors(); + foreach ($errors as $error) { + if (! is_array($error)) { + throw $e; + } - if (is_array($errors) && $errors !== []) { - return count($receipts) - count($errors); - } + $code = $error['ErrorCode'] ?? null; + $message = $error['ErrorMessage'] ?? null; - return count($receipts); + if (! is_string($code) || ! is_string($message)) { + throw $e; + } + + if ($code !== 'MessageNotExist') { + throw new MnsQueueException($message, previous: $e); + } + + $failed++; + } + + return count($handles) - $failed; + } } /** @@ -258,10 +275,10 @@ public function getQueue(?string $queue = null): string /** * The underlying MNS queue. * - * @return \Dew\Mns\Versions\V20150606\Queue + * @return \Dew\Acs\MnsOpen\QueueClient */ public function getMns() { - return $this->mns; + return $this->client; } } diff --git a/tests/MnsJobTest.php b/tests/MnsJobTest.php index 6afe196..619c45d 100644 --- a/tests/MnsJobTest.php +++ b/tests/MnsJobTest.php @@ -1,19 +1,14 @@ client = new MnsClient('http://1234567891011.mns.us-west-1.aliyuncs.com', 'key', 'secret'); - $this->mns = Mockery::mock(new Queue($this->client)); + $this->mns = Mockery::mock(stdClass::class); $this->mockedContainer = Mockery::mock(Container::class); $this->queueName = 'default'; @@ -23,50 +18,42 @@ $this->mockedMessageId = '5F290C926D472878-2-14D9529****-200000001'; $this->mockedReceiptHandle = '1-ODU4OTkzNDU5My0xNDM1MTk3NjAwLTItNg=='; - $this->mockedStream = Mockery::mock(StreamInterface::class); - $this->mockedStream->allows()->__toString()->andReturns(''); - - $this->mockedOkResponse = Mockery::mock(ResponseInterface::class); - $this->mockedOkResponse->allows()->getStatusCode()->andReturns(200); - $this->mockedOkResponse->allows()->getHeaderLine('content-type')->andReturns('text/xml'); - $this->mockedOkResponse->allows()->getBody()->andReturns($this->mockedStream); - - $this->mockedNoContentResponse = Mockery::mock(ResponseInterface::class); - $this->mockedNoContentResponse->allows()->getStatusCode()->andReturns(204); - $this->mockedNoContentResponse->allows()->getHeaderLine('content-type')->andReturns(''); - - $this->mockedReceiveMessageResult = new ReceiveMessageResult($this->mockedOkResponse, tap(Mockery::mock(XmlEncoder::class), function ($mock) { - $mock->expects()->decode('')->andReturns([ - 'MessageId' => $this->mockedMessageId, - 'ReceiptHandle' => $this->mockedReceiptHandle, - 'MessageBody' => $this->mockedPayload, - 'MessageBodyMD5' => md5($this->mockedPayload), - ]); - })); - - $this->mockedChangeMessageVisibilityResult = new ChangeMessageVisibilityResult($this->mockedOkResponse, tap(Mockery::mock(XmlEncoder::class), function ($mock) { - $mock->expects()->decode('')->andReturns([ + $this->mockedReceiveMessage = ReceiveMessage::make([ + 'MessageId' => $this->mockedMessageId, + 'ReceiptHandle' => $this->mockedReceiptHandle, + 'MessageBody' => $this->mockedPayload, + 'MessageBodyMD5' => md5($this->mockedPayload), + 'EnqueueTime' => '1250700979248', + 'NextVisibleTime' => '1250700799348', + 'FirstDequeueTime' => '1250700779318', + 'DequeueCount' => '1', + 'Priority' => '8', + ]); + + $this->mockedChangeMessageVisibilityResult = new ChangeMessageVisibilityResult(new Result([ + 'ChangeVisibility' => [ 'ReceiptHandle' => $this->mockedReceiptHandle, - ]); - })); + 'NextVisibleTime' => '1250700979298000', + ], + ])); - $this->mockedDeleteMessageResult = new Result($this->mockedNoContentResponse, Mockery::mock(XmlEncoder::class)); + $this->mockedDeleteMessageResult = new MnsResult(new Result); }); test('release releases the job onto mns', function () { - $this->mns->expects()->changeMessageVisibility($this->queueName, $this->mockedReceiptHandle, 60)->andReturns($this->mockedChangeMessageVisibilityResult); - $job = new MnsJob($this->mockedContainer, $this->mns, $this->mockedReceiveMessageResult, 'mns', $this->queueName); + $this->mns->expects()->changeMessageVisibility(['QueueName' => $this->queueName, 'ReceiptHandle' => $this->mockedReceiptHandle, 'VisibilityTimeout' => 60])->andReturns($this->mockedChangeMessageVisibilityResult); + $job = new MnsJob($this->mockedContainer, $this->mns, $this->mockedReceiveMessage, 'mns', $this->queueName); $job->release(60); }); test('delete removes the job from mns', function () { - $this->mns->expects()->deleteMessage($this->queueName, $this->mockedReceiptHandle)->andReturns($this->mockedDeleteMessageResult); - $job = new MnsJob($this->mockedContainer, $this->mns, $this->mockedReceiveMessageResult, 'mns', $this->queueName); + $this->mns->expects()->deleteMessage(['QueueName' => $this->queueName, 'ReceiptHandle' => $this->mockedReceiptHandle])->andReturns($this->mockedDeleteMessageResult); + $job = new MnsJob($this->mockedContainer, $this->mns, $this->mockedReceiveMessage, 'mns', $this->queueName); $job->delete(); }); test('fire calls the job handler', function () { - $job = new MnsJob($this->mockedContainer, $this->mns, $this->mockedReceiveMessageResult, 'mns', $this->queueName); + $job = new MnsJob($this->mockedContainer, $this->mns, $this->mockedReceiveMessage, 'mns', $this->queueName); $job->getContainer()->expects()->make($this->mockedJob)->andReturns($handler = Mockery::mock(stdClass::class)); $handler->expects()->fire($job, $this->mockedData); $job->fire(); diff --git a/tests/MnsQueueTest.php b/tests/MnsQueueTest.php index a651509..e8ead64 100644 --- a/tests/MnsQueueTest.php +++ b/tests/MnsQueueTest.php @@ -1,23 +1,19 @@ client = new MnsClient('http://1234567891011.mns.us-west-1.aliyuncs.com', 'key', 'secret'); - $this->mns = Mockery::mock(new Queue($this->client)); + $this->console = Mockery::mock(stdClass::class); + $this->client = Mockery::mock(stdClass::class); $this->queueName = 'default'; $this->mockedJob = 'greeting'; @@ -31,98 +27,79 @@ $this->mockedInactiveMessages = 4; $this->mockedDelayMessages = 5; - $this->mockedStream = Mockery::mock(StreamInterface::class); - $this->mockedStream->allows()->__toString()->andReturns(''); - $this->mockedOkResponse = Mockery::mock(ResponseInterface::class); - $this->mockedOkResponse->allows()->getStatusCode()->andReturns(200); - $this->mockedOkResponse->allows()->getHeaderLine('content-type')->andReturns('text/xml'); - $this->mockedOkResponse->allows()->getBody()->andReturns($this->mockedStream); - - $this->mockedCreatedResponse = Mockery::mock(ResponseInterface::class); - $this->mockedCreatedResponse->allows()->getStatusCode()->andReturns(201); - $this->mockedCreatedResponse->allows()->getHeaderLine('content-type')->andReturns('text/xml'); - $this->mockedCreatedResponse->allows()->getBody()->andReturns($this->mockedStream); - - $this->mockedNoContentResponse = Mockery::mock(ResponseInterface::class); - $this->mockedNoContentResponse->allows()->getStatusCode()->andReturns(204); - $this->mockedNoContentResponse->allows()->getHeaderLine('content-type')->andReturns(''); - - $this->mockedNotFoundResponse = Mockery::mock(ResponseInterface::class); - $this->mockedNotFoundResponse->allows()->getStatusCode()->andReturn(404); - $this->mockedNotFoundResponse->allows()->getHeaderLine('content-type')->andReturns('text/xml'); - $this->mockedNotFoundResponse->allows()->getBody()->andReturns($this->mockedStream); - - $this->mockedGetQueueAttributesResult = new GetQueueAttributesResult($this->mockedOkResponse, tap(Mockery::mock(XmlEncoder::class), function ($mock) { - $mock->expects()->decode('')->andReturns([ + $this->mockedGetQueueAttributesResult = new Result([ + 'Data' => [ 'ActiveMessages' => $this->mockedActiveMessages, 'InactiveMessages' => $this->mockedInactiveMessages, 'DelayMessages' => $this->mockedDelayMessages, - ]); - })); + ], + ]); - $this->mockedSendMessageResult = new SendMessageResult($this->mockedCreatedResponse, tap(Mockery::mock(XmlEncoder::class), function ($mock) { - $mock->expects()->decode('')->andReturns([ + $this->mockedSendMessageResult = new SendMessageResult(new Result([ + 'Message' => [ 'MessageId' => $this->mockedMessageId, - 'MessageBodyMD5' => md5($this->mockedPayload), - 'ReceiptHandle' => $this->mockedReceiptHandle, - ]); - })); - - $this->mockedReceiveMessageResult = new ReceiveMessageResult($this->mockedOkResponse, tap(Mockery::mock(XmlEncoder::class), function ($mock) { - $mock->expects()->decode('')->andReturns([ - 'MessageId' => $this->mockedMessageId, - 'MessageBody' => $this->mockedPayload, - 'MessageBodyMD5' => md5($this->mockedPayload), - 'ReceiptHandle' => $this->mockedReceiptHandle, - ]); - })); - - $this->mockedMessageNotExistsResult = new ReceiveMessageResult($this->mockedNotFoundResponse, tap(Mockery::mock(XmlEncoder::class), function ($mock) { - $mock->expects()->decode('')->andReturns([ + 'MessageBodyMD5' => hash('md5', $this->mockedPayload), + ], + ])); + + $this->mockedReceiveMessage = [ + 'MessageId' => $this->mockedMessageId, + 'MessageBody' => $this->mockedPayload, + 'MessageBodyMD5' => hash('md5', $this->mockedPayload), + 'ReceiptHandle' => $this->mockedReceiptHandle, + 'EnqueueTime' => '1250700979248', + 'NextVisibleTime' => '1250700799348', + 'FirstDequeueTime' => '1250700779318', + 'DequeueCount' => '1', + 'Priority' => '8', + ]; + + $this->mockedReceiveMessageResult = new ReceiveMessageResult(new Result([ + 'Message' => $this->mockedReceiveMessage, + ])); + + $this->mockedMessageNotExistsException = QueueException::makeFromResult(new Result([ + 'Error' => [ 'Code' => 'MessageNotExist', 'Message' => 'Message not exist.', - ]); - })); - - $this->mockedBatchReceiveMessageResult = new BatchReceiveMessageResult($this->mockedOkResponse, tap(Mockery::mock(XmlEncoder::class), function ($mock) { - $mock->expects()->decode('')->andReturns([ - 'Message' => [ - ['ReceiptHandle' => $this->mockedReceiptHandle], - ], - ]); - })); - - $this->mockedBatchMessageNotFoundResult = new BatchReceiveMessageResult($this->mockedNotFoundResponse, tap(Mockery::mock(XmlEncoder::class), function ($mock) { - $mock->expects()->decode('')->andReturns([ + ], + ])); + + $this->mockedBatchReceiveMessageResult = new BatchReceiveMessageResult(new Result([ + 'Messages' => ['Message' => [$this->mockedReceiveMessage]], + ])); + + $this->mockedBatchMessageNotFoundException = QueueException::makeFromResult(new Result([ + 'Error' => [ 'Code' => 'MessageNotExist', 'Message' => 'Message not exist.', - ]); - })); + ], + ])); - $this->mockedBatchDeleteMessageResult = new BatchDeleteMessageResult($this->mockedNoContentResponse, Mockery::mock(XmlEncoder::class)); + $this->mockedBatchDeleteMessageResult = new MnsResult(new Result); }); test('queue size includes active, inactive and delayed messages', function () { - $this->mns->expects()->getQueueAttributes($this->queueName)->andReturns($this->mockedGetQueueAttributesResult); - $queue = new MnsQueue($this->mns, $this->queueName); - expect($queue->size())->toBeInt()->toBe($this->mockedActiveMessages + $this->mockedInactiveMessages + $this->mockedDelayMessages); + $this->console->shouldReceive('getQueueAttributes')->with(['QueueName' => $this->queueName])->once()->andReturn($this->mockedGetQueueAttributesResult); + $queue = new MnsQueue($this->console, $this->client, $this->queueName); + expect($queue->size())->toBe($this->mockedActiveMessages + $this->mockedInactiveMessages + $this->mockedDelayMessages); }); test('push job to mns', function () { - $queue = $this->getMockBuilder(MnsQueue::class)->onlyMethods(['createPayload'])->setConstructorArgs([$this->mns, $this->queueName])->getMock(); + $queue = $this->getMockBuilder(MnsQueue::class)->onlyMethods(['createPayload'])->setConstructorArgs([$this->console, $this->client, $this->queueName])->getMock(); $queue->setContainer($container = Mockery::spy(Container::class)); $queue->expects($this->once())->method('createPayload')->with($this->mockedJob, $this->queueName, $this->mockedData)->willReturn($this->mockedPayload); - $this->mns->expects()->sendMessage($this->queueName, ['MessageBody' => $this->mockedPayload])->andReturns($this->mockedSendMessageResult); + $this->client->shouldReceive('sendMessage')->with(['QueueName' => $this->queueName, 'Message' => ['MessageBody' => $this->mockedPayload]])->andReturn($this->mockedSendMessageResult); $id = $queue->push($this->mockedJob, $this->mockedData, $this->queueName); expect($id)->toBe($this->mockedMessageId); $container->shouldHaveReceived('bound')->with('events'); }); test('push delayed job to mns', function () { - $queue = $this->getMockBuilder(MnsQueue::class)->onlyMethods(['createPayload'])->setConstructorArgs([$this->mns, $this->queueName])->getMock(); + $queue = $this->getMockBuilder(MnsQueue::class)->onlyMethods(['createPayload'])->setConstructorArgs([$this->console, $this->client, $this->queueName])->getMock(); $queue->setContainer($container = Mockery::spy(Container::class)); $queue->expects($this->once())->method('createPayload')->with($this->mockedJob, $this->queueName, $this->mockedData)->willReturn($this->mockedPayload); - $this->mns->expects()->sendMessage($this->queueName, ['MessageBody' => $this->mockedPayload, 'DelaySeconds' => $this->mockedDelay])->andReturns($this->mockedSendMessageResult); + $this->client->shouldReceive('sendMessage')->with(['QueueName' => $this->queueName, 'Message' => ['MessageBody' => $this->mockedPayload, 'DelaySeconds' => $this->mockedDelay]])->once()->andReturn($this->mockedSendMessageResult); $id = $queue->later($this->mockedDelay, $this->mockedJob, $this->mockedData, $this->queueName); expect($id)->toBe($this->mockedMessageId); $container->shouldHaveReceived('bound')->with('events'); @@ -130,42 +107,42 @@ test('push delayed job with datetime to mns', function () { $now = Carbon::now(); - $queue = $this->getMockBuilder(MnsQueue::class)->onlyMethods(['createPayload'])->setConstructorArgs([$this->mns, $this->queueName])->getMock(); + $queue = $this->getMockBuilder(MnsQueue::class)->onlyMethods(['createPayload'])->setConstructorArgs([$this->console, $this->client, $this->queueName])->getMock(); $queue->setContainer($container = Mockery::spy(Container::class)); $queue->expects($this->once())->method('createPayload')->with($this->mockedJob, $this->queueName, $this->mockedData)->willReturn($this->mockedPayload); - $this->mns->expects()->sendMessage($this->queueName, ['MessageBody' => $this->mockedPayload, 'DelaySeconds' => $this->mockedDelay])->andReturns($this->mockedSendMessageResult); + $this->client->shouldReceive('sendMessage')->with(['QueueName' => $this->queueName, 'Message' => ['MessageBody' => $this->mockedPayload, 'DelaySeconds' => $this->mockedDelay]])->once()->andReturn($this->mockedSendMessageResult); $id = $queue->later($now->addSeconds($this->mockedDelay), $this->mockedJob, $this->mockedData, $this->queueName); expect($id)->toBe($this->mockedMessageId); $container->shouldHaveReceived('bound')->with('events'); }); test('pop job off of mns', function () { - $queue = new MnsQueue($this->mns, $this->queueName); + $queue = new MnsQueue($this->console, $this->client, $this->queueName); $queue->setContainer(Mockery::mock(Container::class)); $queue->setConnectionName('mns'); - $this->mns->expects()->receiveMessage($this->queueName)->andReturns($this->mockedReceiveMessageResult); + $this->client->expects()->receiveMessage(['QueueName' => $this->queueName])->andReturns($this->mockedReceiveMessageResult); $job = $queue->pop($this->queueName); expect($job)->toBeInstanceOf(MnsJob::class); }); test('pop job off of empty mns', function () { - $queue = new MnsQueue($this->mns, $this->queueName); - $this->mns->expects()->receiveMessage($this->queueName)->andReturns($this->mockedMessageNotExistsResult); + $queue = new MnsQueue($this->console, $this->client, $this->queueName); + $this->client->expects()->receiveMessage(['QueueName' => $this->queueName])->andThrows($this->mockedMessageNotExistsException); $job = $queue->pop($this->queueName); - expect($job)->toBe(null); + expect($job)->toBeNull(); }); test('clear queue', function () { - $queue = new MnsQueue($this->mns, $this->queueName); - $this->mns->allows()->batchReceiveMessage($this->queueName, ['numOfMessages' => '16', 'waitseconds' => '30'])->andReturns($this->mockedBatchReceiveMessageResult, $this->mockedBatchMessageNotFoundResult); - $this->mns->expects()->batchDeleteMessage($this->queueName, [$this->mockedReceiptHandle])->andReturns($this->mockedBatchDeleteMessageResult); + $queue = new MnsQueue($this->console, $this->client, $this->queueName); + $this->client->allows()->batchReceiveMessage(['QueueName' => $this->queueName, 'numOfMessages' => '16', 'waitseconds' => '30'])->andReturnUsing(fn () => $this->mockedBatchReceiveMessageResult, fn () => throw $this->mockedBatchMessageNotFoundException); + $this->client->expects()->batchDeleteMessage(['QueueName' => $this->queueName, 'ReceiptHandles' => ['ReceiptHandle' => [$this->mockedReceiptHandle]]])->andReturns($this->mockedBatchDeleteMessageResult); $deleted = $queue->clear($this->queueName); expect($deleted)->toBe(1); }); test('clear empty queue', function () { - $queue = new MnsQueue($this->mns, $this->queueName); - $this->mns->expects()->batchReceiveMessage($this->queueName, ['numOfMessages' => '16', 'waitseconds' => '30'])->andReturns($this->mockedBatchMessageNotFoundResult); + $queue = new MnsQueue($this->console, $this->client, $this->queueName); + $this->client->expects()->batchReceiveMessage(['QueueName' => $this->queueName, 'numOfMessages' => '16', 'waitseconds' => '30'])->andThrows($this->mockedBatchMessageNotFoundException); $deleted = $queue->clear($this->queueName); expect($deleted)->toBe(0); }); From f021f3352a709420ad8eeeb8139d9eb94d178eb9 Mon Sep 17 00:00:00 2001 From: Li Zhineng Date: Tue, 24 Dec 2024 21:23:48 +0800 Subject: [PATCH 3/9] drop php 8.1 --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0257f63..cc44b4a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,7 +10,7 @@ jobs: strategy: matrix: - php: ['8.1', '8.2'] + php: ['8.2'] dependency-version: [prefer-lowest, prefer-stable] name: PHP ${{ matrix.php }} - ${{ matrix.dependency-version }} From a37c617ef0d7298c205b057490985ac7313fd51e Mon Sep 17 00:00:00 2001 From: Li Zhineng Date: Tue, 24 Dec 2024 21:33:02 +0800 Subject: [PATCH 4/9] remove mns package --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index a231d1c..45fbb6c 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,6 @@ "php": "^8.0", "illuminate/contracts": "^10.0", "illuminate/queue": "^10.0", - "dew-serverless/mns": "^1.1", "dew-serverless/acs-sdk-php": "dev-mns-queue" }, "require-dev": { From 1a99c73f0a4a98d4699422ae6e4187da47562a3a Mon Sep 17 00:00:00 2001 From: Li Zhineng Date: Tue, 24 Dec 2024 21:36:31 +0800 Subject: [PATCH 5/9] deny discovery plugin --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 45fbb6c..6e7ebf3 100644 --- a/composer.json +++ b/composer.json @@ -44,7 +44,8 @@ }, "config": { "allow-plugins": { - "pestphp/pest-plugin": true + "pestphp/pest-plugin": true, + "php-http/discovery": false } }, "extra": { From 1a7b08a3021ee93aafcc9aa4b1d77d811e348457 Mon Sep 17 00:00:00 2001 From: Li Zhineng Date: Tue, 24 Dec 2024 22:01:44 +0800 Subject: [PATCH 6/9] requires php 8.2 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 6e7ebf3..9a59a30 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ } ], "require": { - "php": "^8.0", + "php": "^8.2", "illuminate/contracts": "^10.0", "illuminate/queue": "^10.0", "dew-serverless/acs-sdk-php": "dev-mns-queue" From 580af9463e3765b2ac2733f3052ab26d0a3ef6f9 Mon Sep 17 00:00:00 2001 From: Li Zhineng Date: Tue, 24 Dec 2024 22:02:26 +0800 Subject: [PATCH 7/9] add php 8.3 and 8.4 to ci --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index cc44b4a..fed30ce 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,7 +10,7 @@ jobs: strategy: matrix: - php: ['8.2'] + php: ['8.2', '8.3', '8.4'] dependency-version: [prefer-lowest, prefer-stable] name: PHP ${{ matrix.php }} - ${{ matrix.dependency-version }} From a5a75f315040a711f7285ca0ba8381354cf4c22b Mon Sep 17 00:00:00 2001 From: Li Zhineng Date: Wed, 25 Dec 2024 11:19:58 +0800 Subject: [PATCH 8/9] use `expects()` syntax --- tests/MnsQueueTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/MnsQueueTest.php b/tests/MnsQueueTest.php index e8ead64..41e7dcb 100644 --- a/tests/MnsQueueTest.php +++ b/tests/MnsQueueTest.php @@ -80,7 +80,7 @@ }); test('queue size includes active, inactive and delayed messages', function () { - $this->console->shouldReceive('getQueueAttributes')->with(['QueueName' => $this->queueName])->once()->andReturn($this->mockedGetQueueAttributesResult); + $this->console->expects()->getQueueAttributes(['QueueName' => $this->queueName])->andReturns($this->mockedGetQueueAttributesResult); $queue = new MnsQueue($this->console, $this->client, $this->queueName); expect($queue->size())->toBe($this->mockedActiveMessages + $this->mockedInactiveMessages + $this->mockedDelayMessages); }); @@ -89,7 +89,7 @@ $queue = $this->getMockBuilder(MnsQueue::class)->onlyMethods(['createPayload'])->setConstructorArgs([$this->console, $this->client, $this->queueName])->getMock(); $queue->setContainer($container = Mockery::spy(Container::class)); $queue->expects($this->once())->method('createPayload')->with($this->mockedJob, $this->queueName, $this->mockedData)->willReturn($this->mockedPayload); - $this->client->shouldReceive('sendMessage')->with(['QueueName' => $this->queueName, 'Message' => ['MessageBody' => $this->mockedPayload]])->andReturn($this->mockedSendMessageResult); + $this->client->expects()->sendMessage(['QueueName' => $this->queueName, 'Message' => ['MessageBody' => $this->mockedPayload]])->andReturns($this->mockedSendMessageResult); $id = $queue->push($this->mockedJob, $this->mockedData, $this->queueName); expect($id)->toBe($this->mockedMessageId); $container->shouldHaveReceived('bound')->with('events'); @@ -99,7 +99,7 @@ $queue = $this->getMockBuilder(MnsQueue::class)->onlyMethods(['createPayload'])->setConstructorArgs([$this->console, $this->client, $this->queueName])->getMock(); $queue->setContainer($container = Mockery::spy(Container::class)); $queue->expects($this->once())->method('createPayload')->with($this->mockedJob, $this->queueName, $this->mockedData)->willReturn($this->mockedPayload); - $this->client->shouldReceive('sendMessage')->with(['QueueName' => $this->queueName, 'Message' => ['MessageBody' => $this->mockedPayload, 'DelaySeconds' => $this->mockedDelay]])->once()->andReturn($this->mockedSendMessageResult); + $this->client->expects()->sendMessage(['QueueName' => $this->queueName, 'Message' => ['MessageBody' => $this->mockedPayload, 'DelaySeconds' => $this->mockedDelay]])->andReturns($this->mockedSendMessageResult); $id = $queue->later($this->mockedDelay, $this->mockedJob, $this->mockedData, $this->queueName); expect($id)->toBe($this->mockedMessageId); $container->shouldHaveReceived('bound')->with('events'); @@ -110,7 +110,7 @@ $queue = $this->getMockBuilder(MnsQueue::class)->onlyMethods(['createPayload'])->setConstructorArgs([$this->console, $this->client, $this->queueName])->getMock(); $queue->setContainer($container = Mockery::spy(Container::class)); $queue->expects($this->once())->method('createPayload')->with($this->mockedJob, $this->queueName, $this->mockedData)->willReturn($this->mockedPayload); - $this->client->shouldReceive('sendMessage')->with(['QueueName' => $this->queueName, 'Message' => ['MessageBody' => $this->mockedPayload, 'DelaySeconds' => $this->mockedDelay]])->once()->andReturn($this->mockedSendMessageResult); + $this->client->expects()->sendMessage(['QueueName' => $this->queueName, 'Message' => ['MessageBody' => $this->mockedPayload, 'DelaySeconds' => $this->mockedDelay]])->andReturns($this->mockedSendMessageResult); $id = $queue->later($now->addSeconds($this->mockedDelay), $this->mockedJob, $this->mockedData, $this->queueName); expect($id)->toBe($this->mockedMessageId); $container->shouldHaveReceived('bound')->with('events'); From 0884a69619ff34376ee0dcf0dcbc1aaad5442d1c Mon Sep 17 00:00:00 2001 From: Li Zhineng Date: Wed, 25 Dec 2024 11:24:17 +0800 Subject: [PATCH 9/9] md5 --- tests/MnsQueueTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/MnsQueueTest.php b/tests/MnsQueueTest.php index 41e7dcb..dd862af 100644 --- a/tests/MnsQueueTest.php +++ b/tests/MnsQueueTest.php @@ -38,14 +38,14 @@ $this->mockedSendMessageResult = new SendMessageResult(new Result([ 'Message' => [ 'MessageId' => $this->mockedMessageId, - 'MessageBodyMD5' => hash('md5', $this->mockedPayload), + 'MessageBodyMD5' => md5($this->mockedPayload), ], ])); $this->mockedReceiveMessage = [ 'MessageId' => $this->mockedMessageId, 'MessageBody' => $this->mockedPayload, - 'MessageBodyMD5' => hash('md5', $this->mockedPayload), + 'MessageBodyMD5' => md5($this->mockedPayload), 'ReceiptHandle' => $this->mockedReceiptHandle, 'EnqueueTime' => '1250700979248', 'NextVisibleTime' => '1250700799348',