Reputation: 163
I am creating an Azure function and would like it to run with a random delay between each run. I want the delay between each run to be randomly selected from the interval 10 - 20 minutes. For example, I want:
Is this possible? Thanks.
Upvotes: 2
Views: 1285
Reputation: 121
Durable Function is the way to go. But instead of using a loop, you can use the ContinueAsNew()
method in IDurableOrchestrationContext
. This will make the orchestration start over, which prevents your orchestration history table becoming overly long from using a simple loop.
Also, the orchestrator needs to be deterministic, so you shouldn't use random number generators or call DateTime.Now
in the orchestrator.
[FunctionName("Orchestrator")]
public static async Task RunOrchestrator([OrchestrationTrigger] IDurableOrchestrationContext context)
{
int delay = await context.CallActivityAsync<int>("Activity", null);
await context.CreateTimer(context.CurrentUtcDateTime.AddMinutes(delay), CancellationToken.None);
context.ContinueAsNew(null);
}
[FunctionName("Activity")]
public static int DoActivity([ActivityTrigger] object input, ILogger log)
{
// Do whatever you want to do at random intervals.
return new Random((int)DateTime.Now.Ticks).Next(1, 60);
}
By the way, due to how durable orchestration works, there is actually no function running when you await on the timer you created in the orchestrator, so you wouldn't be charged during the delay. You are still charged for await time spent in client and activity functions though.
More information:
https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-orchestrations
https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-code-constraints
https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-eternal-orchestrations
Upvotes: 2
Reputation:
functions.json
Do not modify the functions.json
as suggested. It restarts your entire function app, which in my case (using Node.js) also means that I am getting charged a small but noticeable amount of money for reading/writing tens of thousands of files in my node_modules
folder.
Your best bet is to run the function each minute, but exit immediately most of the time. Here's an example. I assume we want to run the function randomly, but on average we want to run the function every 15 minutes.
// On average, run the function every N minutes:
const AVERAGE_RUN_EVERY=15;
if (Math.random() > 1 / AVERAGE_RUN_EVERY) {
// Most of the time, we will exit here:
context.done();
} else {
// Your actual code here
}
int AVERAGE_RUN_EVERY = 15;
Random rnd = new Random();
if (rnd.Next(0, AVERAGE_RUN_EVERY) == 0) {
// Your actual code here
}
Assuming the minimum charge for each execution is 100ms and the memory used by your application is 256 MB or less, every month you will get charged:
0.1s * 0.25 GB * 1440 minutes/day * 30 days * $0.000016/GB/s = 0.02 USD
Actually, you may even end up saving money because you function app will not enter sleep mode if it's running each minute, meaning that the function will consume less time for the startup.
Upvotes: 4
Reputation: 4456
It is possible with Durable Functions using the CreateTimer
method.
Example:
public static async Task Run(DurableOrchestrationContext ctx)
{
//Do some work here
while (true)
{
// Orchestration will sleep until this time
var nextCheck = ctx.CurrentUtcDateTime.AddSeconds(randomNumber);
await ctx.CreateTimer(nextCheck, CancellationToken.None);
//Call the function again
}
}
You can read more about it here Azure Durable Functions
Upvotes: 1