Description
Use case
In the current implementation of Idempotency we don't have the InProgressExpiration timestamp. So currently if a lambda invocation expired there would be no way to retry it, when using the Idempotent attribute in the lambda handler or Idempotent attribute on another method
This field is required to prevent against extended failed retries when a Lambda function times out, Powertools for AWS Lambda (.NET) calculates and includes the remaining invocation available time as part of the idempotency record.
If a second invocation happens after this timestamp, and the record is marked as INPROGRESS, we will execute the invocation again as if it was in the EXPIRED state (e.g, expire_seconds field elapsed).
This means that if an invocation expired during execution, it will be quickly executed again on the next retry.
Solution/User Experience
When decorating the handler with Idempotent attribute we will do it automatically by getting the RemainingTime
value from the ILambdaContext that is passed to the handler.
RemainingTime
is the remaining execution time till the function will be terminated. At the time you create the Lambda function you set maximum time limit, at which time AWS Lambda will terminate the function execution.
Information about the remaining time of function execution can be used to specify function behavior when nearing the timeout.
When using Idempotent attribute on another method to guard isolated parts of your code, you must use RegisterLambdaContext
available in the Idempotency
static class to benefit from this protection.
Here is an example on how you register the Lambda context in your handler:
public class Function
{
public Function()
{
Idempotency.Configure(builder => builder.UseDynamoDb("idempotency_table"));
}
public Task<string> FunctionHandler(string input, ILambdaContext context)
{
Idempotency.RegisterLambdaContext(context);
MyInternalMethod("hello", "world")
return Task.FromResult(input.ToUpper());
}
[Idempotent]
private string MyInternalMethod(string argOne, [IdempotencyKey] string argTwo) {
return "something";
}
}
Lambda request timeout diagram
sequenceDiagram
participant Client
participant Lambda
participant Persistence Layer
alt initial request
Client->>Lambda: Invoke (event)
Lambda->>Persistence Layer: Get or set idempotency_key=hash(payload)
activate Persistence Layer
Note over Lambda,Persistence Layer: Set record status to INPROGRESS. <br> Prevents concurrent invocations <br> with the same payload
Lambda-->>Lambda: Call your function
Note right of Lambda: Time out
Lambda--xLambda: Time out error
Lambda-->>Client: Return error response
deactivate Persistence Layer
else retry after Lambda timeout elapses
Client->>Lambda: Invoke (event)
Lambda->>Persistence Layer: Get or set idempotency_key=hash(payload)
activate Persistence Layer
Note over Lambda,Persistence Layer: Set record status to INPROGRESS. <br> Reset in_progress_expiry attribute
Lambda-->>Lambda: Call your function
Lambda->>Persistence Layer: Update record with result
deactivate Persistence Layer
Persistence Layer-->>Persistence Layer: Update record
Lambda-->>Client: Response sent to client
end
Alternative solutions
No response
Acknowledgment
- This feature request meets Powertools for AWS Lambda (.NET) Tenets
- Should this be considered in other Powertools for AWS Lambda languages? i.e. Python, Java, and TypeScript
Metadata
Metadata
Assignees
Type
Projects
Status