Kumari Dimple
Kumari Dimple

Reputation: 363

How to invoke Durable function by timer trigger?

I am new to Durable function(Orchestration function) and seen sample application as per Microsoft documentation.So I have few doubts.

example:

public static async Task<HttpResponseMessage> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, methods: "post", 
            Route = "orchestrators/{functionName}")] HttpRequestMessage req,
            [OrchestrationClient] DurableOrchestrationClient starter,
            string functionName,
            TraceWriter log)
        {
            // Function input comes from the request content.
            dynamic eventData = await req.Content.ReadAsAsync<object>();
            string instanceId = await starter.StartNewAsync(functionName, eventData);

            log.Info($"Started orchestration with ID = '{instanceId}'.");

            return starter.CreateCheckStatusResponse(req, instanceId);
        } 

to invoke it I made HTTP POST request using postman so request processed successfully but when I configured different verb like HTTP GET it was responded with NotFound" error in console as well as request made to it with http request from browser responded with "NotFound" error in console .Why this happened?

Can I invoke any Orchestration function with in timer trigger azure function?

If not why?

UPDATE:

Some additional details about question

    [FunctionName("TimerTrigger")]
            public static async Task Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, TraceWriter log)
            {//this runs for every 5minutes
                using (HttpClient client = new HttpClient())
                {
                    var content = new FormUrlEncodedContent(new[]
                {
                    new KeyValuePair<string, string>("", "")
                });
               //making request to above function by http trigger
                    var result = await client.PostAsync("http://localhost:7071/orchestrators/E1_HelloSequence", content);
                }
                log.Info($"C# Timer trigger function executed at: {DateTime.Now}");
                return;
            }

can I make request to http trigger by timer triggred why because my durable function has long running process so if invoke orchestration function in timer trigger itself so there might be possibility of timer triggered timeout so that why I am trying to follow this approach.Is it possible to invoke by above code?

Upvotes: 12

Views: 21989

Answers (4)

jreancsu
jreancsu

Reputation: 421

The Microsoft Docs provide an example for an "eternal work" orchestrator to orchestrate work that needs to be done periodically but forever: https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-eternal-orchestrations?tabs=csharp#periodic-work-example

 [FunctionName("EternalWorkOrchestrator")]
 public static async Task Run([OrchestrationTrigger] DurableOrchestrationContext context)
 {
    await context.CallActivityAsync("DoWork", null);

    // sleep for one hour between doing work
    DateTime nextJobStart = context.CurrentUtcDateTime.AddHours(1);
    await context.CreateTimer(nextJobStart, CancellationToken.None);

    context.ContinueAsNew(null);
 }

Upvotes: 2

TomF
TomF

Reputation: 159

More info:

"IDurableClient" is a union of "IDurableEntityClient" and "IDurableOrchastrationClient". It has all the methods of the other two.

Entity Methods:

CleanEntityStorageAsync(Boolean, Boolean, CancellationToken)
ListEntitiesAsync(EntityQuery, CancellationToken)
ReadEntityStateAsync(EntityId, String, String)
SignalEntityAsync(EntityId, DateTime, String, Object, String, String)
SignalEntityAsync(EntityId, String, Object, String, String)
SignalEntityAsync(EntityId, Action)
SignalEntityAsync(EntityId, DateTime, Action)
SignalEntityAsync(String, Action)
SignalEntityAsync(String, DateTime, Action)

Orchestration Methods:

CreateCheckStatusResponse(HttpRequest, String, Boolean)
CreateCheckStatusResponse(HttpRequestMessage, String, Boolean) CreateHttpManagementPayload(String)
GetStatusAsync(String, Boolean, Boolean, Boolean) ListInstancesAsync(OrchestrationStatusQueryCondition, CancellationToken)
PurgeInstanceHistoryAsync(DateTime, Nullable, IEnumerable)
PurgeInstanceHistoryAsync(String)
RaiseEventAsync(String, String, Object)
RaiseEventAsync(String, String, String, Object, String)
RestartAsync(String, Boolean)
StartNewAsync(String, String)
StartNewAsync(String, String, T)
StartNewAsync(String, T)
TerminateAsync(String, String)
WaitForCompletionOrCreateCheckStatusResponseAsync(HttpRequest, String, Nullable, Nullable, Boolean)
WaitForCompletionOrCreateCheckStatusResponseAsync(HttpRequestMessage, String, Nullable, Nullable, Boolean)

https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.webjobs.extensions.durabletask?view=azure-dotnet

Upvotes: 0

Chris Gillum
Chris Gillum

Reputation: 15042

This is general Azure Functions behavior. The reason GET doesn't work is because the function in the sample is only configured to work with POST. See the [HttpTrigger] attribute in the function signature:

[HttpTrigger(AuthorizationLevel.Anonymous, methods: "post", 
        Route = "orchestrators/{functionName}")]

If you want to support GET, then change the methods parameter accordingly:

[HttpTrigger(AuthorizationLevel.Anonymous, methods: "get", 
        Route = "orchestrators/{functionName}")]

Note that Visual Studio seems to have a caching bug where making changes to route information is not properly saved when debugging locally. I opened a GitHub issue to track that here: https://github.com/Azure/Azure-Functions/issues/552

For more information on HTTP triggers, see this documentation: https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook

If you want to trigger a Durable Function using a timer trigger, then just change the trigger type. For example:

[FunctionName("ScheduledStart")]
public static async Task RunScheduled(
    [TimerTrigger("0 0 * * * *")] TimerInfo timerInfo,
    [OrchestrationClient] DurableOrchestrationClient starter,
    TraceWriter log)
{
    string functionName = "E1_HelloSequence";
    string instanceId = await starter.StartNewAsync(functionName, null);
    log.Info($"Started orchestration with ID = '{instanceId}'.");
}

EDIT: If you're using Durable v2.x, then the syntax looks like this:

[FunctionName("ScheduledStart")]
public static async Task RunScheduled(
    [TimerTrigger("0 0 * * * *")] TimerInfo timerInfo,
    [DurableClient] IDurableClient starter,
    ILogger log)
{
    string functionName = "E1_HelloSequence";
    string instanceId = await starter.StartNewAsync(functionName, null);
    log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
}

For more information on Timer triggers, see this documentation: https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-timer

Upvotes: 14

Mikhail Shilkov
Mikhail Shilkov

Reputation: 35134

when I configured different verb like HTTP GET it was responded with NotFound" error in console as well as request made to it with http request from browser responded with "NotFound" error in console .Why this happened?

Because you specified your function to be triggered on POST only:

[HttpTrigger(AuthorizationLevel.Anonymous, methods: "post", 
Route = "orchestrators/{functionName}")] HttpRequestMessage req,

To enable GET, add get to methods parameter.

Can I invoke any Orchestration function with in timer trigger azure function?

You can define timer-triggered function with OrchestrationClient input binding similar to your HTTP function. Sample declaration:

public static async Task Run(
    [TimerTrigger("0 */1 * * * *")] TimerInfo info,
    [OrchestrationClient] DurableOrchestrationClient starter)

Upvotes: 8

Related Questions