Idempotency key

Idempotency key

(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

x-airsorted-idempotency-key

Idempotence (UK: /ˌɪdɛmˈptəns/,[1] US: /ˌ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.

Let's go through the whole backend code

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'
        )

Frontend

the ball is on your side

Made with Slides.com