Skip to content

Commit 0f05e07

Browse files
committed
Merge two different failure handling guides
1 parent c598caf commit 0f05e07

4 files changed

Lines changed: 124 additions & 146 deletions

File tree

docs/guide/en/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ An extension for running tasks asynchronously via queues.
3232
## Reliability and visibility
3333

3434
- [Errors and retryable jobs](error-handling.md)
35-
- [Failure handling pipeline](failure-handling-pipeline.md)
3635
- [Job status](job-status.md)
3736
- [Yii Debug integration](debug-integration.md)
3837

docs/guide/en/error-handling.md

Lines changed: 123 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,68 @@
11
# Error handling on message processing
22

3-
Often when some message handling is failing, we want to retry its execution a couple more times or redirect it to another queue channel. This can be done in [yiisoft/queue](https://github.com/yiisoft/queue) with _Failure Handling Middleware Pipeline_. It is triggered each time message processing via Consume Middleware Pipeline is interrupted with any `Throwable`.
3+
Often when some message handling is failing, we want to retry its execution a couple more times or redirect it to another queue channel. In `yiisoft/queue` this is handled by the failure handling middleware pipeline.
4+
5+
## When failure handling is triggered
6+
7+
Failure handling is triggered only when message processing throws a `Throwable`.
8+
9+
In practice it means:
10+
11+
- The worker runs message processing in `Yiisoft\Queue\Worker\Worker::process()`.
12+
- Your message handler is executed through the [consume middleware pipeline](middleware-pipelines.md#consume-pipeline).
13+
- If any `Throwable` escapes that pipeline, the worker switches to the failure handling pipeline.
14+
15+
## Failure handling pipeline overview (step-by-step)
16+
17+
1. A message is processed via the consume pipeline
18+
19+
The worker builds a `Yiisoft\Queue\Middleware\Consume\ConsumeRequest` and dispatches it through `ConsumeMiddlewareDispatcher`. The final consume handler invokes the resolved message handler.
20+
21+
2. A `Throwable` is caught by the worker
22+
23+
If any middleware or the message handler throws, `Worker::process()` catches it.
24+
25+
3. Failure context is wrapped into a request object
26+
27+
The worker creates a `Yiisoft\Queue\Middleware\FailureHandling\FailureHandlingRequest` ([source](../../../src/Middleware/FailureHandling/FailureHandlingRequest.php)) containing:
28+
29+
- the message
30+
- the caught exception
31+
- the queue instance (including its channel)
32+
33+
4. A failure pipeline is selected by queue channel
34+
35+
`FailureMiddlewareDispatcher::dispatch()` selects which pipeline to run:
36+
37+
- It tries to use the pipeline configured for the current queue channel.
38+
- If there is no pipeline for that channel (or it is empty), it falls back to `FailureMiddlewareDispatcher::DEFAULT_PIPELINE`.
39+
40+
5. Failure middlewares are executed
41+
42+
The dispatcher builds a lazy middleware stack (`MiddlewareFailureStack`) and invokes it.
43+
44+
Each failure middleware implements `MiddlewareFailureInterface`:
45+
46+
- It receives the `FailureHandlingRequest` and a continuation handler.
47+
- It may handle the failure by re-queueing the message (same or different queue/channel), optionally with a delay.
48+
- If it decides not to handle the failure, it calls `$handler->handleFailure($request)` to continue the pipeline.
49+
50+
6. If nothing handles the failure, the exception is rethrown
51+
52+
The failure pipeline ends with `FailureFinalHandler`, which throws `$request->getException()`.
53+
54+
7. The worker wraps and rethrows
55+
56+
If the failure pipeline itself ends with an exception, `Worker::process()` wraps it into `Yiisoft\Queue\Exception\JobFailureException` (including message id from `IdEnvelope` metadata when available) and throws it.
57+
58+
## What “handled failure” means
59+
60+
A failure is considered handled if the failure pipeline returns a `FailureHandlingRequest` without throwing.
61+
In practice, built-in middlewares handle failures by re-queueing the message (same or different queue/channel), optionally with a delay, and returning the updated request.
462

563
## Configuration
664

7-
Here below is configuration via [yiisoft/config](https://github.com/yiisoft/config). If you don't use it, you should add a middleware definition list (in the `middlewares-fail` key here) to the `FailureMiddlewareDispatcher` by your own. You can define different failure handling pipelines for each queue channel. The example below defines two different failure handling pipelines:
65+
Here below is configuration via [yiisoft/config](https://github.com/yiisoft/config) (see also [Configuration with yiisoft/config](configuration-with-config.md)). If you don't use it, you should add a middleware definition list (in the `middlewares-fail` key here) to the `FailureMiddlewareDispatcher` [by your own](configuration-manual.md). You can define different failure handling pipelines for each queue channel (see [Queue channels](channels.md)). The example below defines two different failure handling pipelines:
866

967
```php
1068
'yiisoft/queue' => [
@@ -57,29 +115,77 @@ In the example above failures will be handled this way (look the concrete middle
57115
Failures of messages, which are initially sent to the `failed-messages` channel, will only be handled by the 3rd and the 4th points of this list.
58116

59117
## Default failure handling strategies
118+
119+
Let's see the built-in defaults.
120+
121+
### [SendAgainMiddleware](../../../src/Middleware/FailureHandling/Implementation/SendAgainMiddleware.php)
122+
123+
This strategy simply resends the given message to a queue. Let's see the constructor parameters through which it's configured:
124+
125+
- `id` - A unique string. Allows to use this strategy more than once for the same message, just like in example above.
126+
- `maxAttempts` - Maximum attempts count for this strategy with the given $id before it will give up.
127+
- `queue` - The strategy will send the message to the given queue when it's not `null`. That means you can use this strategy to push a message not to the same queue channel it came from. When the `queue` parameter is set to `null`, a message will be sent to the same channel it came from.
128+
129+
State tracking:
130+
131+
- Uses `FailureEnvelope` metadata (`failure-meta`) to store the per-middleware attempt counter.
132+
- The counter key is `failure-strategy-resend-attempts-{id}`.
133+
134+
### [ExponentialDelayMiddleware](../../../src/Middleware/FailureHandling/Implementation/ExponentialDelayMiddleware.php)
135+
136+
This strategy does the same thing as the `SendAgainMiddleware` with a single difference: it resends a message with an exponentially increasing delay. The delay **must** be implemented by the used `AdapterInterface` implementation.
60137

61-
Let's see the built-in defaults.
138+
It's configured via constructor parameters, too. Here they are:
62139

63-
### [SendAgainMiddleware](../../../src/Middleware/FailureHandling/Implementation/SendAgainMiddleware.php)
140+
- `id` - A unique string allows to use this strategy more than once for the same message, just like in example above.
141+
- `maxAttempts` - Maximum attempts count for this strategy with the given $id before it will give up.
142+
- `delayInitial` - The initial delay that will be applied to a message for the first time. It must be a positive float.
143+
- `delayMaximum` - The maximum delay which can be applied to a single message. Must be above the `delayInitial`.
144+
- `exponent` - Message handling delay will be multiplied by exponent each time it fails.
145+
- `queue` - The strategy will send the message to the given queue when it's not `null`. That means you can use this strategy to push a message not to the same queue channel it came from. When the `queue` parameter is set to `null`, a message will be sent to the same channel it came from.
64146

65-
This strategy simply resends the given message to a queue. Let's see the constructor parameters through which it's configured:
147+
Requirements:
66148

67-
- `id` - A unique string. Allows to use this strategy more than once for the same message, just like in example above.
68-
- `maxAttempts` - Maximum attempts count for this strategy with the given $id before it will give up.
69-
- `queue` - The strategy will send the message to the given queue when it's not `null`. That means you can use this strategy to push a message not to the same queue channel it came from. When the `queue` parameter is set to `null`, a message will be sent to the same channel it came from.
149+
- Requires a `DelayMiddlewareInterface` implementation and an adapter that supports delayed delivery.
70150

71-
### [ExponentialDelayMiddleware](../../../src/Middleware/FailureHandling/Implementation/ExponentialDelayMiddleware.php)
151+
State tracking:
72152

73-
This strategy does the same thing as the `SendAgainMiddleware` with a single difference: it resends a message with an exponentially increasing delay. The delay **must** be implemented by the used `AdapterInterface` implementation.
153+
- Uses `FailureEnvelope` metadata (`failure-meta`) to store attempts and the previous delay.
154+
- The per-middleware keys are:
74155

75-
It's configured via constructor parameters, too. Here they are:
156+
- `failure-strategy-exponential-delay-attempts-{id}`
157+
- `failure-strategy-exponential-delay-delay-{id}`
76158

77-
- `id` - A unique string allows to use this strategy more than once for the same message, just like in example above.
78-
- `maxAttempts` - Maximum attempts count for this strategy with the given $id before it will give up.
79-
- `delayInitial` - The initial delay that will be applied to a message for the first time. It must be a positive float.
80-
- `delayMaximum` - The maximum delay which can be applied to a single message. Must be above the `delayInitial`.
81-
- `exponent` - Message handling delay will be multiplied by exponent each time it fails.
82-
- `queue` - The strategy will send the message to the given queue when it's not `null`. That means you can use this strategy to push a message not to the same queue channel it came from. When the `queue` parameter is set to `null`, a message will be sent to the same channel it came from.
159+
## Built-in failure handling components
160+
161+
This package ships the following built-in failure handling components.
162+
163+
### FailureEnvelope
164+
165+
Class: `Yiisoft\Queue\Middleware\FailureHandling\FailureEnvelope`
166+
167+
Behavior:
168+
169+
- An envelope that stores failure-related metadata under the `failure-meta` key.
170+
- Built-in failure middlewares use it to persist retry counters / delay parameters across retries.
171+
172+
### FailureFinalHandler
173+
174+
Class: `Yiisoft\Queue\Middleware\FailureHandling\FailureFinalHandler`
175+
176+
Behavior:
177+
178+
- Terminal failure handler.
179+
- Throws the exception from the request when the failure pipeline does not handle the failure.
180+
181+
### JobFailureException
182+
183+
Class: `Yiisoft\Queue\Exception\JobFailureException`
184+
185+
Behavior:
186+
187+
- Thrown by the worker when failure handling does not resolve the issue.
188+
- Wraps the original exception and includes the queue message id (if available) in the exception message.
83189

84190
## How to create a custom Failure Middleware?
85191

docs/guide/en/failure-handling-pipeline.md

Lines changed: 0 additions & 127 deletions
This file was deleted.

docs/guide/en/middleware-pipelines.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ The pipeline receives a `FailureHandlingRequest` that contains:
130130
The pipeline is selected by queue channel; if there is no channel-specific pipeline configured,
131131
`FailureMiddlewareDispatcher::DEFAULT_PIPELINE` is used.
132132

133-
See [Failure handling pipeline](failure-handling-pipeline.md) for the step-by-step flow and built-in middlewares.
133+
See [Error handling on message processing](error-handling.md) for the step-by-step flow and built-in middlewares.
134134

135135
## Configuration
136136

0 commit comments

Comments
 (0)