├── test.sh ├── .gitignore ├── test-coverage.sh ├── ISSUE_TEMPLATE.md ├── RELEASE-CHECKLIST.md ├── CONTRIBUTING.rst ├── tests ├── Fixtures │ └── ListMessagesResult.php ├── TestCase.php ├── AzureQueueServiceProviderTest.php ├── AzureJobTest.php ├── AzureConnectorTest.php └── AzureQueueTest.php ├── src ├── AzureQueueServiceProvider.php ├── AzureConnector.php ├── AzureJob.php └── AzureQueue.php ├── phpunit.xml ├── composer.json ├── .github └── workflows │ └── workflow.yaml └── README.md /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eu 3 | cd $(dirname $0) 4 | 5 | vendor/bin/phpunit "$@" 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | composer.phar 3 | composer.lock 4 | .DS_Store 5 | .idea 6 | /test-coverage/ 7 | .phpunit.result.cache 8 | .phpunit.cache 9 | clover.xml 10 | -------------------------------------------------------------------------------- /test-coverage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eu 3 | cd $(dirname $0) 4 | 5 | php -dzend_extension=xdebug.so -d xdebug.coverage_enable=On vendor/bin/phpunit --coverage-html test-coverage "$@" 6 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | (For support requests / bug reports, please complete the following - or delete if not applicable.) 2 | 3 | **Summary of issue** 4 | 5 | 6 | **The complete error message, including file & line numbers** 7 | 8 | 9 | **Copy of your config/queue.php file ** 10 | 11 | 12 | **Software versions** 13 | This Package: 14 | Laravel: 15 | PHP: 16 | Operating System: Windows / Linux / MacOS 17 | 18 | **Any other information** 19 | -------------------------------------------------------------------------------- /RELEASE-CHECKLIST.md: -------------------------------------------------------------------------------- 1 | # Release Checklist 2 | 3 | - [ ] Ensure the documentation is up to date, particularly the changelog 4 | - [ ] Merge the `develop` branch into the `master` branch (`git checkout master; git merge develop`) 5 | - [ ] Push the code changes to GitHub (`git push`) 6 | - [ ] Check the [Travis CI results](https://travis-ci.org/squigg/azure-queue-laravel) 7 | - [ ] Tag the release (`git tag 1.2.3`) 8 | - [ ] Push the tag (`git push --tag`) 9 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | Support & Contribution Guidelines 3 | ################################################################################ 4 | 5 | .. This file is for GitHub (https://github.com/blog/1184-contributing-guidelines) 6 | 7 | Before submitting a support request, bug report, feature request or pull request, please take a moment to read the instructions in the `README `_ file. Thank you. 8 | -------------------------------------------------------------------------------- /tests/Fixtures/ListMessagesResult.php: -------------------------------------------------------------------------------- 1 | count = $count; 14 | } 15 | 16 | public function getQueueMessages(): array 17 | { 18 | if ($this->count == 0) return []; 19 | return array_fill(0, $this->count, new QueueMessage()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/AzureQueueServiceProvider.php: -------------------------------------------------------------------------------- 1 | app['queue']; 20 | 21 | $manager->addConnector('azure', function () { 22 | return new AzureConnector; 23 | }); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | src 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | tests 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | addToAssertionCount(Mockery::getContainer()->mockery_getExpectationCount()); 27 | Mockery::close(); 28 | HandleExceptions::flushState(); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/AzureConnector.php: -------------------------------------------------------------------------------- 1 | shouldReceive('addConnector')->withArgs(function ($driver, $closure) { 21 | return $driver == 'azure' && ($closure() instanceof AzureConnector); 22 | }); 23 | 24 | $mockApp->shouldReceive('offsetGet')->with('queue')->andReturn($mockQueueManager); 25 | 26 | $serviceProvider = new AzureQueueServiceProvider($mockApp); 27 | 28 | $serviceProvider->boot(); 29 | 30 | $this->assertTrue(true); 31 | 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "squigg/azure-queue-laravel", 3 | "description": "Laravel Queue Driver for Microsoft Azure Storage Queue", 4 | "keywords": [ 5 | "laravel", 6 | "azure", 7 | "storage", 8 | "queue", 9 | "microsoft" 10 | ], 11 | "license": "MIT", 12 | "authors": [ 13 | { 14 | "name": "Steve Strugnell", 15 | "email": "github@squigg.co.uk" 16 | } 17 | ], 18 | "require": { 19 | "php": "^8.1", 20 | "illuminate/queue": "^10.0|^11.0|^12.0", 21 | "microsoft/azure-storage-queue": "~1.3.0" 22 | }, 23 | "require-dev": { 24 | "phpunit/phpunit": "^10.0|^11.5.3", 25 | "orchestra/testbench": "^8.0|^9.0|^10.0", 26 | "mockery/mockery": "~1.0", 27 | "php-coveralls/php-coveralls": "~2.0", 28 | "ext-json": "*" 29 | }, 30 | "scripts": { 31 | "test": "phpunit" 32 | }, 33 | "autoload": { 34 | "psr-4": { 35 | "Squigg\\AzureQueueLaravel\\": "src/" 36 | } 37 | }, 38 | "autoload-dev": { 39 | "psr-4": { 40 | "Squigg\\AzureQueueLaravel\\Tests\\": "tests/" 41 | } 42 | }, 43 | "minimum-stability": "stable", 44 | "extra": { 45 | "laravel": { 46 | "providers": [ 47 | "Squigg\\AzureQueueLaravel\\AzureQueueServiceProvider" 48 | ] 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /.github/workflows/workflow.yaml: -------------------------------------------------------------------------------- 1 | name: azure-queue-laravel 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - "[1-9][0-9].x" 8 | pull_request: 9 | branches: 10 | - master 11 | 12 | jobs: 13 | tests: 14 | name: "${{matrix.os}} | PHP${{matrix.php}}" 15 | runs-on: ${{matrix.os}} 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | include: 20 | - php: '8.2' 21 | os: ubuntu-latest 22 | coverage: 'xdebug' 23 | - php: '8.3' 24 | os: ubuntu-latest 25 | coverage: 'xdebug' 26 | - php: '8.3' 27 | os: windows-latest 28 | coverage: 'xdebug' 29 | - php: '8.4' 30 | os: ubuntu-latest 31 | coverage: 'xdebug' 32 | - php: '8.4' 33 | os: windows-latest 34 | coverage: 'xdebug' 35 | 36 | steps: 37 | - name: PHP setup 38 | uses: shivammathur/setup-php@2.34.1 39 | with: 40 | php-version: ${{ matrix.php }} 41 | ini-values: zend.assertions=1, error_reporting=-1, display_errors=On, log_errors_max_len=0 42 | extensions: openssl, mbstring, tokenizer, xml, ctype, fileinfo, curl 43 | coverage: ${{ matrix.coverage || 'none' }} 44 | 45 | - name: Checkout source 46 | uses: actions/checkout@v4 47 | 48 | - name: Install Dependencies 49 | run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist 50 | 51 | - name: Run test suite 52 | run: php vendor/bin/phpunit 53 | 54 | - name: Coveralls Parallel 55 | uses: coverallsapp/github-action@v2 56 | with: 57 | flag-name: "${{matrix.os}} | PHP${{matrix.php}}" 58 | parallel: true 59 | 60 | coveralls-finish: 61 | needs: tests 62 | if: ${{ always() }} 63 | runs-on: ubuntu-latest 64 | steps: 65 | - name: Coveralls Finished 66 | uses: coverallsapp/github-action@v2 67 | with: 68 | parallel-finished: true 69 | -------------------------------------------------------------------------------- /tests/AzureJobTest.php: -------------------------------------------------------------------------------- 1 | azure = Mockery::mock(IQueue::class); 25 | $this->queue = new AzureQueue($this->azure, 'myqueue', 5); 26 | $this->queue->setContainer($this->app); 27 | 28 | $this->message = new QueueMessage(); 29 | $this->message->setMessageId('1234'); 30 | $this->message->setPopReceipt('9876'); 31 | $this->message->setMessageText('{"abcd":"efgh"}'); 32 | $this->message->setDequeueCount(2); 33 | 34 | $this->job = new AzureJob($this->app, $this->azure, $this->message, 'myconnection', 'myqueue'); 35 | } 36 | 37 | #[Test] 38 | public function it_can_get_job_id() 39 | { 40 | $this->assertEquals('1234', $this->job->getJobId()); 41 | } 42 | 43 | #[Test] 44 | public function it_can_delete_job_from_queue() 45 | { 46 | $this->azure->shouldReceive('deleteMessage')->once()->withArgs(['myqueue', '1234', '9876']); 47 | $this->job->delete(); 48 | } 49 | 50 | #[Test] 51 | public function it_can_release_job_back_to_queue() 52 | { 53 | $this->azure->shouldReceive('updateMessage')->once()->withArgs(['myqueue', '1234', '9876', null, 10]); 54 | $this->job->release(10); 55 | } 56 | 57 | #[Test] 58 | public function it_can_get_azure_job() 59 | { 60 | $this->assertEquals($this->message, $this->job->getAzureJob()); 61 | } 62 | 63 | #[Test] 64 | public function it_can_get_raw_body() 65 | { 66 | $this->assertEquals('{"abcd":"efgh"}', $this->job->getRawBody()); 67 | } 68 | 69 | #[Test] 70 | public function it_can_get_azure_proxy() 71 | { 72 | $this->assertInstanceOf(IQueue::class, $this->job->getAzure()); 73 | } 74 | 75 | #[Test] 76 | public function it_can_get_number_of_attempts() 77 | { 78 | $this->assertEquals(2, $this->job->attempts()); 79 | } 80 | 81 | #[Test] 82 | public function it_can_get_app_container() 83 | { 84 | $this->assertEquals($this->app, $this->job->getContainer()); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /tests/AzureConnectorTest.php: -------------------------------------------------------------------------------- 1 | config = [ 24 | 'protocol' => 'https', 25 | 'accountname' => 'foo', 26 | 'key' => 'bar', 27 | 'queue' => 'baz', 28 | 'timeout' => 25, 29 | ]; 30 | 31 | $this->connector = new AzureConnector(); 32 | $this->queueRestProxy = Mockery::mock('alias:' . QueueRestProxy::class); 33 | } 34 | 35 | #[Test] 36 | public function it_can_create_azure_queue() 37 | { 38 | $connectionString = 'DefaultEndpointsProtocol=https;AccountName=foo;AccountKey=bar'; 39 | $queueProxy = Mockery::mock(IQueue::class); 40 | 41 | $this->queueRestProxy->shouldReceive('createQueueService')->once()->with($connectionString)->andReturn($queueProxy); 42 | 43 | $azureQueue = $this->connector->connect($this->config); 44 | $this->assertEquals('baz', $azureQueue->getQueue(null)); 45 | $this->assertEquals(25, $azureQueue->getVisibilityTimeout()); 46 | } 47 | 48 | #[Test] 49 | public function it_can_create_azure_queue_with_endpoint() 50 | { 51 | $this->config['endpoint'] = 'mysuffix'; 52 | 53 | $connectionString = 'DefaultEndpointsProtocol=https;AccountName=foo;AccountKey=bar;EndpointSuffix=mysuffix'; 54 | $queueProxy = Mockery::mock(IQueue::class); 55 | $this->queueRestProxy->shouldReceive('createQueueService')->once()->with($connectionString)->andReturn($queueProxy); 56 | 57 | /** @var AzureQueue $azureQueue */ 58 | $this->connector->connect($this->config); 59 | } 60 | 61 | #[Test] 62 | public function it_can_create_azure_queue_with_queue_endpoint() 63 | { 64 | $this->config['queue_endpoint'] = 'http://localhost:10001/test'; 65 | 66 | $connectionString = 'DefaultEndpointsProtocol=https;AccountName=foo;AccountKey=bar;QueueEndpoint=http://localhost:10001/test'; 67 | $queueProxy = Mockery::mock(IQueue::class); 68 | $this->queueRestProxy->shouldReceive('createQueueService')->once()->with($connectionString)->andReturn($queueProxy); 69 | 70 | /** @var AzureQueue $azureQueue */ 71 | $this->connector->connect($this->config); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/AzureJob.php: -------------------------------------------------------------------------------- 1 | azure = $azure; 46 | $this->job = $job; 47 | $this->queue = $queue; 48 | $this->container = $container; 49 | $this->connectionName = $connectionName; 50 | } 51 | 52 | /** 53 | * Delete the job from the queue. 54 | */ 55 | public function delete(): void 56 | { 57 | parent::delete(); 58 | $this->azure->deleteMessage($this->queue, $this->job->getMessageId(), $this->job->getPopReceipt()); 59 | } 60 | 61 | /** 62 | * Release the job back into the queue. 63 | * 64 | * @param int $delay 65 | */ 66 | public function release($delay = 0): void 67 | { 68 | parent::release($delay); 69 | $this->azure->updateMessage($this->queue, $this->job->getMessageId(), $this->job->getPopReceipt(), null, 70 | $delay); 71 | } 72 | 73 | /** 74 | * Get the number of times the job has been attempted. 75 | */ 76 | public function attempts(): int 77 | { 78 | return $this->job->getDequeueCount(); 79 | } 80 | 81 | /** 82 | * Get the IoC container instance. 83 | */ 84 | public function getContainer(): Container 85 | { 86 | return $this->container; 87 | } 88 | 89 | /** 90 | * Get the underlying Azure client instance. 91 | */ 92 | public function getAzure(): IQueue 93 | { 94 | return $this->azure; 95 | } 96 | 97 | /** 98 | * Get the underlying raw Azure job. 99 | */ 100 | public function getAzureJob(): QueueMessage 101 | { 102 | return $this->job; 103 | } 104 | 105 | /** 106 | * Get the job ID 107 | */ 108 | public function getJobId(): string 109 | { 110 | return $this->job->getMessageId(); 111 | } 112 | 113 | /** 114 | * Get the raw body string for the job. 115 | */ 116 | public function getRawBody(): string 117 | { 118 | return $this->job->getMessageText(); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/AzureQueue.php: -------------------------------------------------------------------------------- 1 | azure = $azure; 40 | $this->default = $default; 41 | $this->visibilityTimeout = $visibilityTimeout ?: 5; 42 | } 43 | 44 | /** 45 | * Push a new job onto the queue. 46 | * 47 | * @param string $job 48 | * @param mixed $data 49 | * @param string $queue 50 | * 51 | * @return void 52 | */ 53 | public function push($job, $data = '', $queue = null): void 54 | { 55 | $this->pushRaw($this->createPayload($job, $queue, $data), $queue); 56 | } 57 | 58 | /** 59 | * Push a raw payload onto the queue. 60 | * 61 | * @param string $payload 62 | * @param string $queue 63 | * @param array $options 64 | * 65 | * @return void 66 | */ 67 | public function pushRaw($payload, $queue = null, array $options = []): void 68 | { 69 | $this->azure->createMessage($this->getQueue($queue), $payload); 70 | } 71 | 72 | /** 73 | * Push a new job onto the queue after (n) seconds. 74 | * 75 | * @param DateTime|int $delay 76 | * @param string $job 77 | * @param mixed $data 78 | * @param string $queue 79 | * 80 | * @return void 81 | */ 82 | public function later($delay, $job, $data = '', $queue = null): void 83 | { 84 | $payload = $this->createPayload($job, $queue, $data); 85 | 86 | $options = new CreateMessageOptions(); 87 | $options->setVisibilityTimeoutInSeconds($this->secondsUntil($delay)); 88 | 89 | $this->azure->createMessage($this->getQueue($queue), $payload, $options); 90 | } 91 | 92 | /** 93 | * Pop the next job off of the queue. 94 | * 95 | * @param string|null $queue 96 | * 97 | * @return AzureJob|null 98 | */ 99 | public function pop($queue = null): AzureJob|null 100 | { 101 | $queue = $this->getQueue($queue); 102 | 103 | // As recommended in the API docs, first call listMessages to hide message from other code 104 | $listMessagesOptions = new ListMessagesOptions(); 105 | $listMessagesOptions->setVisibilityTimeoutInSeconds($this->visibilityTimeout); 106 | $listMessagesOptions->setNumberOfMessages(1); 107 | 108 | $listMessages = $this->azure->listMessages($queue, $listMessagesOptions); 109 | $messages = $listMessages->getQueueMessages(); 110 | 111 | if (count($messages) > 0) { 112 | return new AzureJob($this->container, $this->azure, $messages[0], $this->connectionName, $queue); 113 | } 114 | 115 | return null; 116 | } 117 | 118 | /** 119 | * Get the queue or return the default. 120 | * 121 | * @param string|null $queue 122 | * 123 | * @return string 124 | */ 125 | public function getQueue(?string $queue): string 126 | { 127 | return $queue ?: $this->default; 128 | } 129 | 130 | /** 131 | * Get the visibility timeout for queue messages. 132 | * 133 | * @return int 134 | */ 135 | public function getVisibilityTimeout(): int 136 | { 137 | return $this->visibilityTimeout; 138 | } 139 | 140 | /** 141 | * Get the underlying Azure IQueue instance. 142 | * 143 | * @return IQueue 144 | */ 145 | public function getAzure(): IQueue 146 | { 147 | return $this->azure; 148 | } 149 | 150 | /** 151 | * Get the approximate size of the queue. 152 | * 153 | * @param string $queue 154 | * @return int 155 | */ 156 | public function size($queue = null): int 157 | { 158 | $queue = $this->getQueue($queue); 159 | 160 | $metaData = $this->azure->getQueueMetadata($queue); 161 | 162 | return $metaData->getApproximateMessageCount(); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /tests/AzureQueueTest.php: -------------------------------------------------------------------------------- 1 | azure = Mockery::mock(IQueue::class); 26 | $this->queue = new AzureQueue($this->azure, 'myqueue', 5); 27 | $this->queue->setContainer($this->app); 28 | $this->queue->setConnectionName("myconnection"); 29 | } 30 | 31 | protected function setListMessagesReturnExpectation(ExpectationInterface $mock, int $count = 1): ExpectationInterface 32 | { 33 | return $mock->andReturn(new ListMessagesResult($count)); 34 | } 35 | 36 | #[Test] 37 | public function it_can_push_message_to_queue() 38 | { 39 | $this->azure->shouldReceive('createMessage')->once()->withArgs(function ($queue, $payload) { 40 | $payload = json_decode($payload, true); 41 | return $queue == "myqueue" && $payload['displayName'] == 'foojob' && $payload['job'] == 'foojob' && $payload['data'] == 'bardata'; 42 | }); 43 | $this->queue->push('foojob', 'bardata'); 44 | } 45 | 46 | #[Test] 47 | public function it_can_pop_message_from_queue() 48 | { 49 | $this->setListMessagesReturnExpectation($this->azure->shouldReceive('listMessages')->once()); 50 | 51 | $message = $this->queue->pop('myqueue'); 52 | $this->assertInstanceOf(AzureJob::class, $message); 53 | } 54 | 55 | #[Test] 56 | public function it_can_pop_message_from_queue_using_default() 57 | { 58 | $this->setListMessagesReturnExpectation($this->azure->shouldReceive('listMessages')->once()); 59 | 60 | $message = $this->queue->pop(); 61 | $this->assertInstanceOf(AzureJob::class, $message); 62 | $this->assertEquals('myqueue', $message->getQueue()); 63 | } 64 | 65 | #[Test] 66 | public function it_returns_null_if_no_messages_to_pop() 67 | { 68 | $this->setListMessagesReturnExpectation($this->azure->shouldReceive('listMessages')->once(), 0); 69 | 70 | $message = $this->queue->pop('myqueue'); 71 | $this->assertNull($message); 72 | } 73 | 74 | #[Test] 75 | public function it_passes_visibility_timeout_set_in_config() 76 | { 77 | $mockClient = $this->azure->shouldReceive('listMessages')->once()->withArgs(function ($queue, 78 | ListMessagesOptions $options) { 79 | return $queue == 'myqueue' && $options->getVisibilityTimeoutInSeconds() == 5; 80 | }); 81 | $this->setListMessagesReturnExpectation($mockClient); 82 | 83 | $this->queue->pop('myqueue'); 84 | } 85 | 86 | #[Test] 87 | public function it_only_fetches_first_message() 88 | { 89 | $mockClient = $this->azure->shouldReceive('listMessages')->once()->withArgs(function ($queue, 90 | ListMessagesOptions $options) { 91 | return $queue == 'myqueue' && $options->getNumberOfMessages() == 1; 92 | }); 93 | $this->setListMessagesReturnExpectation($mockClient); 94 | $this->queue->pop('myqueue'); 95 | } 96 | 97 | #[Test] 98 | public function it_can_get_visibility_timeout() 99 | { 100 | $this->assertEquals(5, $this->queue->getVisibilityTimeout()); 101 | } 102 | 103 | #[Test] 104 | public function it_can_queue_a_job_for_later() 105 | { 106 | $this->azure->shouldReceive('createMessage')->once()->withArgs(function ($queue, 107 | $payload, 108 | CreateMessageOptions $options) { 109 | $payload = json_decode($payload, true); 110 | return $queue == "myqueue" && $payload['displayName'] == 'foojob' && $payload['job'] == 'foojob' && $payload['data'] == 'bardata' && $options->getVisibilityTimeoutInSeconds() == 10; 111 | }); 112 | 113 | $this->queue->later(10, 'foojob', 'bardata', 'myqueue'); 114 | } 115 | 116 | #[Test] 117 | public function it_can_get_queue_size() 118 | { 119 | $this->azure->shouldReceive('getQueueMetadata')->with('myqueue')->andReturn(new GetQueueMetadataResult(5, [])); 120 | 121 | $this->assertEquals(5, $this->queue->size('myqueue')); 122 | } 123 | 124 | #[Test] 125 | public function it_can_get_azure_instance() 126 | { 127 | $this->assertInstanceOf(IQueue::class, $this->queue->getAzure()); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | azure-queue-laravel 3 | ============= 4 | 5 | [![Github Actions](https://github.com/squigg/azure-queue-laravel/actions/workflows/workflow.yaml/badge.svg?branch=master)](https://github.com/squigg/azure-queue-laravel/actions/workflows/workflow.yaml) 6 | [![Coverage Status](https://coveralls.io/repos/github/squigg/azure-queue-laravel/badge.svg?branch=master)](https://coveralls.io/github/squigg/azure-queue-laravel?branch=master) 7 | 8 | [![Latest Stable Version](https://poser.pugx.org/squigg/azure-queue-laravel/v/stable.png)](https://packagist.org/packages/squigg/azure-queue-laravel) 9 | [![Total Downloads](https://poser.pugx.org/squigg/azure-queue-laravel/downloads.png)](https://packagist.org/packages/squigg/azure-queue-laravel) 10 | 11 | PHP Laravel Queue Driver package to support Microsoft Azure Storage Queues 12 | 13 | ## Prerequisites 14 | - Laravel 5.2 - 8.x (not tested on previous versions) 15 | - PHP 5.6+ for Laravel 5.2+ 16 | - PHP 7+ for Laravel 5.5+ 17 | - PHP 7.1+ for Laravel 5.6+ 18 | - PHP 7.2+ for Laravel 6+ 19 | - PHP 7.3+ for Laravel 8+ 20 | - PHP 8.0+ for Laravel 9+ 21 | - PHP 8.1+ for Laravel 10+ 22 | - PHP 8.1+ for Laravel 11+ 23 | - PHP 8.2+ for Laravel 12+ 24 | - Microsoft Azure Storage Account and Storage Account Key 25 | - Queue container created through Azure Portal or via 26 | [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/storage/queue?view=azure-cli-latest#az-storage-queue-create) 27 | or [PowerShell](https://docs.microsoft.com/en-us/azure/storage/queues/storage-powershell-how-to-use-queues#create-a-queue) 28 | 29 | ## Installation 30 | 31 | ### Install using composer 32 | You can find this library on [Packagist](https://packagist.org/packages/squigg/azure-queue-laravel). 33 | 34 | Require this package in your `composer.json`. The version numbers will follow Laravel. 35 | 36 | #### Laravel 12.x 37 | "squigg/azure-queue-laravel": "^12.0" 38 | composer require squigg/azure-queue-laravel:^12.0 39 | #### Laravel 11.x 40 | "squigg/azure-queue-laravel": "^11.0" 41 | composer require squigg/azure-queue-laravel:^11.0 42 | #### Laravel 10.x 43 | "squigg/azure-queue-laravel": "^10.0" 44 | composer require squigg/azure-queue-laravel:^10.0 45 | #### Laravel 9.x 46 | "squigg/azure-queue-laravel": "^9.0" 47 | composer require squigg/azure-queue-laravel:^9.0 48 | #### Laravel 8.x 49 | "squigg/azure-queue-laravel": "^8.0" 50 | composer require squigg/azure-queue-laravel:^8.0 51 | #### Laravel 7.x 52 | "squigg/azure-queue-laravel": "^7.0" 53 | composer require squigg/azure-queue-laravel:^7.0 54 | #### Laravel 6.x 55 | "squigg/azure-queue-laravel": "^6.0" 56 | composer require squigg/azure-queue-laravel:^6.0 57 | #### Laravel 5.8.x 58 | "squigg/azure-queue-laravel": "5.8.*" 59 | composer require squigg/azure-queue-laravel:5.8.* 60 | #### Laravel 5.7.x 61 | "squigg/azure-queue-laravel": "5.7.*" 62 | composer require squigg/azure-queue-laravel:5.7.* 63 | #### Laravel 5.6.x 64 | "squigg/azure-queue-laravel": "5.6.*" 65 | composer require squigg/azure-queue-laravel:5.6.* 66 | #### Laravel 5.5.x 67 | "squigg/azure-queue-laravel": "5.5.*" 68 | composer require squigg/azure-queue-laravel:5.5.* 69 | #### Laravel 5.4.x 70 | "squigg/azure-queue-laravel": "5.4.*" 71 | composer require squigg/azure-queue-laravel:5.4.* 72 | #### Laravel 5.3.x 73 | "squigg/azure-queue-laravel": "5.3.*" 74 | composer require squigg/azure-queue-laravel:5.3.* 75 | #### Laravel 5.2.x 76 | "squigg/azure-queue-laravel": "5.2.*" 77 | composer require squigg/azure-queue-laravel:5.2.* 78 | 79 | ##### For versions 5.3 and older only 80 | Add the following pear repository in your `composer.json` file required for the Microsoft Azure SDK 81 | (v5.4+ uses the `microsoft/azure-storage` package instead, and v5.6+ uses `microsoft/azure-storage-queue`): 82 | 83 | "repositories": [ 84 | { 85 | "type": "pear", 86 | "url": "http://pear.php.net" 87 | } 88 | ], 89 | 90 | Update Composer dependencies 91 | 92 | ```sh 93 | composer update 94 | ``` 95 | 96 | ## Configuration 97 | #### Add Provider 98 | If you are not using Laravel auto package discovery, add the ServiceProvider to your `providers` array in `config/app.php`: 99 | 100 | 'Squigg\AzureQueueLaravel\AzureQueueServiceProvider', 101 | 102 | For Lumen (5.x) you will need to add the provider to `bootstrap/app.php`: 103 | 104 | $app->register(Squigg\AzureQueueLaravel\AzureQueueServiceProvider::class); 105 | 106 | #### Add Azure queue configuration 107 | Add the following to the `connections` array in `config/queue.php`, and 108 | fill out your own connection data from the Azure Management portal: 109 | 110 | 'azure' => [ 111 | 'driver' => 'azure', // Leave this as-is 112 | 'protocol' => 'https', // https or http 113 | 'accountname' => env('AZURE_QUEUE_STORAGE_NAME'), // Azure storage account name 114 | 'key' => env('AZURE_QUEUE_KEY'), // Access key for storage account 115 | 'queue' => env('AZURE_QUEUE_NAME'), // Queue container name 116 | 'timeout' => 60, // Seconds before a job is released back to the queue 117 | 'endpoint' => env('AZURE_QUEUE_ENDPOINTSUFFIX'), // Optional endpoint suffix if different from core.windows.net 118 | 'queue_endpoint'=> env('AZURE_QUEUE_ENDPOINT'), // Optional endpoint for custom addresses like http://localhost/my_storage_name 119 | ], 120 | 121 | Add environment variables into your `.env` file to set the above configuration parameters: 122 | 123 | AZURE_QUEUE_STORAGE_NAME=xxx 124 | AZURE_QUEUE_KEY=xxx 125 | AZURE_QUEUE_NAME=xxx 126 | AZURE_QUEUE_ENDPOINTSUFFIX=xxx 127 | AZURE_QUEUE_ENDPOINT=xxx 128 | 129 | #### Set the default Laravel queue 130 | Update the default queue used by Laravel by setting the `QUEUE_CONNECTION` value in your `.env` file to `azure`. 131 | 132 | QUEUE_CONNECTION=azure 133 | 134 | This setting is `QUEUE_DRIVER` in older versions of Laravel. 135 | 136 | ## Usage 137 | Use the normal Laravel Queue functionality as per the [documentation](http://laravel.com/docs/queues). 138 | 139 | Remember to update the default queue by setting the `QUEUE_DRIVER` value in your `.env` file to `azure`. 140 | 141 | ## Changelog 142 | 143 | 2025-07-25 - V11.0 - Support for Laravel 12.x 144 | 145 | 2024-03-30 - V11.0 - Support for Laravel 11.x 146 | 147 | 2023-03-17 - V10.0 - Support for Laravel 10.x 148 | 149 | 2022-03-17 - V9.0 - Support for Laravel 9.x 150 | 151 | 2021-10-16 - V8.1 - Support for PHP 8 152 | 153 | 2020-09-19 - V8.0 - Support for Laravel 8.x (composer dependency and test refactoring only) 154 | 155 | 2020-06-04 - V7.0 - Support for Laravel 7.x (composer dependency and test refactoring only) 156 | 157 | 2020-06-04 - V6.0 - Support for Laravel 6.x (composer dependency changes only) 158 | 159 | 2019-07-13 - V5.8 - Support for Laravel 5.8 (composer dependency and test changes only) 160 | 161 | 2019-07-13 - V5.7.1 - Fix invalid signature on call to base Laravel Queue method 162 | 163 | 2018-09-04 - V5.7 - Support for Laravel 5.7 (composer dependency changes only) 164 | 165 | 2018-02-07 - V5.6 - Switch to GA version of Microsoft Azure Storage PHP API. Support Laravel 5.6 (composer.json changes 166 | only). Update dev dependencies to latest versions. 167 | 168 | 2017-09-11 - V5.5 - Support Laravel 5.5 and PHP7+ only. Update Azure Storage API to 0.18 169 | 170 | 2017-09-11 - V5.4 - Update Azure Storage API to 0.15 (no breaking changes) 171 | 172 | ## License 173 | Released under the MIT License. Based on [Alex Bouma's Laravel 4 package](https://github.com/stayallive/laravel-azure-blob-queue), updated for Laravel 5. 174 | --------------------------------------------------------------------------------