[RFC] [Discussion] Retry functionality

php.internals

Sammy Kaye Powers

9 years ago
Hello internals! The RFC that proposes adding retry functionality to the `try/catch/finally` block is now officially "under discussion". https://wiki.php.net/rfc/retry-keyword Voting will open on Monday, July 3rd, 2017 @ 9 am CDT. Voting will close on Monday, July 17th, 2017 @ 9 am CDT. Discuss amongst yourselves. :) Thanks, Sammy Kaye Powers sammyk.me

Ivan Enderlin @ Hoa

9 years ago
Hello :-), Thank you for the RFC. I have a question though. I would like to know how is it different from the `goto` language construction? If I understand it correctly, both the following examples are identical: try { // … } catch (…) { retry; } and: try { retry: // … } catch (…) { goto retry; } Also, what happens if the `try` block keeps failing over and over again: This is a non-breakable loop. Thank you for your feedbacks :-). Cheers. On 19.06.17 15:55, Sammy Kaye Powers wrote:

lists@rhsoft.net

9 years ago
Am 19.06.2017 um 16:24 schrieb Ivan Enderlin:
> Thank you for the RFC. I have a question though. I would like to know > how is it different from the `goto` language construction? > > If I understand it correctly, both the following examples are identical: > > try { > > // … > > } catch (…) { > > retry; > > } > > and: > > try { > > retry: > > // … > > } catch (…) { > > goto retry; > > }
even if both works the retry-statement is much clearer, especially when the code becomes larger than these few lines
> Also, what happens if the `try` block keeps failing over and over again: > This is a non-breakable loop.
well, as for other loops you are responsible at your own to count up a $retry_count and stop after N tries

Mike Willbanks

9 years ago
> > Hello internals! > > The RFC that proposes adding retry functionality to the > `try/catch/finally` block is now officially "under discussion". >
This feature seems like something that would be extremely useful. However, the proposed syntax for the number of retries for a block level seems to get me. I think what might actually be better from a functional standpoint is: try { doSomething() } catch (SomethingException $e) { retry 3; } catch (RetryMaximumExceeded $e) { $e->getOriginatingException(); } Forcing retry to only work on the keyword level and then providing a distinct exception when the retry has been exceeded. The issue obviously with the above is that you would need to be able to add the originating exception to it rather than bubbling up. What I like more about this, is that it makes it far more clear as per the rejected path and allows you to determine that you had to throw since the retries failed so many times. Often in many applications, you might retry a couple of times and then defer that action to be handled in the background at a later time. In addition, you may also still want to handle that exception to check certain criteria around the failure. For instance, it is often that libraries reuse the same exception but providing different codes and/or messages that you may want to check to see if it is retryable or add additional meta data to the response. I also think that the RFC should state that retry keyword MUST be used with a numeric number to prevent continuous loops. Eventually all loops must die and preventing this early on seems to be something that would be a good idea to handle.

Dan Ackroyd

9 years ago
Hi Sammy, On 19 June 2017 at 14:55, Sammy Kaye Powers <me@sammyk.me> wrote:
> Hello internals!
Please could you add to the RFC a description of what a 'break' in a retry block actually does? Although there is an example for it, and so people can guess what it does, having it described clearly would be better. Could you also confirm, the number of retries can't be an expression, right? i.e. the number of retries has to be hard-coded into the script? I don't believe the section "check out a full userland implementation that covers all the features of the example above with a fully-featured retry() function." is a valid comparison, and certainly not how I (and I suspect other people) write re-attempt code. For me it is much more normal to just use an in place for($attempt.....) loop. A for-loop based equivalent of the example from the RFC is below. Although it is a couple of lines longer than the 'retry' version, it's not drastically longer. It also has the benefit of not having a piece of data (the number of retry attempts) be hard-coded into the PHP script that does the retrying.
> It forces the developer to make extra methods or functions,
tbh - that sounds like a good thing. One function to attempt the thing, and another function to decide whether to retry or do something else. cheers Dan for ($attempt=0; ; $attempt++) { $id = 42; try { throw new RecoverableException("FAILED getting ID #{$id}"); break; // obviously this won't be reached - but is here for completeness } catch (RecoverableException | AnotherRecoverableException $e) { if ($attempt > MAX_RETRY_ATTEMPTS) { echo $e->getMessage(); throw $e; } if (42 === $e->getCode()) { throw $e; } echo "Failed getting ID #{$id} on try #{$attempt}. Retrying..."; sleep(1); } catch (NonRecoverableException $e) { echo $e->getMessage(); throw $e; } }

Marco Pivetta

9 years ago
Hey Sammy, From a language design perspective, this is syntactic sugar that brings a lot of cost for anyone working on optimisations. In most scenarios that I worked on, the retry functionality should always be written as following: try { $externalCollaborator->doSomething($with, $a, $lot, $of, $by, $val, $parameters); } catch (SomethingSomething $e) { $externalCollaborator->doSomething($with, $a, $lot, $of, $by, $val, $parameters); } The reason why it is extremely important to have an external collaborator is that logic wrapped in a retry *MUST* be tested for idempotence. Just imagine what could happen if a credit card payment was processed twice! That said, the above can be rewritten as following: retry( function () use ($externalCollaborator, $with, $a, $lot, $of, $by, $val, $parameters) { $externalCollaborator->doSomething($with, $a, $lot, $of, $by, $val, $parameters); }, [SomethingSomething::class], 1 ); Where the signature of `retry` is as following: function retry(callable $executedLogic, array $caughtExceptionTypes, int $maxRetries) { /* ... */ } This kind of approach is simpler to understand, to test, and doesn't include the "hidden GOTO semantics" that are proposed in this patch, and that would make SSA optimizations quite hard to perform. Given the above, I'm sadly going to vote "NO" on this proposal. Greets, Marco Pivetta http://twitter.com/Ocramius http://ocramius.github.com/ On Mon, Jun 19, 2017 at 3:55 PM, Sammy Kaye Powers <me@sammyk.me> wrote:

François Laupretre

9 years ago
Hi, It seems you just overwrote the RFC main page (https://wiki.php.net/rfc) with your 'retry' RFC (with the 'remove words "visual debt"' change). I tried to follow instructions to revert to the previous revision (select revision and click 'Edit this page') but it does not seem to work (the displayed page is always the latest one) and the wiki is sooooooooooo slow... So, could you please revert your change (go back to 2017/06/19 19:19) <https://wiki.php.net/rfc?rev=1497892778&do=diff>. Thanks François Le 19/06/2017 à 15:55, Sammy Kaye Powers a écrit :

Kalle Sommer Nielsen

9 years ago
Hi 2017-06-19 20:05 GMT+02:00 François Laupretre <francois@tekwire.net>:
> Hi, > > It seems you just overwrote the RFC main page (https://wiki.php.net/rfc) > with your 'retry' RFC (with the 'remove words "visual debt"' change). > > I tried to follow instructions to revert to the previous revision (select > revision and click 'Edit this page') but it does not seem to work (the > displayed page is always the latest one) and the wiki is sooooooooooo > slow... So, could you please revert your change (go back to 2017/06/19 > 19:19) <https://wiki.php.net/rfc?rev=1497892778&do=diff>.
Should be somewhat good now, let me know if I missed something
-- regards, Kalle Sommer Nielsen kalle@php.net

François Laupretre

9 years ago
I don't know which version you restored, and clicking on the glasses to display differences between versions does not display anything, but I lost the changes I did before the page was overwritten. I will do it again but, IMO, anybody having changed something on the main RFC page recently should check the current version. Thanks François Le 19/06/2017 à 20:18, Kalle Sommer Nielsen a écrit :

Sammy Kaye Powers

9 years ago
On Mon, Jun 19, 2017 at 1:30 PM, François Laupretre <francois@tekwire.net> wrote:
> I don't know which version you restored, and clicking on the glasses to > display differences between versions does not display anything, but I lost > the changes I did before the page was overwritten. I will do it again but, > IMO, anybody having changed something on the main RFC page recently should > check the current version. > > Thanks > > François > > > > Le 19/06/2017 à 20:18, Kalle Sommer Nielsen a écrit : >> >> Hi >> >> 2017-06-19 20:05 GMT+02:00 François Laupretre <francois@tekwire.net>: >>> >>> Hi, >>> >>> It seems you just overwrote the RFC main page (https://wiki.php.net/rfc) >>> with your 'retry' RFC (with the 'remove words "visual debt"' change). >>> >>> I tried to follow instructions to revert to the previous revision (select >>> revision and click 'Edit this page') but it does not seem to work (the >>> displayed page is always the latest one) and the wiki is sooooooooooo >>> slow... So, could you please revert your change (go back to 2017/06/19 >>> 19:19) <https://wiki.php.net/rfc?rev=1497892778&do=diff>. >> >> Should be somewhat good now, let me know if I missed something >> >> >> >
OMG how embarrassing! I'm so sorry everyone. It looks as it did at 9AM this morning for me thanks to Kalle's fast fingers. François - I hope you didn't lose too many changes. I will have to buy you an expensive coffee or something for your trouble! :/ Thanks, Sammy Kaye Powers sammyk.me

François Laupretre

9 years ago
Hi, No problem, I just had changed the status of two RFCs. It's OK now. I just said people should check their changes because one of my changes was to move an RFC from 'in discussion' to 'accepted for 7.2' and, after Kalle restored the page, the RFC was in 'Pending implementation', where it never had been before ! One thing I'd like to know is why displaying the differences between two versions does not work. BTW, does someone know why lxr.php.net is not available anymore ? I's been this way for at least one month now. Regards François Le 19/06/2017 à 20:41, Sammy Kaye Powers a écrit :

Aidan Woods

9 years ago
Hi all, It might be useful to incorporate the "retry if" condition that'll likely arise in use of this, into the feature itself. Such that after the retry keyword you could optionally specify a truthy value. Then you could write something like $retries = 5; try { // … } catch (…) { retry $retries--; } Kind regards, Aidan

Stas Malyshev

9 years ago
Hi!
> The RFC that proposes adding retry functionality to the > `try/catch/finally` block is now officially "under discussion". > > https://wiki.php.net/rfc/retry-keyword
To me, it looks like this belongs in userspace, not as a language keyword. I don't really see what it does that you can't do with existing loop constructs. The RFC proclaims that using loops "less than ideal" but provides zero arguments for it. Introducing new keyword into a language should have a high barrier - since it raises the complexity, makes the language harder to learn and increases the number of corner cases and code to maintain. I fail to see this syntax sugar providing enough value to clear the barrier.
> Voting will open on Monday, July 3rd, 2017 @ 9 am CDT.
Also, having only 2 weeks to discuss about introducing a new language keyword sounds like extremely short period. Especially at the summer when many people go to vacations. There's no rush, really. 2 weeks is a *minimal* time, not the time to strive for in any case.
-- Stas Malyshev smalyshev@gmail.com

Sammy Kaye Powers

9 years ago
On Tue, Jun 20, 2017 at 12:47 AM, Stanislav Malyshev <smalyshev@gmail.com> wrote:
> Hi! > > Also, having only 2 weeks to discuss about introducing a new language > keyword sounds like extremely short period. Especially at the summer > when many people go to vacations. There's no rush, really. 2 weeks is a > *minimal* time, not the time to strive for in any case.
I'm OK with holding off on the retry RFC to allow more discussion and give the RFC the TLC that it needs after getting receiving all the feedback. So we won't be going to vote on the retry RFC today, rather we'll shoot for PHP 7.3 at a later date. :) Thanks, Sammy Kaye Powers sammyk.me