1

I'm using Polly for a retry policy:

var policy = Policy
    .Handle<DatabaseException>(x => x.DatabaseErrors.ContainsKey(2601))
    .WaitAndRetry(new[]
    {
        TimeSpan.FromMilliseconds(500),
        TimeSpan.FromMilliseconds(1000),
        TimeSpan.FromMilliseconds(1500)
    }, (exception, timeSpan) => {
        FirstAndRetryMethod();
    });

policy = Policy.Excecute(() => DoSomething());

With the above, FirstAndRetryMethod is called as expected on Retry. How can I call this also the first time DoSomething is executed?

Peter Csala
  • 17,736
  • 16
  • 35
  • 75
Ivan-Mark Debono
  • 15,500
  • 29
  • 132
  • 263
  • `FirstAndRetryMethod` is called whenever the `DoSomething` throws a `DatabaseException` with error code 2601 and you have not exhausted the retry count. Can `FirstAndRetryMethod` throw the same exception with the same status code? – Peter Csala Sep 02 '21 at 14:15
  • @PeterCsala No. – Ivan-Mark Debono Sep 02 '21 at 14:17
  • Does it produce any side-effect? Is the ordering of the method calls (`FirstAndRetryMethod` + `DoSomething` vs `DoSomething` + `FirstAndRetryMethod`) important? – Peter Csala Sep 02 '21 at 14:19
  • @PeterCsala Yes order is important. – Ivan-Mark Debono Sep 02 '21 at 14:21
  • The `onRetry` delegate is executed when the policy is sure that it will be triggered (the thrown exception is handled and the retry count is not exceeded) but before the wait duration (a.k.a penalty). So it is called after the initial (failed) call as well. – Peter Csala Sep 02 '21 at 14:26
  • @PeterCsala And how can I call the method before the initial call? – Ivan-Mark Debono Sep 02 '21 at 14:27
  • You said that ordering matters, so why do want to call that before the initial call? – Peter Csala Sep 02 '21 at 14:30
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/236687/discussion-between-peter-csala-and-ivan-mark-debono). – Peter Csala Sep 02 '21 at 14:33
  • Ordering matters. `FirstAndRetryMethod` must always be called before. On initial call of `DoSomething` or on retries. – Ivan-Mark Debono Sep 02 '21 at 14:34
  • 1
    Then it is quite simple :D `policy.Excecute(() => { FirstAndRetryMethod(); DoSomething(); });` and forgot the `onRetry` delegate. – Peter Csala Sep 02 '21 at 14:36

1 Answers1

2

The Retry policy defines an onRetry optional delegate which is called after the failed attempt but before the wait duration (so called penalty).

So, lets suppose you have the following implementations for FirstAndRetryMethod and DoSomething for debugging purposes:

static int onretryCallCount = 0;
static void FirstAndRetryMethod() {
    Console.WriteLine("FirstAndRetryMethod has been called for the " + onretryCallCount++ + "th time");
}

static int doSomethingCallCount = 0;
static void DoSomething() {
    Console.WriteLine("DoSomething has been called for the " + doSomethingCallCount++ + "th time");
    throw new DatabaseException { ... };
}

Then the output will look like this:

DoSomething has been called for the 0th time
FirstAndRetryMethod has been called for the 0th time
DoSomething has been called for the 1th time
FirstAndRetryMethod has been called for the 1th time
DoSomething has been called for the 2th time
FirstAndRetryMethod has been called for the 2th time
DoSomething has been called for the 3th time

Because you have defined 3 timestamps that's why your retry count is 3.

  • You have an initial attempt and 3 retries (4 in total) (DoSomething has been called for the ...)
  • and 3 onRetry calls (FirstAndRetryMethod has been called for the ...).

If you want to make sure that FirstAndRetryMethod is called prior each and every attempt (including the initial) then you should call it inside the Execute delegate:

policy.Execute(() => { FirstAndRetryMethod(); DoSomething(); });

and you should delete the onRetry part of your policy definition.

Then the output will look like this:

FirstAndRetryMethod has been called for the 0th time
DoSomething has been called for the 0th time
FirstAndRetryMethod has been called for the 1th time
DoSomething has been called for the 1th times
FirstAndRetryMethod has been called for the 2th time
DoSomething has been called for the 2th time
FirstAndRetryMethod has been called for the 3th time
DoSomething has been called for the 3th time

Now you have 4 FirstAndRetryMethod and 4 DoSomething calls.

Peter Csala
  • 17,736
  • 16
  • 35
  • 75