17

I am developing a Function in Azure with Cancellation Token. Its an Http Trigger.

I pass in a Cancellation Token in in the method parameters.

Its long running function. And I cancel the request in between of the process but the process keeps running and the cancellation token doesn't take its affect.

Is this supported in Azure Functions, that if I cancel a Http Request in between it should also cancel its execution but this is not the case.

I tested this via small piece of code

public static class LongRunningFunction
    {
        [FunctionName("LongRunningFunction")]
        public static async Task<IActionResult> RunAsync(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post",  Route = "Long")]
            HttpRequest req, ILogger log, CancellationToken token)
        {
            try
            {
                await Task.Delay(10000, token);
                return new OkResult();

            }
            catch (OperationCanceledException)
            {
                return new NotFoundResult();
            }
            catch (Exception e)
            {
                return new InternalServerErrorResult();
            }
        }
    }

And I used Postman for the execution.

Am I doing something wrong?

I am taking help from the following Link

Noob Coder
  • 444
  • 1
  • 5
  • 16
  • Could You describe your problem more clealy ??? Why do You think you do something wrong ??? – SkorpEN Feb 13 '20 at 07:21
  • I am using Cancellation token to cancel a task if my Http Trigger request was cancelled in between by a client. But when I do cancel it via my client (Postman) it doesn't get cancelled it keeps on executing – Noob Coder Feb 13 '20 at 07:23
  • Please refer to https://learn.microsoft.com/en-us/archive/blogs/benjaminperkins/how-i-would-handle-a-timeout-in-azure-function. It says that when your function is stopped, the CancellationToken will be triggered. – Jim Xu Feb 13 '20 at 09:20
  • So how can we stop the function when its called by an Http Trigger – Noob Coder Feb 13 '20 at 11:15
  • You can try to set the ```functiontimeout``` in the host.json. Let the function running time is greater than functiontimeout. Once the function is time out, the function will terminate unexpectedly, the CancellationToken will be triggered. Also the document you provide says that it enables the operating system to notify your code when the function is about to be terminated. Customers can use this notification to make sure the function doesn't terminate unexpectedly – Jim Xu Feb 14 '20 at 02:17
  • @JimXu Well my objective to cancel it out on demand. When an http request is canceled by client it should be cancelled on the function side but I guess its not possible – Noob Coder Feb 14 '20 at 08:03
  • Yes. Because once your request is sent to Azure function, the function will be triggered then run. You cancel the request on the client and you just cannot revice the response from function. – Jim Xu Feb 14 '20 at 08:08

3 Answers3

36

I know this is an old question, but I found the answer to this issue.

In Azure Functions, there are 2 cancellation tokens.

The token passed in Function Method parameter is the Host Cancellation Token - cancellation is requested when the host is about to shut down.

The other token is req.HttpContext.RequestAborted property. It's being cancelled when browser cancels the request - this is what you were after.

In addition, you can use following code:

using var cancellationSource = CancellationTokenSource.CreateLinkedTokenSource(hostCancellationToken, req.HttpContext.RequestAborted);

To get a token that cancels when either host or request is being cancelled.

alastairtree
  • 3,960
  • 32
  • 49
Miq
  • 3,931
  • 2
  • 18
  • 32
  • 9
    Whenever creating a linked CancellationTokenSource like this, _always_ dispose of the CTS you create when you're done with it or you create a leak becaues the long-lived token (`hostCancellationToken` in this case) will maintain a strong reference to your per-request token source. – Andrew Arnott Sep 07 '20 at 16:51
1

Without using Durable Functions, I don't think it's possible. Here's a sample using Durable:

[FunctionName("ApprovalWorkflow")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    await context.CallActivityAsync("RequestApproval", null);
    using (var timeoutCts = new CancellationTokenSource())
    {
        DateTime dueTime = context.CurrentUtcDateTime.AddHours(72);
        Task durableTimeout = context.CreateTimer(dueTime, timeoutCts.Token);

        Task<bool> approvalEvent = context.WaitForExternalEvent<bool>("ApprovalEvent");
        if (approvalEvent == await Task.WhenAny(approvalEvent, durableTimeout))
        {
            timeoutCts.Cancel();
            await context.CallActivityAsync("ProcessApproval", approvalEvent.Result);
        }
        else
        {
            await context.CallActivityAsync("Escalate", null);
        }
    }
}

https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-overview?tabs=csharp#human

Thiago Custodio
  • 17,332
  • 6
  • 45
  • 90
1

Heads-up Azure Functions Host release 4.20.0 resolves this issue for both In-Process and Out-Of-Process Azure Functions by tying together the application shutdown signal and the HttpContext.RequestAborted signal into a single CancellationToken (the same one that is already available in the FunctionContext).

You can read more here: https://github.com/Azure/azure-functions-host/pull/9159