aws / aws/aws-dotnet-messaging
Allow passing a CancellationToken to ILambdaMessaging.ProcessLambdaEventAsync / ProcessLambdaEventWithBatchResponseAsync
- Dominant language
- C#
- Stars
- 143
- Forks
- 27
- Avg merge
- 1d 18h
- Merged PRs (30d)
- 4
Description
### Describe the feature
Add an optional `CancellationToken` parameter to `ILambdaMessaging.ProcessLambdaEventAsync` and `ILambdaMessaging.ProcessLambdaEventWithBatchResponseAsync`, and thread it through to the internal processing pipeline (`ILambdaMessageProcessor.ProcessMessagesAsync(CancellationToken)` already accepts one) so it reaches each `IMessageHandler.HandleAsync(MessageEnvelope, CancellationToken)` call. Today there is no way for a caller to influence cancellation of an in-flight `ProcessLambdaEventWithBatchResponseAsync` call at all.
### Use Case
We have a dotnet SQS-triggered Lambda (the "generic handler" style - `Amazon.Lambda.RuntimeSupport` invoking an `assembly::type::method` handler, not the ASP.NET Core Lambda integration) where a handler occasionally runs long enough to hit the function's hard timeout. When that happens, the execution environment is torn down mid-flight with zero opportunity for our own code to react: we never get a chance to flush our OpenTelemetry trace exporter, so the slow invocation just disappears from tracing with no signal that it ever happened, which makes it very hard to even detect, let alone diagnose.
We want to race `ProcessLambdaEventWithBatchResponseAsync` against a timer derived from `ILambdaContext.RemainingTime` minus a safety buffer, and when that timer fires, log and force-flush telemetry while there's still time left before the runtime kills the process - and ideally give our `IMessageHandler`s a chance to cooperatively wind down too. There's currently no way to plumb a token in to make that possible.
### Proposed Solution
- Add `CancellationToken token = default` to both `ILambdaMessaging.ProcessLambdaEventAsync` and `ProcessLambdaEventWithBatchResponseAsync`. Defaulting to `CancellationToken.None` keeps this non-breaking.
- Link that token into the `CancellationTokenSource` that `DefaultLambdaMessaging` already creates internally, instead of only ever creating a bare, unlinked one.
- This alone is enough for consumers to build the `ILambdaContext.RemainingTime`-minus-buffer pattern themselves (`CancellationTokenSource` + `CancelAfter`, passed in) with no other framework changes needed.
- Optional stretch: since `DefaultLambdaMessaging` already receives `ILambdaContext` on every call, the framework could offer to derive this automatically - e.g. a `LambdaMessagingOptions.GracefulShutdownBuffer` that auto-cancels the internal token when `RemainingTime` drops below the configured buffer, for callers who don't want to hand-roll it.
### Other Information
- Verified by decompiling `AWS.Messaging.Lambda` 1.0.3 (current latest on NuGet): `DefaultLambdaMessaging.ProcessLambdaEventWithBatchResponseAsync` creates `CancellationTokenSource cts = new CancellationTokenSource();` with no timeout attached, passes `cts.Token` down into `ProcessMessagesAsync`, and only calls `cts.Cancel()` in a `finally` block *after* that call has already completed - so it currently provides no early-warning mechanism to in-flight handlers.
- Confirmed there's no equivalent facility in the base `Amazon.Lambda.RuntimeSupport` "generic handler" invocation path either - automatic `RemainingTime`-derived cancellation is only wired up for the ASP.NET Core Lambda hosting integration. So today this has nowhere to live except fully hand-rolled in every consumer's code.
- Related to, but distinct from, #150 (visibility-timeout reset on handler failure) - both are about giving callers more control over in-flight SQS processing under `ILambdaMessaging`.
### Acknowledgements
- [x] I may be able to implement this feature request
- [ ] This feature might incur a breaking change
### AWS.Messaging (or related) package versions
AWS.Messaging 1.3.0, AWS.Messaging.Lambda 1.0.3
### Targeted .NET Platform
.NET 10
### Operating System and version
AmazonLinux/Lambda (ARM64)
Contributor guide
Research direction
Start at ILambdaMessaging.ProcessLambdaEventAsync and ProcessLambdaEventWithBatchResponseAsync, then trace DefaultLambdaMessaging into ILambdaMessageProcessor.ProcessMessagesAsync and IMessageHandler.HandleAsync. Confirm how the existing internal CancellationTokenSource is created and passed. Done means both public methods accept an optional token, it reaches message handlers, and the existing default behavior remains unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, csharp
- Domain
- backend, cloud
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100