-
Notifications
You must be signed in to change notification settings - Fork 442
Out of proc Support for Cancellation Tokens
In C# functions you can take a CancellationToken argument to allow your function to detect that a host shutdown is occurring and abort gracefully. This work item tracks providing an equivalent mechanism for languages that execute out-of-proc.
Important Note: This is not a new feature. As mentioned, the host already exposes cancellation tokens for in-proc C# function applications. We will be providing the ability for users to react to a cancellation signal. For example, users can bind to a cancellation token which is provided by the host, and observe the token. If a cancellation is signalled, users can react by implementing logic to handle a cancellation scenario.
- Expose the existing cancellation feature to out-of-proc language workers, enabling them to handle a cancellation signal from the host
- Cancellation design for each individual language worker
- We will not be implementing a new feature for cancellations
This is a benefit to end-users as it will give them the ability to handle cancellations per invocation. Users would be able to cancel downstream calls to other APIs, and cleanup resources. It may be more efficient for users to handle termination, rather than having an abrupt termination of operations.
For in-proc C# application, we currently signal CancellationTokens for timeout scenarios. This enables users to clean up resources and operations when the function has timed out, allowing them to avoid an abrupt end.
Sometimes an issue can occur where we'll end up running two copies of a timer trigger at once. If we detect that, we'll cancel one of them but for that to play nicely with user code, it requires the cancellation token pattern. By enabling cancellation tokens here, users can avoid potential duplications downstream.
Users sometimes write code that tries to avoid duplicates in the case of retries for messaging triggers. For example, lets say an EventHub triggered function is running and it loses the lease on the partition. This means another worker is going to run the same function execution using the same data. The cancellation token gets fired if there is one, and the user can react to that by aborting the step they are doing, which might involve updating a database or writing another message somewhere.
This is out-of-scope for this work item as it requires a new feature to be scoped out. The goal of this work item is to expose an existing feature to out-of-proc language workers, there should be nothing new.
Durable users want the ability to cancel in-flight Activity invocations when its parent orchestration is cancelled. This would require each language to have some way that the user can write code that checks for cancellation, which in turn requires some host support.
This issue appears to propose that the Durable Functions (DF) Extension fire a cancellation token to the Function host to signal cancellation of an in-flight Activity function.
- Azure Functions out-of-proc language owners
- We will need to work with language owners to define the cancellation contract between the host and out-of-proc workers
-
Extend the gRPC contract to include an operation that the host can call on a worker to indicate that a given execution is cancelled.
-
Each language worker would then figure out how to map that to the user code.
For example, in .NET isolated it would mean that the isolated worker calls
Cancel
on theCancellationTokenSource
instance for the associated invocation. In Javascript, it might be something like a property on the context object that user code can check e.g.if (context.isExecutionCancelled)
This feature will be built behind a worker capability flag. If a worker does not
have a cancellation capability, we will not send the InvocationCancel
message.
Prior to invoking a Function, the host would subscribe to a CancellationToken and
associate it to the invocation result. First we would need to request the cancellation
token (CT) be passed in the context parameters from WebJobs. We can then flow the CT to
the InvokeAsync
method and eventually to SendInvocationRequest
.
// WorkerFunctionDescriptorProvider.cs
// GetFunctionParametersAsync() - Add the cancellation token from WebJobs to the invocation parameters
parameters.Add(new ParameterDescriptor(ScriptConstants.SystemCancellationTokenParameterName, typeof(CancellationToken)));
// WorkerFunctionInvoker.cs
// InvokeCore() - Update the invocation context to pass through the cancellation token
CancellationToken = (CancellationToken)parameters[cancellationTokenParameterIndex],
Within SendInvocationRequest
, we can register a callback for the CT that we can
use to send the InvocationCancel
message. We will also need to unregister the
callback if we get an InvocationResponse
from the worker.
// GrpcWorkerChannel.cs
// SendInvocationRequest()
context.CancellationToken.Register(() => SendInvocationCancel(invocationRequest.InvocationId));
// SendInvocationCancel()
- Check if the worker has the `HandlesInvocationCancelMessage` capability
- Send a `InvocationCancel` message with the InvocationId
For workers to enable this feature, they will need to:
- Provide the
HandlesInvocationCancelMessage
capability in the WorkerInitResponse message - Implement a handler for the
InvocationCancel
proto message- It is up to workers how they handle the cancellation message
The current protobuf has a definition for InvocationCancel
message that we can use and
potentially extend. The idea is that the host sends a cancel message to attempt to cancel
an invocation. If an invocation is cancelled, the host will receive an invocation response
with status cancelled.
StatusResult
already supports a "cancelled" state.
// Host requests worker to cancel invocation
message InvocationCancel {
// Unique id for invocation
string invocation_id = 2;
// We will not use this property as we cannot reliability provide a grace period
// As removing this may be a breaking change, we can set it to always be a negative
// value (i.e. `-1`) to indicate infinite/ not applicable
google.protobuf.Duration grace_period = 1;
}
- Configuration Settings
- function.json
- host.json
- host.json (v2)
- Http Functions
- Function Runtime Versioning
- Official Functions developers guide
- Host Health Monitor
- Managing Connections
- Renaming a Function
- Retrieving information about the currently running function
- Site Extension Resolution
- Linux Consumption Regions
- Using LinuxFxVersion for Linux Function apps
- Out-of-proc Cancellation Tokens
- Assembly Resolution in Azure Functions
- ILogger
- Precompiled functions
- Official Functions C# developer reference
- Contributor Onboarding
- Development Process
- Deploying the Functions runtime as a private site extension
- Authoring & Testing Language Extensions
- Bindings in out-of-proc
- Language Extensibility
- Worker Capabilities
- Investigating and reporting issues with timer triggered functions not firing
- Sharing Your Function App name privately
- Azure Functions CLI release notes [moved here]
- Function App Zipped Deployment [deprecated]