This is a bit scrappy, but I've been experimenting...
# http4k
t
This is a bit scrappy, but I've been experimenting with adding an http4k idempotency filter based on the following standard: https://datatracker.ietf.org/doc/draft-ietf-httpapi-idempotency-key-header/ My current sketch is by no means worthy of a PR, and would require significant rework to make it sufficiently flexible, but the attached snippet is what I've got so far. Out of interest, has anyone considered a similar sort of mechanism before? If so, how did you go about implementing it? Would you find this useful in your own projects?
Of course, in practice, the InMemoryIdempotencyKeys implementation is likely to be inadequate. My thinking is that you could implement this in whatever technology of your choosing, most likely whatever it is you're using to persist the entities (Postgres in my case).
d
Redis is probably the typical tech for this really, if you're not going to do it at the storage level. Not sure if keeping the entire response is a good plan - especially with date based headers. If you design your APIs to just return "accepted" or similar then maybe you can get around having to store it. Regardless, the storage would need to be pluggable... The http4k connect storage would be a perfect hit here 😉
Http4k-ops-idempotency!
t
Thanks @dave. I've seen a couple of hints towards Redis, but I'm not sure how that's meant to work when your primary persistence mechanism is some other technology like Postgres. Is it something like: 1. Secure lock in Redis 2. Perform transaction in Postgres 3. Remove lock in Redis If something goes wrong between 2. and 3., the client will retry the request, and hopefully remove the lock in Redis then, without repeating the transaction in Postgres. Out of interest, how have you typically handled idempotency requirements for POST / PATCH requests? Options I've seen / considered: 1. Don't bother, and just risk duplicate handlings of the request 2. Let the client generate the entity ID itself and have the database enforce uniqueness (although this case would better fit a PUT request) 3. Have some route level idempotency mechanism like the one I've described above.
j
Just keeping the same kind of implementation, You could use Header.uuid().required("...id") or a stronger typed values4k uuid type, then you could use a few fewer lines, and your interface could be more strongly typed. ...
👍 1