Kısmi güncellemelerde JSON Merge Patch mı JSON Patch mı kullanmalıyım?
Soru
Laravel tabanlı bir REST API'miz var ve kaynak güncellemeleri `PUT` ile yapılıyor. İstemcinin her seferinde kaynağın tamamını göndermesi gerekiyor; sadece tek bir alanı değiştirmek isteyen mobil uygulama bile bütün objeyi geri yolluyor. Sorun şu: iki kullanıcı aynı profili neredeyse aynı anda düzenlediğinde, ikincinin `PUT`'u birincinin değiştirdiği alanları eski değerleriyle eziyor. Klasik lost update. Kısmi güncellemeye (`PATCH`) geçmeyi düşünüyorum ama JSON Merge Patch mı yoksa JSON Patch mı seçmeliyim, ikisinin farkı pratikte ne oluyor?
Cevap
Kısa cevap
Önce iki işi ayıralım — PATCH biçimini seçmek ayrı, lost update’i çözmek ayrı.
Bağlam
Biçim tarafında çoğu CRUD için JSON Merge Patch yeter; kayıp güncellemeyi ise biçim değil, koşullu istekler (ETag/If-Match) çözer.
Neden
-
JSON Merge Patch (RFC 7396) basit ve durumların çoğunu karşılar. Media type’ı
application/merge-patch+json. Sadece değiştirmek istediğiniz alanları gönderirsiniz, gerisine dokunmazsınız. İnsan tarafından okunması ve üretilmesi kolay; tipik “şu iki alanı güncelle” senaryosu için doğru araç. -
JSON Patch (RFC 6902) güçlü ama pahalı. Bir işlem dizisidir:
add,remove,replace,move,copy,test. Dizinin belirli bir elemanınapathile dokunabilir, hattatestile “şu değer hâlâ buysa uygula” diyebilirsiniz. Karşılığında istemci ve sunucu tarafında üretmesi, doğrulaması ve okunması belirgin biçimde daha zordur. -
Merge Patch’in iki tuzağını bilin. Birincisi:
null“bu alanı sil” demektir, dolayısıyla bir alanı bilinçli olaraknull’a çekmek ile silmek arasında ayrım yapamazsınız. İkincisi: diziler tümüyle değiştirilir, eleman bazlı patch yoktur. Bu iki ihtiyaç gerçekse JSON Patch’e geçmelisiniz.
Ne yapmalı
-
Asıl sorun biçimle değil concurrency kontrolüyle çözülür. PATCH’e geçmek gövdeyi küçültür ama iki eşzamanlı yazmanın çakışmasını engellemez. Bunun için ETag +
If-Matchbaşlığı ya da birversionkolonu kullanın: istemci okuduğu ETag’i geri gönderir, sunucu değişmişse412 Precondition Faileddöner. JSON Patch’intestop’u da aynı işi görebilir ama HTTP katmanında ETag daha temizdir.# Sadece display_name'i güncelle, çakışmayı ETag ile koru curl -X PATCH https://api.example.com/users/42 \ -H "Content-Type: application/merge-patch+json" \ -H 'If-Match: "a1b2c3"' \ -d '{"display_name": "Bora"}' -
Validation’ı kısmi gövdeye göre uyarlayın. Laravel’de
PUTiçin tüm alanlarırequiredsayan kurallar PATCH’te işe yaramaz;sometimesile “gelmişse doğrula” mantığına geçin, yoksa eksik alan hata verir.
Sonuç: Ben olsam varsayılan olarak Merge Patch + ETag/If-Match kurardım — bu ikisi hem gövdeyi küçültür hem lost update’i kökten keser. Diziye eleman bazlı dokunmam ya da atomik koşullu çok-alan işlemlerim gerçekten varsa, sadece o uçlarda JSON Patch’e geçerdim. Biçim seçimini tek başına lost update çözümü sanmayın; PATCH’i seçseniz bile koşullu istek yoksa aynı yarışı yaşarsınız.
Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.