├── .gitignore ├── .scrutinizer.yml ├── .travis.yml ├── LICENSE ├── README.md ├── composer.json ├── config └── rocketmq.php ├── phpunit.xml.dist ├── src ├── LaravelQueueRocketMQServiceProvider.php └── Queue │ ├── Connectors │ └── RocketMQConnector.php │ ├── Contracts │ └── PlainPayload.php │ ├── Jobs │ └── RocketMQJob.php │ └── RocketMQQueue.php └── tests └── RocketMQQueueTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /composer.lock 3 | /vendor 4 | .idea 5 | -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | tools: 2 | # external_code_coverage: true 3 | php_mess_detector: true 4 | php_code_sniffer: true 5 | sensiolabs_security_checker: true 6 | # php_code_coverage: true 7 | php_pdepend: true 8 | php_loc: 9 | enabled: true 10 | excluded_dirs: [vendor, tests] 11 | checks: 12 | php: 13 | code_rating: true 14 | duplication: true 15 | filter: 16 | excluded_paths: 17 | - 'tests/*' 18 | build: 19 | tests: 20 | override: 21 | - 22 | command: vendor/bin/phpunit --coverage-clover my-coverage-file 23 | coverage: 24 | file: my-coverage-file 25 | format: php-clover 26 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 7.0 5 | - 7.1 6 | - 7.2 7 | 8 | sudo: false 9 | 10 | install: travis_retry composer install --no-interaction --prefer-source 11 | 12 | script: vendor/bin/phpunit --verbose 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 freyo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

3 | 4 |

5 |

AlibabaMQ(Apache RocketMQ) Driver for Laravel Queue

6 |

7 | 8 | Software License 9 | 10 | 11 | Build Status 12 | 13 | 14 | Coverage Status 15 | 16 | 17 | Quality Score 18 | 19 | 20 | Packagist Version 21 | 22 | 23 | Total Downloads 24 | 25 |

26 |

27 | 28 | FOSSA Status 29 | 30 |

