Draft
Conversation
2085c56 to
a9cb574
Compare
Codecov Report
@@ Coverage Diff @@
## master #1132 +/- ##
==========================================
+ Coverage 92.61% 92.64% +0.03%
==========================================
Files 242 244 +2
Lines 7701 7847 +146
==========================================
+ Hits 7132 7270 +138
- Misses 569 577 +8
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
4c0a816 to
612cbe3
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds opt-in support for idempotent requests in JsonApiDotNetCore, as defined by IETF.
In a microservices world, where at-least-once delivery is common practice, APIs must be able to handle duplicate requests gracefully. According to the HTTP standard, only POST and PATCH are non-idempotent by nature. Since in JSON:API there is no way to express "multiply the existing value of attribute X by 3", we only need to handle POST.
When a client includes the "Idempotency-Key" HTTP header in a POST Resource (or atomic:operations) request, the server stores the response before sending it back. A subsequent POST Resource request with the same key just returns the recorded response instead of executing the request. In such cases, it sends back the idempotency key too, to inform the client this was a replay.
The mechanism applies to both success and error responses. If the client wants to retry a failed request, it should resend with another key.
The tricky part is handling concurrent requests with the same key. The chosen approach here is to wrap the entire request in a transaction, so that concurrent requests block on trying to insert a record with the same primary key. This varies per database provider and isolation level, so needs more testing.
An even more scalable solution would be to use an expiring lease that is atomically obtained, but then we'd need to know the maximum duration that processing a request can take. This is problematic when non-idempotent downstream external network service calls are made from resource definitions.
References on idempotency:
References on capturing request/response bodies in ASP.NET: