Tüm yazılar Arka Uç

Çevrimdışı Çalışan Uygulama Yazmak ve Çakışmaları Çözmek

Çevrimdışı desteği "veriyi yerelde tut" demek değil. Asıl zor kısım, iki taraf da aynı kaydı değiştirdiğinde ne olacağına karar vermek.

DT
Demir Taşdemir Mobil Uygulama & Web Geliştirici
— dk okuma

Bir uygulamanın çevrimdışı çalışması, kullanıcı için sihir gibi görünüyor: internet yokken de her şey duruyor, bağlantı gelince kendiliğinden yerine oturuyor. Geliştirici tarafında ise bu, üzerinde en çok düşünülmesi gereken konulardan biri.

Çünkü kolay kısım veriyi yerelde saklamak. Zor kısım şu soru: iki taraf da aynı kaydı değiştirdiyse hangisi kazanacak?

Önce şunu netleştirin: her veri aynı değil

Uygulamadaki her verinin çevrimdışı davranışı aynı olmak zorunda değil. Ben veriyi üçe ayırıyorum:

TürÖrnekÇevrimdışı davranış
Yalnızca kullanıcının Kişisel notlar, ayarlar Tam çevrimdışı yazma. Çakışma neredeyse hiç olmaz.
Paylaşılan Ekip görevleri, ortak liste Çevrimdışı yazma mümkün ama çakışma stratejisi şart.
Sunucunun otoritesinde Stok, bakiye, ödeme Çevrimdışı yazmaya hiç izin vermeyin. Kuyruğa alın, sunucu karar versin.

Bu ayrımı baştan yapmak, sonradan çözülmesi çok zor olan bir sınıf problemi ortadan kaldırıyor. Bakiyeyi çevrimdışı düşürmeye izin verirseniz, kullanıcı uçak modunda parasından fazlasını harcayabiliyor.

Varsayılan strateji: son yazan kazanır

Çoğu araç varsayılan olarak bunu yapıyor: en son gelen yazma işlemi öncekini eziyor. Uygulaması kolay, ama sessizce veri kaybettiriyor. Kullanıcı yazdığı notun kaybolduğunu ancak günler sonra fark ediyor ve neden olduğunu asla anlamıyor.

Cihaz saatine güvenmeyin

"Son yazan" kararını cihazın saatine göre veriyorsanız, saati yanlış ayarlanmış tek bir cihaz tüm senkronizasyonu bozabilir. Zaman damgasını sunucu üretmeli; istemcinin gönderdiği saati kayıt için değil, yalnızca bilgi olarak tutun.

Daha iyisi: alan düzeyinde birleştirme

Çoğu çakışma aslında gerçek bir çakışma değil. Kullanıcı çevrimdışıyken görevin başlığını değiştirdi, siz panelden son tarihini değiştirdiniz. Dokümanın tamamını ezmek yerine yalnızca değişen alanları birleştirmek ikisini de koruyor.

// Tüm dokümanı göndermek yerine sadece değişen alanı gönder
// (Firestore'da update, REST'te PATCH mantığı)
db.collection("gorevler").document(id)
  .update(mapOf("baslik" to yeniBaslik))

Bunu yapabilmek için istemcinin neyin değiştiğini bilmesi gerekiyor. Yani yerel tarafta "bu kaydın şu alanları değişti" bilgisini tutmak, tüm nesneyi göndermekten daha fazla iş ama sonuç çok daha sağlam.

Bekleyen işlemleri kuyrukta tutun

Çevrimdışı yapılan değişiklikleri doğrudan "veri" olarak değil, işlem olarak saklamak işleri kolaylaştırıyor. Bağlantı gelince kuyruk sırayla işleniyor.

// Veriyi değil, niyeti sakla
{ "islem": "gorev_ekle",     "id": "g_918", "veri": { ... }, "zaman": 1723... }
{ "islem": "gorev_guncelle", "id": "g_204", "alanlar": ["baslik"] }
{ "islem": "gorev_sil",      "id": "g_177" }

Bu yapı, "önce ekle sonra sil" gibi sıralı işlemlerin doğru uygulanmasını sağlıyor. Ayrıca başarısız olan tek bir işlemi yeniden denemek, tüm senkronizasyonu baştan çalıştırmaktan çok daha ucuz.

İşlemler tekrarlanabilir olmalı

Ağ kopukluğunda aynı isteğin iki kez gitmesi çok olağan. Sunucu bunu ikinci bir işlem sanırsa aynı kayıt iki kez oluşuyor.

Çözüm, her işleme istemcide üretilmiş benzersiz bir kimlik vermek. Sunucu aynı kimliği ikinci kez gördüğünde işlemi tekrar uygulamıyor, sadece önceki sonucu döndürüyor.

Kullanıcıya durumu gösterin

Çevrimdışı destek, kullanıcıyı bilgilendirmediğiniz sürece güven vermiyor. Basit bir durum göstergesi çok işe yarıyor:

  • Kaydedildi — sunucuya ulaştı.
  • Bekliyor — cihazda duruyor, bağlantı gelince gönderilecek.
  • Gönderilemedi — bir sorun var, kullanıcı tekrar deneyebilir.

Bu göstergeyi koymadığınızda kullanıcı, verinin kaydedilip kaydedilmediğinden emin olamadığı için aynı işlemi tekrar tekrar yapıyor — ve asıl karmaşa o zaman başlıyor.

Gerçek çakışmada kullanıcıya sorun

Otomatik olarak çözülemeyen bir çakışma varsa — iki taraf da aynı alanı farklı şekilde değiştirmişse — sessizce birini seçmek yerine kullanıcıya iki sürümü gösterip seçtirmek en dürüst yol. Nadiren olur, ama olduğunda kullanıcı veri kaybetmemiş olur.

Çevrimdışı desteği, mutlu senaryoda hiç fark edilmeyen ama kötü senaryoda ürünün tamamını kurtaran bir yatırım. Zor kısmı yazmak değil, ne olacağına önceden karar vermek.

  • Çevrimdışı
  • Senkronizasyon
  • Çakışma
  • Mimari
  • Veri modeli
Paylaş: LinkedIn X WhatsApp
DT

Demir Taşdemir

Mobil Uygulama & Web Geliştirici

2018'den beri yazılım geliştiriyorum. App Store ve Google Play'de 11 uygulama yayınladım; şu an 6 mobil uygulama, 1 e-ticaret platformu ve 1 masaüstü oyun üzerinde çalışıyorum.

Zor kısmı atlamayan bir yaklaşım

Mutlu senaryoyu herkes yazar. Ürünü ayakta tutan, kenar durumların düşünülmüş olması.