31 |
32 | 33 | ## Installation 34 | 35 | ```shell 36 | composer require freyo/laravel-queue-rocketmq 37 | ``` 38 | 39 | ## Configure 40 | 41 | **Laravel 5.5+ uses Package Auto-Discovery, so doesn't require you to manually add the ServiceProvider.** 42 | 43 | 1. `config/app.php`: 44 | 45 | ```php 46 | 'providers' => [ 47 | // ... 48 | Freyo\LaravelQueueRocketMQ\LaravelQueueRocketMQServiceProvider::class, 49 | ] 50 | ``` 51 | 52 | 2. `.env`: 53 | 54 | ``` 55 | QUEUE_DRIVER=rocketmq 56 | 57 | ROCKETMQ_ACCESS_KEY=your-access-key 58 | ROCKETMQ_ACCESS_ID=your-access-id 59 | 60 | ROCKETMQ_ENDPOINT=http://***.mqrest.***.aliyuncs.com 61 | ROCKETMQ_INSTANCE_ID=MQ_INST_***_*** 62 | ROCKETMQ_GROUP_ID=GID_*** 63 | 64 | ROCKETMQ_QUEUE=topic_name # default topic name 65 | 66 | ROCKETMQ_USE_MESSAGE_TAG=false # set to true to use message tag 67 | ROCKETMQ_WAIT_SECONDS=0 68 | ``` 69 | 70 | ## Usage 71 | 72 | Once you completed the configuration you can use Laravel Queue API. If you used other queue drivers you do not need to change anything else. If you do not know how to use Queue API, please refer to the official Laravel documentation: http://laravel.com/docs/queues 73 | 74 | ### Example 75 | 76 | #### Dispatch Jobs 77 | 78 | The default connection name is `rocketmq` 79 | 80 | ```php 81 | // Without message tag (ROCKETMQ_USE_MESSAGE_TAG=false) 82 | Job::dispatch()->onConnection('connection-name')->onQueue('TopicTestMQ'); 83 | // or dispatch((new Job())->onConnection('connection-name')->onQueue('TopicTestMQ')) 84 | 85 | // With message tag (ROCKETMQ_USE_MESSAGE_TAG=true) 86 | Job::dispatch()->onConnection('connection-name')->onQueue('TagA'); 87 | // or dispatch((new Job())->onConnection('connection-name')->onQueue('TagA')) 88 | ``` 89 | 90 | #### Multiple Queues 91 | 92 | Configure `config/queue.php` 93 | 94 | ```php 95 | 'connections' => [ 96 | //... 97 | 'new-connection-name' => [ 98 | 'driver' => 'rocketmq', 99 | 'access_key' => 'your-access-key', 100 | 'access_id' => 'your-access-id', 101 | 'endpoint' => 'http://***.mqrest.***.aliyuncs.com', 102 | 'instance_id' => 'MQ_INST_***_***', 103 | 'group_id' => 'GID_***', 104 | 'queue' => 'your-default-topic-name', 105 | 'use_message_tag' => false, 106 | 'wait_seconds' => 0, 107 | 'plain' => [ 108 | 'enable' => false, 109 | 'job' => 'App\Jobs\RocketMQPlainJobHandler@handle', 110 | ], 111 | ]; 112 | //... 113 | ]; 114 | ``` 115 | 116 | #### Process Jobs 117 | 118 | ```bash 119 | php artisan queue:work {connection-name} --queue={queue-name} 120 | ``` 121 | 122 | #### Plain Mode 123 | 124 | Configure `.env` 125 | 126 | ``` 127 | ROCKETMQ_PLAIN_ENABLE=true 128 | ROCKETMQ_PLAIN_JOB=App\Jobs\RocketMQPlainJob@handle 129 | ``` 130 | 131 | Create a job implements `PlainPayload` interface. The method `getPayload` must return a sting value. 132 | 133 | ```php 134 | payload = $payload; 158 | } 159 | 160 | /** 161 | * Get the plain payload of the job. 162 | * 163 | * @return string 164 | */ 165 | public function getPayload() 166 | { 167 | return $this->payload; 168 | } 169 | } 170 | ``` 171 | 172 | Create a plain job handler 173 | 174 | ```php 175 | release(); 198 | 199 | // delete message when processed. 200 | if (! $job->isDeletedOrReleased()) { 201 | $job->delete(); 202 | } 203 | } 204 | } 205 | ``` 206 | 207 | ## References 208 | 209 | - [Product Documentation](https://www.alibabacloud.com/product/mq) 210 | 211 | ## License 212 | 213 | The MIT License (MIT). Please see [License File](LICENSE) for more information. 214 | 215 | [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Ffreyo%2Flaravel-queue-rocketmq.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Ffreyo%2Flaravel-queue-rocketmq?ref=badge_large) 216 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "freyo/laravel-queue-rocketmq", 3 | "description": "Queue Adapter for AlibabaMQ(Apache RocketMQ) SDK", 4 | "keywords": ["laravel-queue", "rocketmq", "aliyun", "alibabamq"], 5 | "require": { 6 | "php": ">=5.6.4", 7 | "illuminate/queue": "5.2.*|5.3.*|5.4.*|5.5.*|5.6.*|5.7.*|5.8.*", 8 | "ext-json": "*", 9 | "ext-curl": "*", 10 | "aliyunmq/mq-http-sdk": "^1.0", 11 | "guzzlehttp/guzzle": "^6.0.0" 12 | }, 13 | "require-dev": { 14 | "php": "^7.0", 15 | "phpunit/phpunit": ">=6.0.0", 16 | "vlucas/phpdotenv": "^3.3", 17 | "mockery/mockery": "^1.2.3" 18 | }, 19 | "autoload": { 20 | "psr-4": { 21 | "Freyo\\LaravelQueueRocketMQ\\": "src/" 22 | } 23 | }, 24 | "autoload-dev": { 25 | "psr-4": { 26 | "Freyo\\LaravelQueueRocketMQ\\Tests\\": "tests" 27 | } 28 | }, 29 | "license": "MIT", 30 | "authors": [ 31 | { 32 | "name": "freyo", 33 | "email": "freyhsiao@gmail.com" 34 | } 35 | ], 36 | "minimum-stability": "dev", 37 | "extra": { 38 | "laravel": { 39 | "providers": [ 40 | "Freyo\\LaravelQueueRocketMQ\\LaravelQueueRocketMQServiceProvider" 41 | ] 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /config/rocketmq.php: -------------------------------------------------------------------------------- 1 | 'rocketmq', 11 | 12 | 'access_key' => env('ROCKETMQ_ACCESS_KEY', 'your-access-key'), 13 | 'access_id' => env('ROCKETMQ_ACCESS_ID', 'your-access-id'), 14 | 15 | 'endpoint' => env('ROCKETMQ_ENDPOINT'), 16 | 'instance_id' => env('ROCKETMQ_INSTANCE_ID'), 17 | 'group_id' => env('ROCKETMQ_GROUP_ID'), 18 | 19 | 'queue' => env('ROCKETMQ_QUEUE', 'default'), 20 | 21 | 'use_message_tag' => env('ROCKETMQ_USE_MESSAGE_TAG', false), 22 | 'wait_seconds' => env('ROCKETMQ_WAIT_SECONDS', 0), 23 | 24 | 'plain' => [ 25 | 'enable' => env('ROCKETMQ_PLAIN_ENABLE', false), 26 | 'job' => env('ROCKETMQ_PLAIN_JOB', 'App\Jobs\RocketMQPlainJobHandler@handle'), 27 | ], 28 | 29 | ]; 30 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | ./tests/ 14 | 15 | 16 | 17 | 18 | src/ 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/LaravelQueueRocketMQServiceProvider.php: -------------------------------------------------------------------------------- 1 | app instanceof LumenApplication) { 20 | $this->app->configure('queue'); 21 | } 22 | 23 | $this->mergeConfigFrom( 24 | __DIR__.'/../config/rocketmq.php', 'queue.connections.rocketmq' 25 | ); 26 | } 27 | 28 | /** 29 | * Register the application's event listeners. 30 | * 31 | * @return void 32 | */ 33 | public function boot() 34 | { 35 | /** @var QueueManager $queue */ 36 | $queue = $this->app['queue']; 37 | 38 | $queue->addConnector('rocketmq', function () { 39 | return new RocketMQConnector(); 40 | }); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Queue/Connectors/RocketMQConnector.php: -------------------------------------------------------------------------------- 1 | container = $container; 40 | $this->connection = $connection; 41 | $this->message = $message; 42 | $this->queue = $queue; 43 | $this->connectionName = $connectionName; 44 | } 45 | 46 | /** 47 | * Get the job identifier. 48 | * 49 | * @return string 50 | */ 51 | public function getJobId() 52 | { 53 | return $this->message->getMessageId(); 54 | } 55 | 56 | /** 57 | * Get the raw body of the job. 58 | * 59 | * @return string 60 | */ 61 | public function getRawBody() 62 | { 63 | return $this->message->getMessageBody(); 64 | } 65 | 66 | /** 67 | * Get the number of times the job has been attempted. 68 | * 69 | * @return int 70 | */ 71 | public function attempts() 72 | { 73 | return $this->message->getConsumedTimes(); 74 | } 75 | 76 | /** 77 | * Fire the job. 78 | * 79 | * @return void 80 | */ 81 | public function fire() 82 | { 83 | method_exists($this, 'resolveAndFire') 84 | ? $this->resolveAndFire($this->payload()) 85 | : parent::fire(); 86 | } 87 | 88 | /** 89 | * Get the decoded body of the job. 90 | * 91 | * @return array 92 | */ 93 | public function payload() 94 | { 95 | if ($this->connection->isPlain()) { 96 | $job = $this->connection->getPlainJob(); 97 | 98 | return [ 99 | 'displayName' => is_string($job) ? explode('@', $job)[0] : null, 100 | 'job' => $job, 101 | 'maxTries' => null, 102 | 'timeout' => null, 103 | 'data' => $this->getRawBody(), 104 | ]; 105 | } 106 | 107 | return json_decode($this->getRawBody(), true); 108 | } 109 | 110 | /** 111 | * Delete the job from the queue. 112 | * 113 | * @return void 114 | */ 115 | public function delete() 116 | { 117 | parent::delete(); 118 | 119 | $this->connection 120 | ->getConsumer($this->getQueue()) 121 | ->ackMessage([$this->message->getReceiptHandle()]); 122 | } 123 | 124 | /** 125 | * Release the job back into the queue. 126 | * 127 | * @param int $delay 128 | * 129 | * @return void 130 | */ 131 | public function release($delay = 0) 132 | { 133 | parent::release($delay); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/Queue/RocketMQQueue.php: -------------------------------------------------------------------------------- 1 | client = $client; 41 | $this->config = $config; 42 | 43 | $this->createPayload = new \ReflectionMethod($this, 'createPayload'); 44 | } 45 | 46 | /** 47 | * @return bool 48 | */ 49 | public function isPlain() 50 | { 51 | return (bool)Arr::get($this->config, 'plain.enable'); 52 | } 53 | 54 | /** 55 | * @return string 56 | */ 57 | public function getPlainJob() 58 | { 59 | return Arr::get($this->config, 'plain.job'); 60 | } 61 | 62 | /** 63 | * Get the size of the queue. 64 | * 65 | * @param string $queue 66 | * 67 | * @return int 68 | */ 69 | public function size($queue = null) 70 | { 71 | return 1; 72 | } 73 | 74 | /** 75 | * Push a new job onto the queue. 76 | * 77 | * @param string|object $job 78 | * @param mixed $data 79 | * @param string $queue 80 | * 81 | * @throws \Exception 82 | * 83 | * @return mixed 84 | */ 85 | public function push($job, $data = '', $queue = null) 86 | { 87 | if ($this->isPlain()) { 88 | return $this->pushRaw($job->getPayload(), $queue); 89 | } 90 | 91 | $payload = $this->createPayload->getNumberOfParameters() === 3 92 | ? $this->createPayload($job, $queue, $data) // version >= 5.7 93 | : $this->createPayload($job, $data); 94 | 95 | return $this->pushRaw($payload, $queue); 96 | } 97 | 98 | /** 99 | * Push a raw payload onto the queue. 100 | * 101 | * @param string $payload 102 | * @param string $queue 103 | * @param array $options 104 | * 105 | * @throws \Exception 106 | * 107 | * @return TopicMessage 108 | */ 109 | public function pushRaw($payload, $queue = null, array $options = []) 110 | { 111 | $message = new TopicMessage($payload); 112 | 113 | if ($this->config['use_message_tag'] && $queue) { 114 | $message->setMessageTag($queue); 115 | } 116 | 117 | if ($delay = Arr::get($options, 'delay', 0)) { 118 | $message->setStartDeliverTime(time() * 1000 + $delay * 1000); 119 | } 120 | 121 | return $this->getProducer( 122 | $this->config['use_message_tag'] ? $this->config['queue'] : $queue 123 | )->publishMessage($message); 124 | } 125 | 126 | /** 127 | * Push a new job onto the queue after a delay. 128 | * 129 | * @param \DateTimeInterface|\DateInterval|int $delay 130 | * @param string|object $job 131 | * @param mixed $data 132 | * @param string $queue 133 | * 134 | * @throws \Exception 135 | * 136 | * @return mixed 137 | */ 138 | public function later($delay, $job, $data = '', $queue = null) 139 | { 140 | $delay = method_exists($this, 'getSeconds') 141 | ? $this->getSeconds($delay) 142 | : $this->secondsUntil($delay); 143 | 144 | if ($this->isPlain()) { 145 | return $this->pushRaw($job->getPayload(), $queue, ['delay' => $delay]); 146 | } 147 | 148 | $payload = $this->createPayload->getNumberOfParameters() === 3 149 | ? $this->createPayload($job, $queue, $data) // version >= 5.7 150 | : $this->createPayload($job, $data); 151 | 152 | return $this->pushRaw($payload, $queue, ['delay' => $delay]); 153 | } 154 | 155 | /** 156 | * Pop the next job off of the queue. 157 | * 158 | * @param string $queue 159 | * 160 | * @return \Illuminate\Contracts\Queue\Job|null 161 | * 162 | * @throws \Exception 163 | */ 164 | public function pop($queue = null) 165 | { 166 | try { 167 | 168 | $consumer = $this->config['use_message_tag'] 169 | ? $this->getConsumer($this->config['queue'], $queue) 170 | : $this->getConsumer($queue); 171 | 172 | /** @var array $messages */ 173 | $messages = $consumer->consumeMessage(1, $this->config['wait_seconds']); 174 | 175 | } catch (\Exception $e) { 176 | if ($e instanceof \MQ\Exception\MessageNotExistException) { 177 | return null; 178 | } 179 | 180 | throw $e; 181 | } 182 | 183 | return new RocketMQJob( 184 | $this->container ?: Container::getInstance(), 185 | $this, 186 | Arr::first($messages), 187 | $this->config['use_message_tag'] ? $this->config['queue'] : $queue, 188 | $this->connectionName ?? null 189 | ); 190 | } 191 | 192 | /** 193 | * Get the consumer. 194 | * 195 | * @param string $topicName 196 | * @param string $messageTag 197 | * 198 | * @return \MQ\MQConsumer 199 | */ 200 | public function getConsumer($topicName = null, $messageTag = null) 201 | { 202 | return $this->client->getConsumer( 203 | $this->config['instance_id'], 204 | $topicName ?: $this->config['queue'], 205 | $this->config['group_id'], 206 | $messageTag 207 | ); 208 | } 209 | 210 | /** 211 | * Get the producer. 212 | * 213 | * @param string $topicName 214 | * 215 | * @return \MQ\MQProducer 216 | */ 217 | public function getProducer($topicName = null) 218 | { 219 | return $this->client->getProducer( 220 | $this->config['instance_id'], 221 | $topicName ?: $this->config['queue'] 222 | ); 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /tests/RocketMQQueueTest.php: -------------------------------------------------------------------------------- 1 | 'rocketmq', 22 | 23 | 'access_key' => env('ROCKETMQ_ACCESS_KEY', 'your-access-key'), 24 | 'access_id' => env('ROCKETMQ_ACCESS_ID', 'your-access-id'), 25 | 26 | 'endpoint' => env('ROCKETMQ_ENDPOINT'), 27 | 'instance_id' => env('ROCKETMQ_INSTANCE_ID'), 28 | 'group_id' => env('ROCKETMQ_GROUP_ID'), 29 | 30 | 'queue' => env('ROCKETMQ_QUEUE', 'default'), 31 | 32 | 'use_message_tag' => env('ROCKETMQ_USE_MESSAGE_TAG', false), 33 | 'wait_seconds' => env('ROCKETMQ_WAIT_SECONDS', 0), 34 | 35 | 'plain' => [ 36 | 'enable' => env('ROCKETMQ_PLAIN_ENABLE', false), 37 | 'job' => env('ROCKETMQ_PLAIN_JOB', 'App\Jobs\CMQPlainJob@handle'), 38 | ], 39 | 40 | ]; 41 | 42 | $connector = new RocketMQConnector(); 43 | 44 | $queue = $connector->connect($config); 45 | 46 | return [ 47 | [$queue, $config], 48 | ]; 49 | } 50 | 51 | /** 52 | * @dataProvider provider 53 | */ 54 | public function testIsPlain(RocketMQQueue $queue, $config) 55 | { 56 | $this->assertSame($config['plain']['enable'], $queue->isPlain()); 57 | } 58 | 59 | /** 60 | * @dataProvider provider 61 | */ 62 | public function testGetPlainJob(RocketMQQueue $queue, $config) 63 | { 64 | $this->assertSame($config['plain']['job'], $queue->getPlainJob()); 65 | } 66 | 67 | /** 68 | * @dataProvider provider 69 | */ 70 | public function testSize(RocketMQQueue $queue, $config) 71 | { 72 | $this->assertGreaterThanOrEqual(1, $queue->size()); 73 | } 74 | 75 | /** 76 | * @dataProvider provider 77 | */ 78 | public function testPush(RocketMQQueue $queue, $config) 79 | { 80 | $queue = \Mockery::mock(RocketMQQueue::class) 81 | ->shouldAllowMockingProtectedMethods(); 82 | 83 | $queue->expects() 84 | ->push('App\Jobs\RocketMQJob@handle') 85 | ->andReturn(new TopicMessage('MockMessageBody')); 86 | 87 | $this->assertInstanceOf( 88 | TopicMessage::class, $queue->push('App\Jobs\RocketMQJob@handle') 89 | ); 90 | } 91 | 92 | /** 93 | * @dataProvider provider 94 | */ 95 | public function testPushRaw(RocketMQQueue $queue, $config) 96 | { 97 | $queue = \Mockery::mock(RocketMQQueue::class) 98 | ->shouldAllowMockingProtectedMethods(); 99 | 100 | $queue->expects() 101 | ->pushRaw('App\Jobs\RocketMQJob@handle') 102 | ->andReturn(new TopicMessage('MockMessageBody')); 103 | 104 | $this->assertInstanceOf( 105 | TopicMessage::class, $queue->pushRaw('App\Jobs\RocketMQJob@handle') 106 | ); 107 | } 108 | 109 | /** 110 | * @dataProvider provider 111 | */ 112 | public function testLater(RocketMQQueue $queue, $config) 113 | { 114 | $queue = \Mockery::mock(RocketMQQueue::class) 115 | ->shouldAllowMockingProtectedMethods(); 116 | 117 | $queue->expects() 118 | ->later(0, 'App\Jobs\RocketMQJob@handle') 119 | ->andReturn(new TopicMessage('MockMessageBody')); 120 | 121 | $this->assertInstanceOf( 122 | TopicMessage::class, $queue->later(0, 'App\Jobs\RocketMQJob@handle') 123 | ); 124 | } 125 | 126 | /** 127 | * @dataProvider provider 128 | */ 129 | public function testPop(RocketMQQueue $queue, $config) 130 | { 131 | $client = \Mockery::mock(RocketMQQueue::class) 132 | ->shouldAllowMockingProtectedMethods(); 133 | 134 | $client->expects() 135 | ->pop() 136 | ->andReturn( 137 | \Mockery::mock(RocketMQJob::class) 138 | ); 139 | 140 | $this->assertInstanceOf(RocketMQJob::class, $client->pop()); 141 | } 142 | 143 | /** 144 | * @dataProvider provider 145 | */ 146 | public function testGetConsumer(RocketMQQueue $queue, $config) 147 | { 148 | $this->assertInstanceOf(MQConsumer::class, $queue->getConsumer()); 149 | } 150 | 151 | /** 152 | * @dataProvider provider 153 | */ 154 | public function testGetProducer(RocketMQQueue $queue, $config) 155 | { 156 | $this->assertInstanceOf(MQProducer::class, $queue->getProducer()); 157 | } 158 | } 159 | --------------------------------------------------------------------------------