(aka why front-end sucks and backend needs to save the day as always)
READY
- generate uuid
READY
- generate uuid
SUBMIT
- call API
- disable button
- show spinner
READY
- generate uuid
SUBMIT
FAIL
SUCCESS
- call API
- disable button
- show spinner
200
!200
READY
- generate uuid
SUBMIT
FAIL
SUCCESS
- call API
- disable button
- show spinner
- show message
- redirect
- show error
- generate new key
- enable button
READY
- generate uuid
SUBMIT
FAIL
SUCCESS
- call API
- disable button
- show spinner
- show message
- redirect
- show error
- generate new key
- enable button
READY
- generate uuid
SUBMIT
API
- call API
- disable button
- show spinner
REQUEST
REQUEST
REQUEST
API
API
API
API
API
READY
- generate uuid
SUBMIT
API
- call API
- disable button
- show spinner
REQUEST
REQUEST
REQUEST
API
API
API
API
API
Idempotence (UK: /ˌɪdɛmˈpoʊtəns/,[1] US: /ˌaɪdəm-/)[2] is the property of certain operations in mathematics and computer science whereby they can be applied multiple times without changing the result beyond the initial application. The concept of idempotence arises in a number of places in abstract algebra (in particular, in the theory of projectors and closure operators) and functional programming (in which it is connected to the property of referential transparency).
Cleaning dishes is idempotent.
If you have a full sink and clean dishes, you end up with an empty sink.
If you "clean dishes" again, you finish with empty sink again. State of the kitchen has not changed.
Cooking is not idempotent.
If you cook a dinner, you end up with a dinner.
If you "cook a dinner" again, you finish with two dinners and obesity.
def before_request():
...
prevent_duplicate_calls()
------------------------------
def prevent_duplicate_calls():
if request.method not in ['POST', 'PUT', 'PATCH', 'DELETE']:
return
idempotency_key = request.headers.get('x-airsorted-idempotency-key', '').strip()
if not idempotency_key:
return
lock = redis_lock.Lock(
cache_conn,
f'idempotency-{idempotency_key}',
auto_renewal=True
)
if not lock.acquire(blocking=False):
raise ConflictException(
f'Request with idempotency key {idempotency_key} already registered'
)