This handy method takes a CRON string and is an easy way of creating an awaitable task. It returns True if the await finished without being cancelled by the optional token.
//Async wait until the 0th second of every 5th minute
await PerigeeUtil.BlockUntil("0 */5 * * * *");
//Or for non async methods
PerigeeUtil.BlockUntil("0 */5 * * * *").GetAwaiter().GetResult();
//Block until the next 5 minute mark, or 10 seconds. Whichever comes first
CancellationTokenSource CTSource = new CancellationTokenSource();
CTSource.CancelAfter(TimeSpan.FromSeconds(10));
var done = PerigeeUtil.BlockUntil("*/5 * * * *", null, CTSource.Token).GetAwaiter().GetResult();
Retry and Rety Async
One of the utility class methods is a Retryand RetryAsync. They provide an easy ability to retry on exception thrown with a delay.
The response from these classes is a Tuple where
Item1 is a boolean indicating if it was a success(true), or failed the maximum number of times (false).
Item2 is the exception thrown if it was not a succeed
PerigeeApplication.ApplicationNoInit("CancelTokens", (c) => {
c.AddRecurring("Recurring", (ct, l) => {
//This will be tried 5 times, with 10 seconds between retries.
Tuple<bool, Exception> Retry = PerigeeUtil.Retry(5, (i) => {
bool Success = false;
if (Success == false)
{
throw new Exception("Do or do not, there is a retry");
}
}, 10000);
if (!Retry.Item1)
{
l.LogError(Retry.Item2, "Retries exceeded");
}
});
});
RetryExponentialBackoff
Another retry strategy is the Exponential Backoff method. Unlike a constant delay between retries, this method progressively increases the delay (incorporating jitter) to prevent overwhelming a remote system with requests.
You can define both a base delay (in milliseconds) and a maximum delay (in milliseconds) to ensure the delay between requests scales appropriately.
PerigeeApplication.ApplicationNoInit("Backoff", (c) => {
c.AddRecurring("Exponential", (ct, l) => {
//Log out the backoff delays, logging them is an easy way to test and see what times are going to be used.
l.LogInformation("Backoff times: {time}", string.Join(", ", PerigeeUtil.GetExponentialBackoffDelays(20, 1000, 1800000)));
// Use the .RetryExponential to follow the same times as shown above, with a small jitter to each delay
PerigeeUtil.RetryExponentialBackoff(20, (i) => {
l.LogInformation("Retry number {i}", i);
throw new Exception("Throwing to cause another retry");
}, 1000, 1800000);
});
});
/*
Backoff times: 956, 2102, 4469, 8470, 17127, 31337, 57203, 152968, 234956, 575255, 901233, 1645927, 1800000, 1800000, 1800000, 1800000, 1800000, 1800000, 1800000, 1800000
*/