Skip to content

Commit 69d339c

Browse files
authored
Merge pull request #7 from TimoKoerber/feature/6-support-queue-name
Queue for the dispatched jobs can be changed
2 parents c1948dc + 5e8e83c commit 69d339c

File tree

5 files changed

+109
-10
lines changed

5 files changed

+109
-10
lines changed

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ php artisan operations:make <operation_name> // create operation file
4949
php artisan operations:process // process operation files
5050
php artisan operations:process --sync // force syncronously execution
5151
php artisan operations:process --async // force asyncronously execution
52+
php artisan operations:process --queue=<name> // force queue, that the job will be dispatched to
5253
php artisan operations:process --test // dont flag operations as processed
5354
php artisan operations:process <operation_name> // re-run one specific operation
5455
```
@@ -130,6 +131,11 @@ return new class extends OneTimeOperation
130131
* Determine if the operation is being processed asyncronously.
131132
*/
132133
protected bool $async = true;
134+
135+
/**
136+
* The queue that the job will be dispatched to.
137+
*/
138+
protected string $queue = 'default';
133139

134140
/**
135141
* Process the operation.
@@ -155,10 +161,13 @@ public function process(): void
155161
```
156162

157163
By default, the operation is being processed ***asyncronously*** (based on your configuration) by dispatching the job `OneTimeOperationProcessJob`.
164+
By default, the operation is being dispatched to the `default` queue of your project. Change the `$queue` as you wish.
158165

159166
You can also execute the code syncronously by setting the `$async` flag to `false`.
160167
_(this is only recommended for small operations, since the processing of these operations should be part of the deployment process)_
161168

169+
**Hint:** If you use syncronous processing, the `$queue` attribute will be ignored (duh!).
170+
162171
### Processing the operations
163172

164173
![One-Time Operations for Laravel - Processing the operations](https://user-images.githubusercontent.com/65356688/224434129-43082402-6077-4043-8e97-c44786e60a59.png)
@@ -192,6 +201,14 @@ php artisan operations:process --sync // force dispatchSync()
192201
**Hint!** If `operation:process` is part of your deployment process, it is **not recommended** to process the operations syncronously,
193202
since an error in your operation could make your whole deployment fail.
194203

204+
### Force different queue for all operations
205+
206+
You can provide the `--queue` option in the artisan call. The given queue will be used for all operations, ignoring the `$queue` attribute in the class.
207+
208+
```shell
209+
php artisan operations:process --queue=redis // force redis queue
210+
```
211+
195212
### Re-run an operation
196213

197214
![One-Time Operations for Laravel - Re-run an operation manually](https://user-images.githubusercontent.com/65356688/224440344-3d095730-12c3-4a2c-b4c3-42a8b6d60767.png)

src/Commands/OneTimeOperationsProcessCommand.php

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,24 @@ class OneTimeOperationsProcessCommand extends OneTimeOperationsCommand
1313
{name? : Name of specific operation}
1414
{--test : Process operation without tagging it as processed, so you can call it again}
1515
{--async : Ignore setting in operation and process all operations asynchronously}
16-
{--sync : Ignore setting in operation and process all operations synchronously}';
16+
{--sync : Ignore setting in operation and process all operations synchronously}
17+
{--queue= : Set the queue, that all jobs will be dispatched to}';
1718

1819
protected $description = 'Process all unprocessed one-time operations';
1920

2021
protected bool $forceAsync = false;
2122

2223
protected bool $forceSync = false;
2324

25+
protected ?string $queue = null;
26+
2427
public function handle(): int
2528
{
2629
$this->displayTestmodeWarning();
2730

2831
$this->forceAsync = (bool) $this->option('async');
2932
$this->forceSync = (bool) $this->option('sync');
33+
$this->queue = $this->option('queue');
3034

3135
if ($this->forceAsync && $this->forceSync) {
3236
$this->components->error('Abort! Process either with --sync or --async.');
@@ -63,7 +67,7 @@ protected function proccessSingleOperation(string $providedOperationName): int
6367
protected function processOperationFile(OneTimeOperationFile $operationFile): int
6468
{
6569
$this->components->task($operationFile->getOperationName(), function () use ($operationFile) {
66-
$this->processOperation($operationFile);
70+
$this->dispatchOperationJob($operationFile);
6771
$this->storeOperation($operationFile);
6872
});
6973

@@ -86,7 +90,7 @@ protected function processOperationModel(Operation $operationModel): int
8690
$this->components->task($operationModel->name, function () use ($operationModel) {
8791
$operationFile = OneTimeOperationManager::getOperationFileByModel($operationModel);
8892

89-
$this->processOperation($operationFile);
93+
$this->dispatchOperationJob($operationFile);
9094
$this->storeOperation($operationFile);
9195
});
9296

@@ -110,7 +114,7 @@ protected function processNextOperations(): int
110114

111115
foreach ($unprocessedOperationFiles as $operationFile) {
112116
$this->components->task($operationFile->getOperationName(), function () use ($operationFile) {
113-
$this->processOperation($operationFile);
117+
$this->dispatchOperationJob($operationFile);
114118
$this->storeOperation($operationFile);
115119
});
116120
}
@@ -130,13 +134,15 @@ protected function storeOperation(OneTimeOperationFile $operationFile): void
130134
Operation::storeOperation($operationFile->getOperationName(), $this->isAsyncMode($operationFile));
131135
}
132136

133-
protected function processOperation(OneTimeOperationFile $operationFile)
137+
protected function dispatchOperationJob(OneTimeOperationFile $operationFile)
134138
{
135139
if ($this->isAsyncMode($operationFile)) {
136-
OneTimeOperationProcessJob::dispatch($operationFile->getOperationName());
137-
} else {
138-
OneTimeOperationProcessJob::dispatchSync($operationFile->getOperationName());
140+
OneTimeOperationProcessJob::dispatch($operationFile->getOperationName())->onQueue($this->getQueue($operationFile));
141+
142+
return;
139143
}
144+
145+
OneTimeOperationProcessJob::dispatchSync($operationFile->getOperationName());
140146
}
141147

142148
protected function testModeEnabled(): bool
@@ -163,4 +169,13 @@ protected function isAsyncMode(OneTimeOperationFile $operationFile): bool
163169

164170
return $operationFile->getClassObject()->isAsync();
165171
}
172+
173+
protected function getQueue(OneTimeOperationFile $operationFile): ?string
174+
{
175+
if ($this->queue) {
176+
return $this->queue;
177+
}
178+
179+
return $operationFile->getClassObject()->getQueue() ?: null;
180+
}
166181
}

src/OneTimeOperation.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ abstract class OneTimeOperation
99
*/
1010
protected bool $async = true;
1111

12+
/**
13+
* The queue that the job will be dispatched to.
14+
*/
15+
protected string $queue = 'default';
16+
1217
/**
1318
* Process the operation.
1419
*/
@@ -18,4 +23,9 @@ public function isAsync(): bool
1823
{
1924
return $this->async;
2025
}
26+
27+
public function getQueue(): string
28+
{
29+
return $this->queue;
30+
}
2131
}

stubs/one-time-operation.stub

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ return new class extends OneTimeOperation
99
*/
1010
protected bool $async = true;
1111

12+
/**
13+
* The queue that the job will be dispatched to.
14+
*/
15+
protected string $queue = 'default';
16+
1217
/**
1318
* Process the operation.
1419
*/

tests/Feature/OneTimeOperationCommandTest.php

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ public function test_sync_processing_with_file_attribute()
137137

138138
// Job was executed synchronously
139139
Queue::assertPushed(OneTimeOperationProcessJob::class, function (OneTimeOperationProcessJob $job) {
140-
return $job->operationName === '2015_10_21_072800_foo_bar_operation' && $job->connection === 'sync'; // sync
140+
return $job->operationName === '2015_10_21_072800_foo_bar_operation'
141+
&& $job->connection === 'sync' // sync
142+
&& $job->queue === null; // no queue
141143
});
142144

143145
$operation = Operation::first();
@@ -151,12 +153,62 @@ public function test_sync_processing_with_file_attribute()
151153

152154
// Job was executed asynchronously
153155
Queue::assertPushed(OneTimeOperationProcessJob::class, function (OneTimeOperationProcessJob $job) {
154-
return $job->operationName === '2015_10_21_072800_foo_bar_operation' && $job->connection === null; // async
156+
return $job->operationName === '2015_10_21_072800_foo_bar_operation'
157+
&& $job->connection === null // async
158+
&& $job->queue === 'default'; // default queue
155159
});
156160

157161
$operation = Operation::all()->last();
158162
$this->assertEquals('2015_10_21_072800_foo_bar_operation', $operation->name);
159163
$this->assertEquals('async', $operation->dispatched);
164+
165+
// process again - now on queue "foobar"
166+
$this->artisan('operations:process 2015_10_21_072800_foo_bar_operation --async --queue=foobar')
167+
->expectsConfirmation('Operation was processed before. Process it again?', 'yes')
168+
->assertSuccessful();
169+
170+
// Job was executed asynchronously on queue "foobar"
171+
Queue::assertPushed(OneTimeOperationProcessJob::class, function (OneTimeOperationProcessJob $job) {
172+
return $job->operationName === '2015_10_21_072800_foo_bar_operation'
173+
&& $job->connection === null // async
174+
&& $job->queue === 'foobar'; // default queue
175+
});
176+
}
177+
178+
public function test_processing_with_queue()
179+
{
180+
$filepath = $this->filepath('2015_10_21_072800_foo_bar_operation.php');
181+
Queue::assertNothingPushed();
182+
183+
// create file
184+
$this->artisan('operations:make FooBarOperation')->assertSuccessful();
185+
186+
// edit file so it will use different queue
187+
$fileContent = File::get($filepath);
188+
$newContent = Str::replaceFirst('$queue = \'default\';', '$queue = \'narfpuit\';', $fileContent);
189+
File::put($filepath, $newContent);
190+
191+
// process
192+
$this->artisan('operations:process')->assertSuccessful();
193+
194+
// Job was executed synchronously
195+
Queue::assertPushed(OneTimeOperationProcessJob::class, function (OneTimeOperationProcessJob $job) {
196+
return $job->operationName === '2015_10_21_072800_foo_bar_operation'
197+
&& $job->connection === null // async
198+
&& $job->queue === 'narfpuit'; // queue narfpuit
199+
});
200+
201+
// process again - overwrite queue with "foobar"
202+
$this->artisan('operations:process 2015_10_21_072800_foo_bar_operation --queue=foobar')
203+
->expectsConfirmation('Operation was processed before. Process it again?', 'yes')
204+
->assertSuccessful();
205+
206+
// Job was executed asynchronously on queue "foobar"
207+
Queue::assertPushed(OneTimeOperationProcessJob::class, function (OneTimeOperationProcessJob $job) {
208+
return $job->operationName === '2015_10_21_072800_foo_bar_operation'
209+
&& $job->connection === null // async
210+
&& $job->queue === 'foobar'; // queue foobar
211+
});
160212
}
161213

162214
public function test_processing_with_test_flag()

0 commit comments

Comments
 (0)