Skip to content

3.0.0

Latest

Choose a tag to compare

@Aldaviva Aldaviva released this 27 Sep 21:13
3.0.0
aeae084

Features

Retrier

  • Pass exception and attempt # to beforeRetry and afterFailure actions.
  • Add built-in delay functions for constant, linear, exponential, power, log, and random delays.
  • Let users limit Retrier attempts by total duration, in addition to attempt quantity.
  • Changed Retrier from using optional parameters to encapsulating them in a struct.
  • Added optional callback that runs between the failure and the delay before the next attempt, which is nice for logging the intermediate failure.
  • Allow async Retrier overloads to take options with either synchronous or asynchronous callbacks for IsRetryAllowed, AfterFailure, and BeforeRetry without a separate method name (AttemptAsync), allowing async callbacks in sync methods, or forcing those callbacks to always be async, which I tried and causes a warning or extra ugly return statement, takes more lines, prevents one-line expression bodies, and it's too easy to forget and get the sync overload which causes inscrutable bugs because it's not awaiting the func to detect exceptions. Instead, make clever use of an interface hierarchy and some generic type reflection to fix broken method overload resolution (T vs Task<T>).

Fixes

Throttler and Debouncer

  • Remove array pooling for argument storage, which was added in 54c2db7, because it uses the same amount of memory (ConcurrentStack node objects allocate memory when returning an array to the pool) and takes longer to execute (2.3× – 3.8× as long, depending on how many arguments the func takes). If this causes problems, blame Stephen Toub (https://youtu.be/bw7ljmvbrr0?t=410, https://youtu.be/bw7ljmvbrr0?t=1477).
  • Statically declare argument array length instead of reflecting it.
  • Invoke callback using dynamic language runtime, which is 6–8.3× as fast as CLR reflection's Delegate.DynamicInvoke.