Reputation: 16238
I'm building a Durable Function based on the monitor pattern. I have the code below and my question is regarding the counter variable which I used for a simple exponential retry-backoff.
[FunctionName("RequestOrchestrator")]
public static async Task RequestOrchestrator(
[OrchestrationTrigger] DurableOrchestrationContext monitorContext, ILogger log)
{
DateTime endTime = monitorContext.CurrentUtcDateTime.AddHours(1);
int counter = 0;
while (monitorContext.CurrentUtcDateTime < endTime)
{
var result = await monitorContext.CallActivityAsync<bool>("GetStatusExternal", "test");
if (result)
{
// all ok
break;
}
else
{
counter++;
// Wait for the next checkpoint with exponential backoff
var nextCheckpoint = monitorContext.CurrentUtcDateTime.AddSeconds(5 * counter);
if (!monitorContext.IsReplaying)
{
log.LogInformation($"Next check at {nextCheckpoint}.");
}
await monitorContext.CreateTimer(nextCheckpoint, CancellationToken.None);
}
}
}
Is the usage of the counter ok like this or does the counter++
need to go into
if (!monitorContext.IsReplaying)
counter++;
for it to be replay-safe?
Upvotes: 0
Views: 808
Reputation: 6657
No. You don't need the monitorContext.IsReplaying
check around counter++
.
You need this check only for statements you want to be run just once like logging (as in your code), status updates to an external system, etc.
To be replay-safe, you basically just need your code to be deterministic. So any code that can't be constituted in a Pure Function has to be moved into their own activity functions. Everything else will do.
Like the documentation states, any code that changes over time (replay times) like time-based generators, remote data from external APIs, etc. has to be in activity functions.
Upvotes: 3