63 lines
4.9 KiB
HTML
63 lines
4.9 KiB
HTML
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:pls="http://www.w3.org/2005/01/pronunciation-lexicon" xmlns:ssml="http://www.w3.org/2001/10/synthesis" xmlns:svg="http://www.w3.org/2000/svg"><head><title>Typical Repeat-Retry Pattern</title><link rel="stylesheet" type="text/css" href="docbook-epub.css"/><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"/><link rel="prev" href="apcs02.xhtml" title="Simple Stateless Retry"/><link rel="next" href="apcs04.xhtml" title="Asynchronous Chunk Processing"/></head><body><header/><section class="section" title="Typical Repeat-Retry Pattern" epub:type="division" id="repeatRetry"><div class="titlepage"><div><div><h2 class="title" style="clear: both">Typical Repeat-Retry Pattern</h2></div></div></div><p>The most typical batch processing pattern is to add a retry to the
|
|
inner block of the chunk in the Simple Batching example.
|
|
Consider this:</p><pre class="programlisting">
|
|
1 | REPEAT(until=exhausted, exception=not critical) {
|
|
|
|
|
2 | TX {
|
|
3 | REPEAT(size=5) {
|
|
|
|
|
4 | RETRY(stateful, exception=deadlock loser) {
|
|
4.1 | input;
|
|
5 | } PROCESS {
|
|
5.1 | output;
|
|
6 | } SKIP and RECOVER {
|
|
| notify;
|
|
| }
|
|
|
|
|
| }
|
|
| }
|
|
|
|
|
| }
|
|
</pre><p>The inner RETRY(4) block is marked as "stateful" - see the
|
|
typical use case for a description of a stateful
|
|
retry. This means that if the the retry PROCESS(5) block fails, the
|
|
behaviour of the RETRY(4) is as follows.</p><div class="itemizedlist" epub:type="list"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem" epub:type="list-item"><p>Throw an exception, rolling back the transaction TX(2) at the
|
|
chunk level, and allowing the item to be re-presented to the input
|
|
queue.</p></li><li class="listitem" epub:type="list-item"><p>When the item re-appears, it might be retried depending on the
|
|
retry policy in place, executing PROCESS(5) again. The second and
|
|
subsequent attempts might fail again and rethrow the exception.</p></li><li class="listitem" epub:type="list-item"><p>Eventually the item re-appears for the final time: the retry
|
|
policy disallows another attempt, so PROCESS(5) is never
|
|
executed. In this case we follow a RECOVER(6) path, effectively
|
|
"skipping" the item that was received and is being processed.</p></li></ul></div><p>Notice that the notation used for the RETRY(4) in the plan above
|
|
shows explictly that the the input step (4.1) is part of the retry.
|
|
It also makes clear that there are two alternate paths for
|
|
processing: the normal case is denoted by PROCESS(5), and the
|
|
recovery path is a separate block, RECOVER(6). The two alternate
|
|
paths are completely distinct: only one is ever taken in normal
|
|
circumstances.</p><p>In special cases (e.g. a special <code class="classname">TranscationValidException</code>
|
|
type), the retry policy might be able to determine that the
|
|
RECOVER(6) path can be taken on the last attempt after PROCESS(5)
|
|
has just failed, instead of waiting for the item to be re-presented.
|
|
This is not the default behavior because it requires detailed
|
|
knowledge of what has happened inside the PROCESS(5) block, which is
|
|
not usually available - e.g. if the output included write
|
|
access before the failure, then the exception should be rethrown to
|
|
ensure transactional integrity.</p><p>The completion policy in the outer, REPEAT(1) is crucial to the
|
|
success of the above plan. If the output(5.1) fails it may throw an
|
|
exception (it usually does, as described), in which case the
|
|
transaction TX(2) fails and the exception could propagate up through
|
|
the outer batch REPEAT(1). We do not want the whole batch to stop
|
|
because the RETRY(4) might still be successful if we try again, so
|
|
we add the exception=not critical to the outer REPEAT(1).</p><p>Note, however, that if the TX(2) fails and we <span class="emphasis"><em>do</em></span> try again, by
|
|
virtue of the outer completion policy, the item that is next
|
|
processed in the inner REPEAT(3) is not guaranteed to be the one
|
|
that just failed. It might well be, but it depends on the
|
|
implementation of the input(4.1). Thus the output(5.1) might fail
|
|
again, on a new item, or on the old one. The client of the batch
|
|
should not assume that each RETRY(4) attempt is going to process the
|
|
same items as the last one that failed. E.g. if the termination
|
|
policy for REPEAT(1) is to fail after 10 attempts, it will fail
|
|
after 10 consecutive attempts, but not necessarily at the same item.
|
|
This is consistent with the overall retry strategy: it is the inner
|
|
RETRY(4) that is aware of the history of each item, and can decide
|
|
whether or not to have another attempt at it.</p></section><footer/></body></html> |