Skip to content

Instantly share code, notes, and snippets.

@kvz
Last active December 20, 2015 06:58
Show Gist options
  • Save kvz/6089432 to your computer and use it in GitHub Desktop.
Save kvz/6089432 to your computer and use it in GitHub Desktop.
Tries your function several times with a bigger & bigger interval, until it does not throw an exception. Useful if you want to gracefully handle external services not being available, without actually building retries into your code. Works via Hollywood principle: Don't call us, we'll call you.
<?php
Class SomeClass() {
public function retry ($cb, $intervals = array(2, 4, 8, 16)) {
while ($intervals) {
if (!is_a($results = $cb(), 'Exception')) {
// good results, return them
return $results;
}
// failed, sleep for a larger & larger interval
$backoff = array_shift($intervals);
sleep($backoff);
}
// all retries failed :'( return the exception
return $results;
}
public function run () {
$results = $this->retry(function () use ($model, $findOptions) {
try {
// Your code that could throw an exception here
return $model->find('all', $findOptions);
} catch (Exception $e) {
// Return the exception to retry()
return $e;
}
}, $intervals = array(2, 4, 8, 16));
// Config exponential backoff --^
// You could also calculate it, but I think for most usecases it makes
// sense to have a limited and configurable backoff that gets eaten away.
// Also less prone to bugs / endless loops.
if (is_a($results, 'Exception') {
printf(
'Sorry, but even after %d tries in %d seconds I still got the Exception "%s"',
count($intervals),
array_sum($intervals),
$e->getMessage()
);
} else {
printf('Some nice results!');
print_r($results);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment