Bugün, REST API Maturity Levels’i incelerken Level 2’de karşıma çıkan ‘Idempotency’ kavramı hakkında öğrendiklerimi yazıya dökmek istiyorum. Bu yazıyı sohbet havasında yazmak istiyorum, çünkü böyle daha rahat hissediyorum ve daha anlaşılabilir olduğunu düşünüyorum :)

 

Idempotency Nedir?

Idempotency kelimesinin kökeni aslında matematikten geliyor. Latince “idem” kelimesi “aynı” anlamına gelirken, “potent” ise “etkili” anlamına geliyor, ikisini birleştirince de “aynı etkiye sahip” anlamı çıkıyor.

Matematikte de, bir işlem yada fonksiyon tekrar tekrar uygulandığında sonuç değişmiyorsa, idempotent deniyor.

Idempotency isim haliyken idempotent sıfat hali, o yüzden yazıda kullanım şekilleri değişebilir.

Örnek:

  • f(x)=∣x∣ fonksiyonu bir idempotenttir, çünkü bir kez ya da defalarca uygulandığında sonuç değişmez.
  • f(x)=x+1 ise idempotent değildir; her uygulamada sonuç değişir.

Yazılımda ve REST API Tasarımında Idempotency’nin Yeri

 

REST API’ler, HTTP protokolü üzerinde çalışır. Temel olarak GET, POST, PUT, PATCH, DELETE, HEAD gibi HTTP metodları kullanılarak çeşitli işlemler gerçekleştirilir. Her metodun kendine özgü bir amacı ve sistem üzerinde yarattığı etkisi vardır.

Idempotency, bu HTTP metodlarının nasıl davranması gerektiğini anlamak ve API tasarımının doğru kurgulanması için önemlidir.

Bu sebeple HTTP metodlarının idempotency açısından değerlendirelim:

GET

Sunucudan veri almak için kullanılır. Aynı GET isteğini bir yada binlerce kez uygulasak da sonuç aynı olacak, veri değişmeyecektir(işlemler sırasında verinin değiştirilmediğini farzedersek). Bu nedenle GET metodları idempotenttir.

POST

Yeni bir kaynak oluşturmak veya bir işlem başlatmak için kullanılır(Instagrama fotoğraf atmak ve bir alışverişi onaylamak gibi). Aynı POST isteğini tekrar tekrar gönderdiğinizde, her seferinde yeni bir kaynak yaratılabilir ya da işlem tekrar yapılabilir. Bu yüzden POST genellikle idempotent değildir. Ancak “idempotency key” gibi yöntemlerle bu durum yönetilebilir.

PUT

Belirli bir kaynağı tamamen güncellemek ya da yoksa oluşturmak için kullanılır. Aynı PUT isteği kaç kere yapılırsa yapılsın, sonuç hep aynı olur; kaynak her zaman aynı veriye sahip olur. Bu nedenle PUT idempotenttir.

PATCH

Kaynağın belirli kısımlarını kısmi olarak güncellemek için kullanılır. Genellikle idempotent değildir çünkü her çağrıda farklı veya kümülatif değişiklikler yapılabilir. Fakat dikkatli tasarlanırsa idempotent olması da mümkün olabilir.

Örneğin bir patch işlemi ile bir çalışan maaşı %20 arttırılabilir, ard arda 2 güncelleme işlemi ile çalışanınızın maaşını %44 arttırmış olursunuz.

DELETE

Belirli bir kaynağı silmek için kullanılır. Kaynak silindikten sonra aynı DELETE isteği tekrar edilse bile, kaynak zaten yoktur ve sistem durumu değişmez. Bu nedenle DELETE idempotenttir.

Not: Eğer endpoint şu şekildeyse :

VERB : Delete

URI : kayas.dev/posts/last

DELETE metodu non-idempotent olarak davranabilir.

HTTP Metodlarının Idempotency Durumu Uygulamamızı Nasıl Etkiler?

Idempotency, yazılımımızın davranışını, hata yönetimini, dolayısıyla kullanıcı deneyimini doğrudan etkiler. Şimdi bunu somut örneklerle açıklayalım:

1. Ağ Problemleri ve Tekrarlanan İstekler

Örneğin bir e-ticaret sitesinde kullanıcı sipariş veriyor ve POST metodu kullanılıyor. Kullanıcı ödeme butonuna bastığında, bağlantı kopuyor ve sunucudan yanıt alamıyor. Kullanıcı işlemin başarısız olduğunu düşünüp siparişi tekrar gönderiyor.

Eğer POST isteği idempotent değilse, kullanıcı aynı üründen birden fazla sipariş vermiş olur — Empati kurunca yeterince sinir bozucu :)

Idempotency key kullanılırsa, sistem aynı isteği tekrar aldığında sadece ilkini işleyip diğerlerine önceki cevabı döner. Böylece siparişlerin tekrar edilmesi engellenmiş olur.

2. Kullanıcı Deneyimi

Bir banka uygulamasında kullanıcı para transferi yapıyor, ancak bağlantı kopuyor ve yanıt alınamıyor. Kullanıcı tekrar “Gönder” butonuna basarsa ve idempotency uygulanmamışsa, parası iki kez çekilebilir.

Idempotency key sayesinde, aynı isteğin tekrarları algılanır ve işlem yalnızca bir kez gerçekleştirilir. Kullanıcı güvenli ve sorunsuz bir deneyim yaşar.

3. Veri Tutarlılığı ve Güvenlik

Kullanıcı profilini güncellerken PUT metodunu kullanıyorsunuz. Aynı güncellemeyi birkaç kez göndermek, idempotent olduğu için veri tutarsızlığı yaratmaz.

PATCH gibi kısmi güncellemelerde ise idempotency sağlanmazsa, tekrar eden istekler veri tutarsızlığına yol açabilir.

4. Performans ve Ölçeklenebilirlik

Örneğin otel rezervasyon sisteminde, müşteriler aynı odayı kontrol etmek için sık sık GET isteği gönderiyor. GET istekleri idempotent olduğu için sistem bu talepleri önbelleğe alabilir ve hızlıca yanıt verebilir.

Ancak rezervasyon için gönderilen POST istekleri tekrar edilirse ve idempotency yoksa, aynı oda birden fazla kişiye rezerve edilebilir. Bu da hem müşteri hem işletme için sorun yaratır.

Peki bu Non-Idempotent Metodlara Karşı Alınabilecek Önlemler Var Mı?

Evet, var. Özellikle POST gibi idempotent olmayan metodlarda tekrar eden isteklerin yol açabileceği sorunları önlemek için idempotency key kullanılır. Bu key ile Post metodlarına idempotentlik katılır diyebiliriz

Idempotency Key ile Çözüm

Neden İhtiyaç Var?

Non-idempotent metodların temel problemi, aynı isteğin birden fazla kez gönderilmesi ve işlemin birden çok kez yapılmasıdır.

Örnek durumlar:

  • Kullanıcının ödeme butonuna art arda basması
  • Ağ problemleri nedeniyle isteklerin tekrar edilmesi
  • Mobil uygulamalarda arka arkaya tetiklenen istekler

Bunlar; çift ödeme, yinelenmiş siparişler veya tekrar tekrar oluşturulan veriler gibi sorunlara yol açabilir.

Çözüm Ne?

Ardışık gelen isteklerden sadece bir tanesini işleme alıp diğerlerine ilk cevabı dönmek.

Yani sistem şunu bilmeli:
 “Bu işlemi zaten yaptım, tekrar etmeye gerek yok.”

Bunu da idempotency key ile sağlarız.

Idempotency Key Nasıl Çalışır?

  1. İstemci Tarafı — Key Üretimi:
     Sayfa açıldığında ya da işlem başlamadan önce, istemci benzersiz bir idempotency key üretir. Bu genellikle GUID formatında olur. (sayfa içinde script ile random guid üretip form içindeki idempotency key değişkenine atanarak yapılabilir.)
  2. İstekle Birlikte Gönderim:
     Kullanıcı işlemi tetiklediğinde, bu benzersiz anahtar HTTP header veya form verisi olarak sunucuya gönderilir.
  3. Sunucu Tarafı — Key Kontrolü:
     Sunucu, bu key ile daha önce işlem yapılıp yapılmadığını cache veya veritabanında kontrol eder.
  4. Eğer işlem yapılmamışsa, isteği işler ve sonucu key ile beraber saklar. Eğer işlem daha önce yapılmışsa, işlemi tekrar etmez, önceki sonucu döner.

 

Gerçek Hayattan Örnek: Ödeme Sistemi

Kullanıcı kart bilgilerini girip “Öde” butonuna basıyor. Bağlantı yavaş ve yanıt gecikiyor. Kullanıcı birkaç kez daha aynı butona basıyor.

Eğer idempotency key yoksa, kullanıcıdan birden fazla ödeme alınabilir.

Ama idempotency key varsa, sunucu ilk isteği işler, sonraki tekrarları görmezden gelir ve aynı sonucu döner.

Ödeme Sisteminden örnek vermişken Uber Eats India’nın yaşadığı Idempotency kaynaklı olduğu tahmin edilen bir bug haberini okudum, haberin özeti şu şekilde:

  • Paytm bir ödeme hizmet sağlayıcısı, Uber Eats India’da bu ödeme sağlayıcısı ile çalışıyor.
  • Paytm’in ödeme API’si önce tek tip bir hata mesajı döndürüyordu.
  • Sonra yapılan bir güncellemeyle, özellikle ikinci başarısız denemede farklı bir hata mesajı eklediler.
  • Ancak bu değişiklik API kullanıcılarına (örneğin Uber Eats gibi firmalara) düzgün şekilde duyurulmadı.
  • Uber Eats’in sistemi sadece eski hata mesajlarını bekliyordu ve yeni hata mesajını doğru şekilde işlemedi.
  • Bu yüzden bazı durumlarda başarısız işlemler “başarılı” gibi algılandı ve siparişler tekrar tekrar işlendi.

Şu videoda bahsediliyor: 

 

 

Sonuç

Idempotency, tekrarlanan isteklerden doğabilecek hataları önler, veri tutarlılığını sağlar ve performans iyileştirmelerine olanak verir, dolayısıyla kullanıcı memnuniyetini de doğrudan etkiler.

Bu yazımda Idempotency ile ilgili öğrendiklerimi yazıya dökmeye çalıştım. Yazımda hatalar olabilir, mazur görünüz :)

İyi okumalar dilerim.

 

Referans aldığım kaynaklar:

https://stackoverflow.com/questions/45016234/what-is-idempotency-in-http-methods