I have an Azure timer function that kicks off every 5 minutes. It is hooked up to Application Insights and the invocation log shows it triggered twice for each time and the same operation ID.
Why the apparently spurious duplication of the invocation in the log?
The relevant code:
public async Task RunEST([TimerTrigger("0 */5 * * * *"
#if DEBUG
, RunOnStartup = true
#endif
)]TimerInfo myTimer, ILogger log, ExecutionContext context)
{...
Screenshot of the invocations in Azure:
Related
I am running on an Azure Consumption Plan. And notice high CPU usage with what I understand as a simple task. I would like to know if my approach is correct. At times CPU was above 80%
I have created a scheduler function, which executes once a minute and checks a SQL db for IoT devices that needs to control at specific times. If the device needs to be controlled, and durable function is executed. This durable function simply sends the device a message and wait for the reply before sending another request.
What I am doing is simply polling the durable function and then sleeping or delaying the function for x seconds as shown below:
[FunctionName("Irrimer_HttpStart")]
public static async Task<HttpResponseMessage> HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")]HttpRequestMessage req,
[OrchestrationClient]DurableOrchestrationClient starter,
ILogger log)
{
// Function input comes from the request content.
log.LogInformation($"Started Timmer Irr");
dynamic eventData = await req.Content.ReadAsAsync<object>();
string ZoneNumber = eventData.ZoneNumber;
string instanceId = await starter.StartNewAsync("Irrtimer", ZoneNumber);
return starter.CreateCheckStatusResponse(req, instanceId);
}
public static async Task<List<string>> RunOrchestrator(
[OrchestrationTrigger] DurableOrchestrationContext context, ILogger log)
{
log.LogInformation($"Time Control Started--->");
Iot_data_state iotstatedata = new Iot_data_state();
iotstatedata.NextState = "int_zone";
var outputs = new List<string>();
outputs.Add("Stating Durable");
iotstatedata.zonenumber = context.GetInput<string>();
iotstatedata.termination_counter = 0;
while (iotstatedata.NextState != "finished")
{
iotstatedata = await context.CallActivityAsync<Iot_data_state>("timer_irr_process", iotstatedata);
outputs.Add(iotstatedata.NextState + " " + iotstatedata.now_time);
if (iotstatedata.sleepduration > 0)
{
DateTime deadline = context.CurrentUtcDateTime.Add(TimeSpan.FromSeconds(iotstatedata.sleepduration));
await context.CreateTimer(deadline, CancellationToken.None);
}
}
return outputs;
}
I have another function "timer_irr_process", which is simply a case statement, which performs and queries as required. Then sets the delay in seconds before it needs to be invoked again. When it gets to the case "Finish", this means the durable function is no longer needed and it exists.
The kind of tasks i am trying to create efficiently is sending a message to IoT device to switch On, observe it performance incase its been controlled manually or various other things. If it malfunctions send a message to a user, if it preforms correctly and task is finished , close the durable function.
Is the any efficient away to doing this?
I have an http triggered azure durable function with an orchestration trigger called "ExecuteWork" and two activities namely "HandleClaimsForms" and "HandleApplicationForms". I will add the definitions for them below. The function is used to process PDFs in a blob storage container. When running locally it will execute "HandleClaimsForms" four or five times on startup without it being called.
Here are the logs that it is producing:
Functions:
Function1: [GET,POST] http://localhost:7071/api/Function1
ExecuteWork: orchestrationTrigger
HandleApplicationForms: activityTrigger
HandleClaimsForms: activityTrigger
[2022-06-07T12:39:44.587Z] Executing 'HandleClaimsForms' (Reason='(null)', Id=c45878fe-35c8-4a57-948e-0b43da969427)
[2022-06-07T12:39:44.587Z] Executing 'HandleClaimsForms' (Reason='(null)', Id=0fb9644d-6748-4791-96cf-a92f6c161a97)
[2022-06-07T12:39:44.587Z] Executing 'HandleClaimsForms' (Reason='(null)', Id=9a39a169-a91d-4524-b5e5-63e6226f70ec)
[2022-06-07T12:39:44.587Z] Executing 'HandleClaimsForms' (Reason='(null)', Id=b3697f6b-7c96-4497-826f-3894359ff361)
[2022-06-07T12:39:44.587Z] Executing 'HandleClaimsForms' (Reason='(null)', Id=3ca3bbce-1657-453b-a5b3-e9dbdb940302)
Here are the Function definitions:
Function entrypoint
[FunctionName("Function1")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
[DurableClient] IDurableOrchestrationClient starter,
ILogger log)
{
string instanceID = await starter.StartNewAsync("ExecuteWork");
return starter.CreateCheckStatusResponse(req, instanceID);
}
Orchestration trigger
[FunctionName("ExecuteWork")]
public async Task<bool> ProcessForms(
[OrchestrationTrigger] IDurableOrchestrationContext context,
ILogger log)
{
bool success = true;
try
{
await context.CallActivityAsync("HandleClaimsForms", success);
await context.CallActivityAsync("HandleApplicationForms", success);
return success;
}
catch (Exception err)
{
log.LogInformation($"The following error was thrown: {err}");
success = false;
return success;
}
}
HandleClaimsForm Activity
public async Task<bool> ProcessClaimsForms(
[ActivityTrigger]bool success)
{
await _docHandler.Handle();
return success;
}
HandleApplicationForm activity
[FunctionName("HandleApplicationForms")]
public async Task<bool> ProcessApplicationForms(
[ActivityTrigger]bool success)
{
await _appHandler.HandleJsonApplicationFormAsync();
return success;
}
One of the workaround you can follow to resolve the above issue,
Based on the MICROSOFT DOCUMENT about the reliability is:
Durable Functions uses event sourcing transparently. Behind the scenes, the await (C#) or yield (JavaScript/Python) operator in an
orchestrator function yields control of the orchestrator thread back
to the Durable Task Framework dispatcher.
The orchestrator wakes up and re-executes the entire function from scratch to rebuild the local state whenever an orchestration function
is given more work to do (for instance, when a response message is
received or a durable timer expires). The Durable Task Framework
analyses the orchestration's execution history if the code tries to
invoke a function or do any other async task during the replay. In the
event that it discovers that the activity function has already run and
produced a result, it replays that result while the orchestrator code
keeps running. Playback continues until the function code terminates
or until additional async work has been scheduled.
Another, approach is to use the dependency injection .
For more information please refer the below links:-
SIMILAR SO THREAD| HTTP Trigger on demand azure function calling itself multiple times & Azure Durable Function Activity seems to run multiple times and not complete .
I have an azure timer function.
It works when I run it locally.
It works if I remove this code when running in Azure:
[EventGrid(TopicEndpointUri = "EventGridUri", TopicKeySetting = "EventGridKey")] IAsyncCollector outputEvents
Otherwise it does not work. The timer never seems to go off and the function is not triggered.
The code is below. I have tried removing the for loop and everything else with the idea that I might be getting a silent exception, but the function still does not execute. Any idea how to troubleshoot or what might be causing the issue?
public static class TimeTest
{
[FunctionName("TimeTest")]
public static async Task Run(
[TimerTrigger("0 */1 * * * *")] TimerInfo myTimer,
[EventGrid(TopicEndpointUri = "EventGridUri", TopicKeySetting = "EventGridKey")] IAsyncCollector<EventGridEvent> outputEvents)
{
for (var i = 0; i < 3; i++)
{
var myEvent = new EventGridEvent("message-id-" + i, "subject-name", "event-data", "event-type", DateTime.UtcNow, "1.0");
await outputEvents.AddAsync(myEvent);
}
}
}
I had a lot of trouble finding the exception, but was finally able to see it when I went to application insights for the entire functions app (as opposed to trying to see logs at the function level).
It said that my eventuri was incorrect. After taking a closer look I realized that I had not given my functions permission to the keyvault.
I came across the link below, and have questions:
https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-checkpointing-and-replay
1 When an OrchestrationTrigger Durable Function is invoked, and crashes for some reasons (e.g. after max timeout duration of 10 mins), will the inputs, names, below be read from table storage or queue automatically.
[FunctionName("E1_HelloSequence")]
public static async Task<List<string>> Run(
[OrchestrationTrigger] DurableOrchestrationContext context)
{
var names= ctx.GetInput<List<string>>();
var outputs = new List<string>();
outputs.Add(await context.CallActivityAsync<string>("E1_SayHello", names[0]));
outputs.Add(await context.CallActivityAsync<string>("E1_SayHello", names[1]));
// returns ["Hello Tokyo!", "Hello Seattle!"]
return outputs;
}
2 After it crashes, will it re-start automatically.
3 At each await, the function transits into wait status, does the wait period contribute to part of max timeout duration?
Hi as Chris from Function Product Group is already involved with you on GitHub Thread.
Posting it here so that it is beneficial for other members as well.
1) Yes, the results of any executed activity function will be read from table storage.
2) Yes, the function will retry automatically. An existing queue message ensures this.
3) No, time spent awaiting does not count against your max function timeout. Nor are you
billed for time spent awaiting.
We have created an azure function which is set as timer triggered . We want to schedule invoke the same func012.tion in different time intervals. i.e
1) Every Week Friday with certain set of input parameters
2) Every Month Last day with certain set of input parameters
Thanks
The timer trigger can only take a single cron schedule.
Do this as a union of schedules. Have multiple timer triggers - each with a part of the schedule (Friday vs. Monday) and then each can call to a common function passing the respective parameters.
Here is a sample
public async Task FunctionLogicOnTimer(string parameter)
{
// ...
// ...
}
[FunctionName(nameof(MyFunc1))]
public async Task MyFunc1(
[TimerTrigger("%MyTimerIntervalFromSettings1%")] TimerInfo timer, ILogger log)
{
// ...
// ...
FunctionLogicOnTimer("I am triggered from MyFunc1");
}
[FunctionName(nameof(MyFunc2))]
public async Task MyFunc2(
[TimerTrigger("%MyTimerIntervalFromSettings2%")] TimerInfo timer ILogger log)
{
// ...
// ...
FunctionLogicOnTimer("I am triggered from MyFunc2");
}
Functions take a single scheduling configuration. Therefore you can create Scheduler/Logic app on different days to trigger your function.
Alternatively, create two functions (FuncitonA_FridayJob,FunctionA_MondayJob) with a specific scheduling.