-
Notifications
You must be signed in to change notification settings - Fork 28
Idempotency issue in Azure Functions UpdateCounts function #224
Description
Description:
In the provided Azure Functions code for the UpdateCounts function in ServerlessLibrary/ServerlessLibraryFunctionApp/UpdateCounts.cs, there is an idempotency problem that may cause incorrect counts in the storage table for likes, dislikes, and downloads. If a failure occurs after updating the counts but before the function completes, subsequent retries may result in duplicate updates to the counts.
Steps to Reproduce:
- Deploy the Azure Function with proper environment configurations.
- Simulate a failure after updating the counts in the storage table but before the function completes. This can be done by introducing a breakpoint or throwing an exception.
- Trigger the function execution by adding a message to the "slitemstats" queue.
- Let the function automatically retry with the same message (this time the failure is optional)
Expected Behavior:
The UpdateCounts function should update the counts in the storage table without causing duplicates or unexpected behavior when retried. That is, each update message should only lead to one corresponding update.
Actual Behavior:
The function may cause duplicate updates to the counts or other unexpected behavior when retried after a failure between updating the counts and the function completion.
Suggested fix:
Introduce idempotency checks in the UpdateCounts function to ensure that updates to the counts are made only once for each unique message. We can do so by maintaining a LastRequestId field in each table entry and blob entry, which stores the invocation id of the last UpdateCounts function call. The invocation id is constant across Azure Function retries. Before updating a table/blob entry, if the comparison finds item.LastRequestId == FunctionContext.InvocationId, so no redundant action is required. Otherwise, if item.LastRequestId != FunctionContext.InvocationId, update the prevalence counter and the LastRequestId field with FunctionContext.InvocationId.
Thank you for your contribution to the Github community and I really appreciate your effort in following through this issue.