How to Retry After Exception

How to retry after exception?

Do a while True inside your for loop, put your try code inside, and break from that while loop only when your code succeeds.

for i in range(0,100):
while True:
try:
# do stuff
except SomeSpecificException:
continue
break

Retry after exception in delphi

I often use this construct:

FOR I:=1 TO Retries DO BEGIN
TRY
<Code>
BREAK
EXCEPT
<Report/Log failure, prepare for next iteration>
END
END

this way, it loops around "Retries" number of times, but if it succeeds at some point, it breaks out of the loop.

The EXCEPT part should prepare for the next iteration of the retry loop (like delete any files created by the failed code, etc.), perhaps guarded by an

IF I=Retries THEN
RAISE
ELSE BEGIN
<Report/Log failure, prepare for next iteration>
END

How do you implement a re-try-catch?

You need to enclose your try-catch inside a while loop like this: -

int count = 0;
int maxTries = 3;
while(true) {
try {
// Some Code
// break out of loop, or return, on success
} catch (SomeException e) {
// handle exception
if (++count == maxTries) throw e;
}
}

I have taken count and maxTries to avoid running into an infinite loop, in case the exception keeps on occurring in your try block.

Retry function in Python

Apart from being able to pass functions and use them by adding () after the name (Python's syntax for invoking calls), you don't need to use recursion; just put it in a loop:

import time
def retry(fun, max_tries=10):
for i in range(max_tries):
try:
time.sleep(0.3)
fun()
break
except Exception:
continue

except Exception should be changed to catch a meaningfull exception that the function might raise. Using Exception (as I did in the example) is generally bad practice since it catches a large class of exceptions that you might not of wanted caught.

Apart from that, using a for-loop instead of an explicit third counter and recursion (which leads to a long call-stack for large values) is better.

How can you retry after an exception in Javascript when using promises?

Here's a sample retry function (not yet tested):

function retry(maxRetries, fn) {
return fn().catch(function(err) {
if (maxRetries <= 0) {
throw err;
}
return retry(maxRetries - 1, fn);
});
}

The idea is that you can wrap a function that returns a promise with something that will catch and retry on error until running out of retries. So if you're going to retry sendResponseAsync:

receiveMessageAsync(params)
.then(function(data)) {
return [data, handleMessageAsync(request)];
})
.spread(function(data, response) {
return [response, deleteMessageAsync(request)];
})
.spread(function(response, data) {
return retry(3, function () { return sendResponseAsync(response); });
})
.then(function(data) {
return waitForMessage(data);
})
.catch (function(err) {
// handle error here
});

Since the retry promise won't actually throw until all retries have been exhausted, your call chain can continue.

Edit:

Of course, you could always loop forever if you preferred:

function retryForever(fn) {
return fn().catch(function(err) {
return retryForever(fn);
});
}

How to retry requests on specific exception

You can recursively call the function from itself in your case, although be careful about unexpected edge cases:

def do_request(retry: int = 3):
try:
# There is some scenarios where I would use my own proxies by doing
# requests.get("https://www.bbc.com/", timeout=0.1, proxies={'https': 'xxx.xxxx.xxx.xx'))
while (response := requests.get("https://www.bbc.com/", timeout=0.1)).status_code >= 500:
print("sleeping")
time.sleep(20)

if response.status_code not in (200, 404):
response.raise_for_status()

print("Successful requests!")

soup = BeautifulSoup(response.text, 'html.parser')

for link in soup.find_all("a", {"class": "media__link"}):
yield link.get('href')

except Timeout as err:
if retry:
print(f"Retry due to timed out: {err}")
yield from do_request(retry=retry - 1)
else:
raise

except RequestException as err:
raise RequestException("Unexpected request error")

This will attempt 3 times (or as many as you set in the parameter) until retry is equal to 0 or until another error is encountered

Spring retry exception handling execution behavior

Since you are catching and "handling" the exception, retry is disabled; retry will only work if the method throws an exception.

To change the result (instead of throwing the exception to the caller when retries are exhausted, you need a @Recover method.

Not retryable exceptions will go straight there; you can have multiple @Recover methods for different exception types, or one generic one and you can check the exception type yourself.

Functionality for automatic retry after exception

This looks pretty good, but I would split the running task from the retry. Also use generics, don't just throw Object about.

Use a Java 8 lambda and the return of the method:

public static <T> Optional<T> doWithRetry(final Supplier<T> t) {
for (int retry = 0; retry <= StaticData.NETWORK_RETRY; ++retry) {
try {
Thread.sleep(retry * StaticData.NETWORK_CALL_WAIT);
return Optional.of(t.get());
} catch (InterruptedException | UnknownHostException e) {
LOGGER.log(Level.SEVERE, "Call failed.", e);
return Optional.empty();
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Call failed. Retry.", e);
}
}
LOGGER.log(Level.SEVERE, "Call failed. Retries exceeded.");
return Optional.empty();
}

Also, use a real logger, not printStackTrace...

Usage:

final String data = doWithRetry(() -> {
//do stuff
});

If your lambda needs to throw an exception, you'll need to define your own @FunctionalInterface:

@FunctionalInterface
interface StuffDoer<T> {
T doStuff() throws Exception;
}

And use that in the method signature, you'll need to handle generic Exception.

Pre-Java 8 usage:

final String data = doWithRetry(new StuffDoer<T>() {
@Override
public T get() throws Exception {
return null;
}
});


Related Topics



Leave a reply



Submit