Idempotentność

Właściwość operacji, której wielokrotne wykonanie daje ten sam efekt co jednokrotne. Kluczowa dla niezawodności narzędzi IaC i automatyzacji.

Idempotentność (ang. idempotence) to właściwość operacji, dla której wykonanie jej raz daje dokładnie ten sam efekt końcowy co wykonanie jej pięć, dziesięć czy sto razy. Liczy się stan, w jakim zostawiasz system, a nie liczba prób. Jeśli operacja jest idempotentna, możesz ją bezpiecznie powtórzyć po awarii, timeoutcie albo nerwowym kliknięciu „uruchom ponownie” i nic złego się nie stanie — system po prostu utrzyma docelowy stan.

Jak to działa i do czego się przydaje

Kluczem jest myślenie w kategoriach stanu docelowego, a nie listy kroków. Operacja nieidempotentna mówi „dodaj 1 do licznika” — każde wywołanie zmienia wynik. Operacja idempotentna mówi „licznik ma mieć wartość 5″ albo „ten plik ma istnieć z taką treścią”. Jeśli warunek jest już spełniony, narzędzie nic nie robi; jeśli nie — doprowadza do niego. Dzięki temu nie musisz pamiętać, czy poprzednie uruchomienie się udało.

To fundament niezawodnej automatyzacji i narzędzi IaC (Infrastructure as Code). W rozproszonych systemach pakiety giną, połączenia się zrywają, a klienci ponawiają żądania. Bez idempotentności każdy retry groziłby podwójnym obciążeniem karty albo zdublowanym rekordem w bazie.

Przykład z praktyki

Najczystszy przykład to Ansible. Gdy uruchamiasz ansible-playbook site.yml, moduł najpierw sprawdza stan, a dopiero potem działa. Załóżmy taki task:

  • ansible -m apt -a "name=nginx state=present"

Pierwszy przebieg zgłosi changed i zainstaluje nginx. Każdy kolejny — przy niezmienionym stanie — zwróci ok i nie ruszy nic. Stąd słynne hasło „dążymy do zera w kolumnie changed”. Tak samo działa terraform apply: porównuje stan rzeczywisty z deklaracją i wprowadza tylko różnicę.

To samo pojęcie żyje w HTTP. Metody GET, PUT i DELETE są z definicji idempotentne, a POST — nie. Dlatego płatności często zabezpiecza się nagłówkiem Idempotency-Key: powtórzone żądanie z tym samym kluczem nie obciąży klienta drugi raz.

Na co uważać

Najczęstszy mit: „skrypt w Bashu jest idempotentny, bo go napisałem”. Nie jest — dopóki sam nie sprawdzisz warunku. mkdir katalog wywali się przy drugim uruchomieniu, ale mkdir -p katalog już nie. Druga pułapka to mylenie idempotentności z bezpieczeństwem (safe methods) — DELETE jest idempotentny, ale na pewno nie „bezpieczny”, bo zmienia stan. I uwaga na moduł shell/command w Ansible: te nie znają pojęcia stanu, więc idempotentność musisz wymusić ręcznie przez creates albo changed_when.

Pojęcia powiązane: Infrastructure as Code, deklaratywność, stan docelowy (desired state), retry/ponawianie żądań, metody HTTP, Idempotency-Key, atomowość operacji.