Skip to content

Commit a45cb20

Browse files
authored
Merge branch 'cakephp:master' into issue/64
2 parents 12376b1 + fb2bd80 commit a45cb20

36 files changed

+1796
-31
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242
}
4343
},
4444
"suggest": {
45-
"cakephp/bake": "Required if you want to generate jobs."
45+
"cakephp/bake": "Required if you want to generate jobs.",
46+
"cakephp/migrations": "Needed for running the migrations necessary for using Failed Jobs."
4647
},
4748
"scripts": {
4849
"check": [
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
use Migrations\AbstractMigration;
5+
6+
class CreateFailedJobs extends AbstractMigration
7+
{
8+
/**
9+
* Change Method.
10+
*
11+
* More information on this method is available here:
12+
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
13+
* @return void
14+
*/
15+
public function change()
16+
{
17+
$table = $this->table('queue_failed_jobs');
18+
$table->addColumn('class', 'string', [
19+
'length' => 255,
20+
'null' => false,
21+
'default' => null,
22+
])
23+
->addColumn('method', 'string', [
24+
'length' => 255,
25+
'null' => false,
26+
'default' => null,
27+
])
28+
->addColumn('data', 'text', [
29+
'null' => false,
30+
'default' => null,
31+
])
32+
->addColumn('config', 'string', [
33+
'length' => 255,
34+
'null' => false,
35+
'default' => null,
36+
])
37+
->addColumn('priority', 'string', [
38+
'length' => 255,
39+
'null' => true,
40+
'default' => null,
41+
])
42+
->addColumn('queue', 'string', [
43+
'length' => 255,
44+
'null' => false,
45+
'default' => null,
46+
])
47+
->addColumn('exception', 'text', [
48+
'null' => true,
49+
'default' => null,
50+
])
51+
->addColumn('created', 'datetime', [
52+
'default' => null,
53+
'limit' => null,
54+
'null' => true,
55+
])
56+
->create();
57+
}
58+
}

docs/en/index.rst

Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,11 @@ The following configuration should be present in the config array of your **conf
4141
'Queue' => [
4242
'default' => [
4343
// A DSN for your configured backend. default: null
44-
'url' => 'redis:',
44+
// Can contain protocol/port/username/password or be null if the backend defaults to localhost
45+
'url' => 'redis://myusername:[email protected]:1000',
4546

4647
// The queue that will be used for sending messages. default: default
47-
// This can be overriden when queuing or processing messages
48+
// This can be overridden when queuing or processing messages
4849
'queue' => 'default',
4950

5051
// The name of a configured logger, default: null
@@ -55,20 +56,51 @@ The following configuration should be present in the config array of your **conf
5556

5657
// The amount of time in milliseconds to sleep if no jobs are currently available. default: 10000
5758
'receiveTimeout' => 10000,
59+
60+
// Whether to store failed jobs in the queue_failed_jobs table. default: false
61+
'storeFailedJobs' => true,
62+
63+
// (optional) The cache configuration for storing unique job ids. `duration`
64+
// should be greater than the maximum length of time any job can be expected
65+
// to remain on the queue. Otherwise, duplicate jobs may be
66+
// possible. Defaults to +24 hours. Note that `File` engine is only suitable
67+
// for local development.
68+
// See https://book.cakephp.org/4/en/core-libraries/caching.html#configuring-cache-engines.
69+
'uniqueCache' => [
70+
'engine' => 'File',
71+
],
5872
]
5973
],
6074
// ...
6175

6276
The ``Queue`` config key can contain one or more queue configurations. Each of
6377
these is used for interacting with a different queuing backend.
6478

79+
If ``storeFailedJobs`` is set to ``true``, make sure to run the plugin migrations to create the ``queue_failed_jobs`` table.
80+
81+
Install the migrations plugin:
82+
83+
.. code-block:: bash
84+
85+
composer require cakephp/migrations:"^3.1"
86+
87+
Run the migrations:
88+
89+
.. code-block:: bash
90+
91+
bin/cake migrations migrate --plugin Cake/Queue
92+
93+
6594
Usage
6695
=====
6796

6897
Defining Jobs
6998
-------------
7099

71-
Create a Job class::
100+
Workloads are defined as 'jobs'. Job classes can recieve dependencies from your
101+
application's dependency injection container in their constructor just like
102+
Controllers or Commands. Jobs are responsible for processing queue messages.
103+
A simple job that logs received messages would look like::
72104

73105
<?php
74106
// src/Job/ExampleJob.php
@@ -92,6 +124,13 @@ Create a Job class::
92124
*/
93125
public static $maxAttempts = 3;
94126

127+
/**
128+
* Whether there should be only one instance of a job on the queue at a time. (optional property)
129+
*
130+
* @var bool
131+
*/
132+
public static $shouldBeUnique = false;
133+
95134
public function execute(Message $message): ?string
96135
{
97136
$id = $message->getArgument('id');
@@ -125,13 +164,19 @@ The job **may** also return a null value, which is interpreted as
125164
``Processor::ACK``. Failure to respond with a valid type will result in an
126165
interpreted message failure and requeue of the message.
127166

128-
Properties:
167+
Job Properties:
129168

130169
- ``maxAttempts``: The maximum number of times the job may be requeued as a result
131170
of an exception or by explicitly returning ``Processor::REQUEUE``. If
132171
provided, this value will override the value provided in the worker command
133172
line option ``--max-attempts``. If a value is not provided by the job or by
134173
the command line option, the job may be requeued an infinite number of times.
174+
- ``shouldBeUnique``: If ``true``, only one instance of the job, identified by
175+
it's class, method, and data, will be allowed to be present on the queue at a
176+
time. Subsequent pushes will be silently dropped. This is useful for
177+
idempotent operations where consecutive job executions have no benefit. For
178+
example, refreshing calculated data. If ``true``, the ``uniqueCache``
179+
configuration must be set.
135180

136181
Queueing
137182
--------
@@ -266,6 +311,62 @@ This shell can take a few different options:
266311
- Max Runtime
267312
- Runtime: Time since the worker started, the worker will finish when Runtime is over Max Runtime value
268313

314+
Failed Jobs
315+
===========
316+
317+
By default, jobs that throw an exception are requeued indefinitely. However, if
318+
``maxAttempts`` is configured on the job class or via a command line argument, a
319+
job will be considered failed if a ``Processor::REQUEUE`` response is received
320+
after processing (typically due to an exception being thrown) and there are no
321+
remaining attempts. The job will then be rejected and added to the
322+
``queue_failed_jobs`` table and can be requeued manually.
323+
324+
Your chosen transport may offer a dead-letter queue feature. While Failed Jobs
325+
has a similar purpose, it specifically captures jobs that return a
326+
``Processor::REQUEUE`` response and does not handle other failure cases. It is
327+
agnostic of transport and only supports database persistence.
328+
329+
The following options passed when originally queueing the job will be preserved:
330+
``config``, ``queue``, and ``priority``.
331+
332+
Requeue Failed Jobs
333+
-------------------
334+
335+
Push jobs back onto the queue and remove them from the ``queue_failed_jobs``
336+
table. If a job fails to requeue it is not guaranteed that the job was not run.
337+
338+
.. code-block:: bash
339+
340+
bin/cake queue requeue
341+
342+
Optional filters:
343+
344+
- ``--id``: Requeue job by the ID of the ``FailedJob``
345+
- ``--class``: Requeue jobs by the job class
346+
- ``--queue``: Requeue jobs by the queue the job was received on
347+
- ``--config``: Requeue jobs by the config used to queue the job
348+
349+
If no filters are provided then all failed jobs will be requeued.
350+
351+
Purge Failed Jobs
352+
------------------
353+
354+
Delete jobs from the ``queue_failed_jobs`` table.
355+
356+
.. code-block:: bash
357+
358+
bin/cake queue purge_failed
359+
360+
Optional filters:
361+
362+
- ``--id``: Purge job by the ID of the ``FailedJob``
363+
- ``--class``: Purge jobs by the job class
364+
- ``--queue``: Purge jobs by the queue the job was received on
365+
- ``--config``: Purge jobs by the config used to queue the job
366+
367+
If no filters are provided then all failed jobs will be purged.
368+
369+
269370
Worker Events
270371
=============
271372

phpunit.xml.dist

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,11 @@
1515
<directory>tests/TestCase</directory>
1616
</testsuite>
1717
</testsuites>
18+
<listeners>
19+
<listener class="Cake\TestSuite\Fixture\FixtureInjector">
20+
<arguments>
21+
<object class="Cake\TestSuite\Fixture\FixtureManager"/>
22+
</arguments>
23+
</listener>
24+
</listeners>
1825
</phpunit>

src/Command/JobCommand.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
namespace Cake\Queue\Command;
1818

1919
use Bake\Command\SimpleBakeCommand;
20+
use Cake\Console\Arguments;
2021
use Cake\Console\ConsoleOptionParser;
2122

2223
class JobCommand extends SimpleBakeCommand
@@ -47,6 +48,20 @@ public function template(): string
4748
return 'Cake/Queue.job';
4849
}
4950

51+
/**
52+
* @inheritDoc
53+
*/
54+
public function templateData(Arguments $arguments): array
55+
{
56+
$parentData = parent::templateData($arguments);
57+
58+
$data = [
59+
'isUnique' => $arguments->getOption('unique'),
60+
];
61+
62+
return array_merge($parentData, $data);
63+
}
64+
5065
/**
5166
* Gets the option parser instance and configures it.
5267
*
@@ -61,6 +76,11 @@ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionPar
6176
->setDescription('Bake a queue job class.')
6277
->addArgument('name', [
6378
'help' => 'The name of the queue job class to create.',
79+
])
80+
->addOption('unique', [
81+
'help' => 'Whether there should be only one instance of a job on the queue at a time.',
82+
'boolean' => true,
83+
'default' => false,
6484
]);
6585
}
6686
}

0 commit comments

Comments
 (0)