rfc:retry-keyword
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
rfc:retry-keyword [2017/06/19 13:22] – Add lots more examples & refine syntax sammyk | rfc:retry-keyword [2017/09/22 13:28] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== PHP RFC: Retry keyword in catch blocks | + | ====== PHP RFC: Retry functionality |
* Version: 1.0 | * Version: 1.0 | ||
* Date: 2016-06-19 | * Date: 2016-06-19 | ||
Line 19: | Line 19: | ||
* Retry the '' | * Retry the '' | ||
* Execute arbitrary code before each retry (to sleep, log, check exception code, etc) | * Execute arbitrary code before each retry (to sleep, log, check exception code, etc) | ||
- | * Access to the number of times the try block has been executed (with ' | + | * Access to the number of times the try block has been executed (with '' |
- | * Use the '' | + | * Use the '' |
<code php> | <code php> | ||
Line 26: | Line 26: | ||
somethingSketchy(); | somethingSketchy(); | ||
} retry 3 (RecoverableException $e, $attempt) { | } retry 3 (RecoverableException $e, $attempt) { | ||
- | echo " | + | echo " |
sleep(1); | sleep(1); | ||
} catch (RecoverableException $e) { | } catch (RecoverableException $e) { | ||
- | echo $e-> | + | echo $e-> |
} | } | ||
</ | </ | ||
Line 81: | Line 81: | ||
</ | </ | ||
- | There are currently a few ways to implement a feature that will retry a failed block of code '' | + | There are currently a few ways to implement a feature that will retry a failed block of code '' |
=== Recursive Functions === | === Recursive Functions === | ||
Line 87: | Line 87: | ||
<code php> | <code php> | ||
function myRetryFunction($maxTries) { | function myRetryFunction($maxTries) { | ||
- | try { | + | |
- | somethingSketchy(); | + | somethingSketchy(); |
- | } catch (RecoverableException $e) { | + | } catch (RecoverableException $e) { |
- | if ($maxTries === 0) { | + | if ($maxTries === 0) { |
- | die(' | + | die(' |
- | } | + | } |
- | myRetryFunction(--$maxTries); | + | myRetryFunction(--$maxTries); |
- | } | + | } |
} | } | ||
Line 108: | Line 108: | ||
for ($x=0; $x< | for ($x=0; $x< | ||
- | try { | + | |
- | somethingSketchy(); | + | somethingSketchy(); |
- | break; | + | break; |
- | } catch (RecoverableException $e) { | + | } catch (RecoverableException $e) { |
- | die(' | + | die(' |
- | } | + | } |
} | } | ||
</ | </ | ||
Line 126: | Line 126: | ||
retryTheThing: | retryTheThing: | ||
try { | try { | ||
- | somethingSketchy(); | + | |
} catch (RecoverableException $e) { | } catch (RecoverableException $e) { | ||
- | if (--$maxTries > 0) { | + | |
- | goto retryTheThing; | + | goto retryTheThing; |
- | } | + | } |
- | die(' | + | die(' |
} | } | ||
</ | </ | ||
- | This is arguably the cleanest option | + | While this is arguably the cleanest option, it still requires |
- | === Use Retry === | + | <code php> |
+ | $maxTries = 5; | ||
+ | |||
+ | retryTheThing: | ||
+ | |||
+ | someCodeIDoNotWantToRetry(); | ||
+ | |||
+ | try { | ||
+ | somethingSketchy(); | ||
+ | } catch (RecoverableException $e) { | ||
+ | if (--$maxTries > 0) { | ||
+ | goto retryTheThing; | ||
+ | } | ||
+ | die(' | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Use Retry ==== | ||
Using the '' | Using the '' | ||
Line 143: | Line 160: | ||
<code php> | <code php> | ||
const MAX_TRIES = 5; | const MAX_TRIES = 5; | ||
- | $attempts | + | $attempt |
try { | try { | ||
- | somethingSketchy(); | + | |
} catch (RecoverableException $e) { | } catch (RecoverableException $e) { | ||
- | if ($attempt < MAX_TRIES) { | + | |
- | sleep(1); | + | sleep(1); |
- | // And log stuff maybe | + | // And log stuff maybe |
- | retry; | + | retry; |
- | } | + | } |
- | die(' | + | die(' |
} | } | ||
</ | </ | ||
- | Alternatively using the block-level implementation of '' | + | Alternatively using the block-level implementation of '' |
<code php> | <code php> | ||
Line 179: | Line 196: | ||
<code php> | <code php> | ||
try { | try { | ||
- | throw new RecoverableException(" | + | |
} retry 3 (RecoverableException | AnotherRecoverableException $e, $attempt) { | } retry 3 (RecoverableException | AnotherRecoverableException $e, $attempt) { | ||
- | echo " | + | echo " |
- | sleep(1); | + | sleep(1); |
} catch (RecoverableException $e) { | } catch (RecoverableException $e) { | ||
- | echo $e-> | + | echo $e-> |
} | } | ||
Line 196: | Line 213: | ||
<code php> | <code php> | ||
try { | try { | ||
- | throw new RecoverableException(" | + | |
} retry 10 (RecoverableException $e, $attempt) { | } retry 10 (RecoverableException $e, $attempt) { | ||
echo " | echo " | ||
Line 210: | Line 227: | ||
<code php> | <code php> | ||
try { | try { | ||
- | throw new RecoverableException(" | + | |
} retry (RecoverableException $e, $attempt) { | } retry (RecoverableException $e, $attempt) { | ||
echo " | echo " | ||
Line 222: | Line 239: | ||
<code php> | <code php> | ||
try { | try { | ||
- | throw new RecoverableException(" | + | |
} retry INF (RecoverableException $e, $attempt) { | } retry INF (RecoverableException $e, $attempt) { | ||
echo " | echo " | ||
Line 232: | Line 249: | ||
=== Breaking out of retry === | === Breaking out of retry === | ||
- | It is sometimes necessary to have some logic that would abort any more retry attempts, like in the case of retrying forever. That can be done using the ``break`` keyword. | + | It is sometimes necessary to have some logic that would abort any more retry attempts, like in the case of retrying forever. That can be done using the '' |
<code php> | <code php> | ||
try { | try { | ||
- | throw new RecoverableException(" | + | |
} retry INF (RecoverableException $e, $attempt) { | } retry INF (RecoverableException $e, $attempt) { | ||
- | if (42 === $e-> | + | |
- | break; | + | break; |
- | } | + | } |
echo " | echo " | ||
} catch (RecoverableException $e) { | } catch (RecoverableException $e) { | ||
Line 258: | Line 275: | ||
$id = 42; | $id = 42; | ||
try { | try { | ||
- | throw new RecoverableException(" | + | |
} retry 3 (RecoverableException | AnotherRecoverableException $e, $attempt) { | } retry 3 (RecoverableException | AnotherRecoverableException $e, $attempt) { | ||
- | if (42 === $e-> | + | |
- | break; | + | break; |
- | } | + | } |
echo " | echo " | ||
- | sleep(1); | + | |
} catch (RecoverableException | AnotherRecoverableException $e) { | } catch (RecoverableException | AnotherRecoverableException $e) { | ||
echo $e-> | echo $e-> | ||
Line 281: | Line 298: | ||
function retry(int $retryCount, | function retry(int $retryCount, | ||
{ | { | ||
- | $attempts = 0; | + | |
tryCode: | tryCode: | ||
try { | try { | ||
return $tryThis(); | return $tryThis(); | ||
} catch (\Throwable $e) { | } catch (\Throwable $e) { | ||
- | $isTargetException = false; | + | |
- | foreach ($targetExceptions as $targetException) { | + | foreach ($targetExceptions as $targetException) { |
- | if ($e instanceof $targetException) { | + | if ($e instanceof $targetException) { |
- | $isTargetException = true; | + | $isTargetException = true; |
- | break; | + | break; |
- | } | + | } |
- | } | + | } |
if (!$retryCount || !$isTargetException) { | if (!$retryCount || !$isTargetException) { | ||
throw $e; | throw $e; | ||
Line 299: | Line 316: | ||
$shouldRetry = true; | $shouldRetry = true; | ||
if ($beforeRetry) { | if ($beforeRetry) { | ||
- | $shouldRetry = $beforeRetry($e, | + | |
} | } | ||
if ($shouldRetry) { | if ($shouldRetry) { | ||
- | goto tryCode; | + | |
} | } | ||
throw $e; | throw $e; | ||
Line 310: | Line 327: | ||
$id = 42; | $id = 42; | ||
try { | try { | ||
- | $result = retry(3, function () use ($id) { | + | |
- | throw new AnotherRecoverableException(" | + | throw new AnotherRecoverableException(" |
- | }, function ($e, $attempt) use ($id) { | + | }, function ($e, $attempt) use ($id) { |
- | if (42 === $e-> | + | if (42 === $e-> |
- | return false; | + | return false; |
- | } | + | } |
- | echo " | + | echo " |
- | sleep(1); | + | sleep(1); |
- | return true; | + | return true; |
- | }, [RecoverableException:: | + | }, [RecoverableException:: |
} catch (RecoverableException | AnotherRecoverableException $e) { | } catch (RecoverableException | AnotherRecoverableException $e) { | ||
echo $e-> | echo $e-> | ||
Line 361: | Line 378: | ||
===== Proposed PHP Version ===== | ===== Proposed PHP Version ===== | ||
- | Next PHP 7.2. | + | Next PHP 7.3. |
===== Proposed Voting Choices ===== | ===== Proposed Voting Choices ===== | ||
Requires a 2/3 majority. | Requires a 2/3 majority. | ||
+ | |||
+ | ==== Add block-level retry ==== | ||
+ | |||
+ | <code php> | ||
+ | try { | ||
+ | somethingSketchy(); | ||
+ | } retry 3 (RecoverableException $e, $attempt) { | ||
+ | sleep(1); | ||
+ | } catch (RecoverableException $e) { | ||
+ | echo $e-> | ||
+ | } | ||
+ | </ | ||
<doodle title=" | <doodle title=" | ||
Line 371: | Line 400: | ||
* No | * No | ||
</ | </ | ||
+ | |||
+ | ==== Add retry keyword ==== | ||
+ | |||
+ | <code php> | ||
+ | try { | ||
+ | somethingSketchy(); | ||
+ | } catch (RecoverableException $e) | ||
+ | retry; | ||
+ | } | ||
+ | </ | ||
<doodle title=" | <doodle title=" | ||
Line 379: | Line 418: | ||
===== Patches and Tests ===== | ===== Patches and Tests ===== | ||
- | There are a few WIP implementations of '' | + | There are a few slightly outdated |
* [[https:// | * [[https:// |
rfc/retry-keyword.1497878520.txt.gz · Last modified: 2017/09/22 13:28 (external edit)