3 puan yazan GN⁺ 5 시간 전 | Henüz yorum yok. | WhatsApp'ta paylaş
  • Daha birkaç yıl öncesine kadar gerçek zamanlı çok oyunculu veri senkronizasyonu, uzman insan gücü ve şirket düzeyinde yatırım gerektiren en zor problemlerden biriydi; artık ise tek bir npm install ile hobi projelerinde bile çok oyunculu UI uygulanabiliyor
  • Automerge, local-first, çok oyunculu kullanımda güvenli ve sürüm kontrollü veri modelleri kurmak için bir araç; React’in useState desenine benzer şekilde veri kalıcılığı, geçmiş yönetimi, işbirlikçilere yayın, çakışma çözümü gibi işleri UI’nin dert etmesine gerek kalmadan otomatik olarak ele alıyor
  • Tarayıcı tabanlı çok oyunculu ses editörü Ducking örneğinde, veri modelini CRDT işlemlerine doğal biçimde eşlenecek şekilde tasarlamak kritik
  • Liste yeniden sıralama gibi Automerge’in garanti etmediği durumlarda, uygulama katmanı koduyla daha güçlü değişmezler doğrudan uygulanıyor
  • Eskiden endüstriyel ölçekte sihir gibi görünen gerçek zamanlı işbirlikli düzenleme, artık az sayıda kullanıcıya yönelik küçük uygulamalara da özgürce uygulanabiliyor olması asıl anlamı taşıyor

Arka plan — Ducking projesi

  • Son birkaç ayda partnerinin podcast’i için tarayıcı tabanlı çok oyunculu bir ses editörü olan Ducking’i geliştirdi
  • Ses düzenlemenin hâlâ 20 yıllık tek kullanıcılı masaüstü uygulamaları ve dosya alışverişi yöntemine sıkışmış olması garip geliyordu
    • Biri klipleri düzenlerken diğerinin transkripti düzeltmesi ya da EQ ayarlarını değiştirmesi gibi, Google Docs veya Figma benzeri işbirlikli iş akışları gerekliydi
    • Yorumlar, geçmiş, değişiklik takibi gibi modern işbirliği araçları da isteniyordu
  • Önceki yazıda ele alınan özgün UI tasarımı ve ses yerleşim modeli, tek editörü daha etkili hale getirmişti; ancak asıl istenen şey daha işbirlikçi bir iş akışıydı

Automerge nasıl çalışıyor

  • Ses blob’ları hariç Ducking’deki tüm veriler Automerge belgeleri içinde tutuluyor
  • Temel desen, React geliştiricilerine tanıdık bir yapıda: veriyi hook ile alıp render ediyorsunuz, asenkron değişiklik isteği gönderiyorsunuz ve veri değiştiğinde hook yeniden render tetikliyor
    • useDocument hook kullanım örneği: const [doc, changeDoc] = useDocument<Episode>(docUrl) ile belge alınır, giriş değeri değiştiğinde changeDoc((d) => { d.title = e.target.value }) ile güncellenir
  • Veri güncelleme işlemleri emir kipinde yazılmış gibi görünür ama normal JS nesne ve dizilerinden farklıdır
    • Daha az metoda sahiptir, anında mutate etmez ve yapılan değişiklikleri yakalayıp belge geçmişindeki changelist girdilerine dönüştürür
  • Automerge basit kullanım senaryolarında gerekeni yapar ama sihirli değildir; değişmezleri her zaman sizin istediğiniz anlamla birebir örtüşmez, bu yüzden veri modelini dikkatle tasarlamak önemlidir
    • Kullanıcının anlamlı eylemlerinin çoğunu Automerge’in sağladığı tekil işlemlere karşılık gelecek şekilde kurmak gerekir
    • İlişkili veriler üzerindeki ayrı kullanıcı eylemleri, ilgili Automerge işlemlerinin değişmezleri açısından doğal biçimde çözülebilmelidir
    • Saklanan kanonik veri ile hesaplama sonucu elde edilen türetilmiş veriyi net biçimde ayırmak gerekir

Çok oyunculu kullanım için veri modelleme

  • Ducking veri modelinde clip (klip), değiştirilemeyen temel ses kaynağının bir bölümünü oynatan bir pencere görevi görür; oynatma aralığını, efekt uygulamasını ve zaman çizelgesindeki kapladığı alanı belirler
    • En yaygın efekt, klibin temel sesin ses seviyesini zaman içinde değiştirerek crossfade yapması veya gürültüyü azaltmasıdır
  • Başlangıçta her klip, klip başlangıcına göre zaman indekslenmiş ses seviyesi listesini taşıyordu; ama ses değişikliklerinin çoğu klibe değil temel sese aitti ve bu sorun yaratıyordu
    • Klip başlangıç zamanı biraz öne çekildiğinde tüm ses seviyesi değişiklikleri sesin başka bir bölümüne uygulanmış oluyordu
    • Klip başlangıcı değiştiğinde tüm ses seviyesi zaman damgalarını güncelleyen kod yazmak kötü bir tercihti
  • İki işbirlikçi aynı anda klibin başlangıç zamanını düzenlerse, her düzenleme başlangıç zamanı ile tüm ses otomasyonu zaman damgalarını birlikte değiştiriyordu
    • Automerge bu değişiklikler arasındaki nedensel ilişkiyi (causal relationship) bilemediği için, birleştirme sırasında karmakarışık sonuçlar üretebiliyordu
    • Bu, tek bir anlamlı eylemin CRDT’nin anlayamadığı nedensel bir yapıyla birden fazla kalıcı veriyi güncellemeye çalıştığı tipik bir problemdir
  • Çözüm, ses efekt verisini klipten alıp temel sesin zaman çerçevesine göre taşımak oldu
    • Böylece klip başlangıcı veya uzunluğu değiştiğinde güncelleme gerekmiyor; birden çok editör başlangıç zamanı, ses otomasyonu ve diğer efektleri değiştirse bile bunlar birbirinden bağımsız kalıyor ve doğru birleştirilme olasılığı artıyor
  • Tek kullanıcılı UI ile çok oyunculu UI arasındaki fark
    • Tek kullanıcılı UI’de mevcut veri modeli korunup yazma anında ek hesaplama ile iş yürütülebilir
    • Çok oyunculu UI’de ise tüm kalıcı veriyi ortogonal durumda tutmak için veri modeli göçleri çok daha yaygındır
  • Bu yaklaşım, yazma anını basitleştirip okuma anındaki hesaplamayı tercih ederek Automerge’in otomatik birleştirme yeteneğinden en yüksek verimi almayı sağlar
  • Veri biçimi göçüyle ilgili tavsiyeler
    • Build sürecinde veri biçimini dönüştürmek zorunda kalacağınızı kabul edin ve ilk büyük göçten korkmamak için baştan buna zaman ayırıp pratik yapın
    • İstemcide okuma anında işleme, sunucuda toplu yükseltme gibi farklı desenler vardır
    • Göç öncesi ve sonrası durumun aynı olduğunu doğrulayacak kullanışlı değişmezler bulursanız iş çok kolaylaşır
    • Ducking’de tüm projelerin sesi göç öncesi ve sonrası dışa aktarılıp ses parmak izi (audio fingerprint) ile fark olup olmadığı kontrol edilerek büyük şema değişiklikleri bile güvenle dağıtıldı

Liste yeniden sıralamayı uygulamak

  • Bazen Automerge’in sağlamadığı garantiler için uygulama katmanında daha güçlü değişmezleri kendiniz yazmanız gerekir
  • Ducking’in magnetic timeline’ını (çalınacak kliplerin sıralı listesi) uygularken bir sorun çıktı
    • Automerge, dizi üzerinde indeksle öğe silme ve ekleme işlemleri sunuyor; ancak mevcut öğeyi atomik olarak yeniden sıralama (atomic re-order) işlemi sunmuyor
  • Bilinen çözümler var
    • Martin Kleppmann atomik liste yeniden sıralama işlemi üzerine bir makale yayımladı
    • Liangrun Da ile birlikte "Extending JSON CRDTs with Move Operations" makalesi de yayımlandı
    • Bunu Automerge’e ekleyen bir taslak PR de var ama henüz birleştirilmiş değil
  • Basit yeniden sıralama yaklaşımının sorunu
    • Nesneyi mevcut indeksten silip hedef indekste yeniden eklemek
    • Bu iki işlemin değişmezlerini birleştirmek bile, "çok sayıda eşzamanlı yeniden sıralama olduğunda nesne listede tam olarak bir kez bulunur" şeklindeki istenen değişmezi garanti etmez
    • Birden fazla eşzamanlı silme ve ekleme varsa nesne listede birden fazla konumda yer alabilir (Alice ve Bob, B’yi ayrı ayrı delete+insert ile taşıdığında iki silme tek bir tombstone’da birleşir ama iki ekleme ayrı yeni öğeler oluşturur ve ikisi de yaşar; sonuçta B iki kez görünür)
  • "Tam olarak bir kez" değişmezini uygulama katmanında doğrudan sağlama
    • Klip zaman çizelgesine eklendiğinde ona bir semantic id atanır
    • Yeniden sıralama sırasında yukarıdaki gibi silme ve ekleme işlemleri tetiklenir
    • Okuma anında uygulama aynı semantic id’ye sahip kopyaları tarar, silinmemiş ilk öğeyi keyfi olarak seçer ve diğerlerini yok sayar
    • Böylece nesne listede yalnızca bir kez bulunur ve tüm okuyucular her zaman aynı nihai duruma ulaşır
  • Liste yeniden sıralama, Ducking’de Automerge’in sağlamadığı tek işlem oldu; ilgili PR birleşirse uygulama seviyesi mantığa gerek kalmayabilir

Belge geçmişi (Document history)

  • İyi bir çok oyunculu UI, geçmiş yönetimi araçlarına ihtiyaç duyar; işbirlikçiler yokken yapılan değişiklikleri görmek, diff yorumları bırakmak, eski sürümleri karşılaştırmak ve geri almak isterler
  • Automerge, belge sürüm geçmişini takip etmek ve geçmiş ile karşılaştırmaları ele almak için güçlü temel bileşenler sunar
    • Ancak bu bilgiyi nasıl göstereceğiniz ve kullanıcıya hangi kavramları sunacağınız uygulama geliştiricisinin kararına bağlıdır
  • Ink & Switch’in Patchwork lab notes içeriği öneriliyor
    • Özellikle kullanıcıya branch’leri gösterme çalışmaları ve universal comments üzerine olanlar ilgi çekici
  • Ducking’in yerleştiği görece basit işbirliği ve geçmiş modeli
    • Kullanıcının adlandırabildiği checkpoint’lere sahip doğrusal bir sürüm geçmişi; checkpoint hem değişikliklerin gruplanma birimi hem de tartışma, diff ve rollback birimi
    • Sesin belirli bir noktasına, transkriptin bir bölümüne veya bir sürüm checkpoint’ine bağlanabilen yorum dizileri (comment thread)
  • Henüz branch eklemek için yeterli sebep oluşmamış olsa da ileride faydalı olabileceği belirtiliyor

Metin ve marks

  • Zengin metinle çalışmak, düzenlenebilir metin üzerine özel mantık eklemeye çalıştığınızda özellikle zorlu bir problemdir
    • Zengin metin ve genel olarak çok oyunculu yazılımdaki zorlukları açıklayan Peritext makalesi öneriliyor
  • Automerge’in rich text şeması, marks içerir; bunlar metin aralıklarına uygulanan ve metin düzenlenirken de tutarlılığını koruyan açıklamalardır
    • En yaygın kullanım kalın ve italik gibi biçimlendirmedir; ancak uygulamaya özgü özel mark’lar da oluşturulabilir
  • Ducking’deki iki özel mark kullanımı
    • Yorum dizilerinin hedef aldığı transkript alanlarını takip etmek
    • Transkriptteki kelimelerin zaman damgalarını takip etmek ve buna rağmen düzenlemeye izin vermek
      • Transkripsiyon servisi, her kelimeye zaman bilgisi mark’ı iliştirilmiş rich text nesnesi olarak transkripti Automerge’e kaydeder
      • Küçük bir yazım hatasında tek kelime düzeltilirse mark korunur ve tüm zaman bilgisi saklanır
      • Tüm cümle değiştirilirse aradaki bazı mark’lar kaybolabilir; ancak cümlenin başı ve sonundaki mark’lar korunur, böylece en azından yaklaşık zaman bilgisi elde kalır
  • marks’ın bir kısıtı, verinin basit bir değer olması gerektiği (genelde string) ve çok oyunculu biçimde birleştirilememesidir
    • Transkript zaman bilgisi gibi küçük ve değişmeyen veriler için JSON string olarak serileştirilir
    • Yorum dizileri gibi daha karmaşık veya değişken verilerde ise mark içinde yalnızca id tutulur, asıl veri belgede başka bir yerde saklanır
  • marks, çok oyunculu rich text üzerine uygulama özellikleri kurmak için mükemmel bir temel sağlar

Sonraki yazı — serinin yapısı

  • Bu yazı, Ducking geliştirme süreci üzerine üç yazılık serinin 2. bölümü
      1. bölüm: yazılımın özgün UI tasarımını anlatıyor
      1. bölüm (bu yazı): Automerge’i incelemeyi öneriyor ve hobi amaçlı çok oyunculu projeler inşa etmenin mümkün olduğunu gösteriyor
    • Son 3. bölüm planlanıyor: Ducking yapımından çıkarılan dersler
  • Son 3. bölümle ilgili notlar
    • LLM desteği, işi büyütmek için değil; daha fazla eskiz ve hamak zamanı yaratmak için kullanıldı
    • Yalnızca az sayıda insanı memnun etmesi gereken narrowcast yazılımı üretmenin keyfi vurgulanıyor

Beklenen sorular

Ses verisi ne oluyor?

  • Tüm çok oyunculu veri Automerge’de tutuluyor; ancak temel ses blob’u, hızlı oynatma için Automerge dışında ayrı ele alınıyor
  • Hedef, yeni bir işbirlikçinin sayfa yüklendikten sonra 4 saniye içinde dinlemeye ve düzenlemeye başlayabilmesi; bu hem bir masaüstü uygulamayı açmaktan hızlı hem de tüm proje dosyasını indirmekten çok daha hızlı
    • 1 saatlik bir bölüm, yüksek kaliteli stüdyo kaydından 4 saatlik ses, efektler ve arka plan müziğiyle birlikte yaklaşık 1 GB ses verisine dayanabiliyor
  • Hızlı cold start için yükleme sırasında ses servisinin yaptığı işler
    • Orijinal sesi yedeklemek
    • Konuşmayı transkript görünümü için yazıya dökmek
    • Zaman çizelgesi görünümü için waveform üretmek
    • 40 dakikalık kayıttan sadece 1 dakika kullanılıyorsa, istemcilerin çoğunun yalnızca bir iki küçük parça alması için kısa pencerelere bölmek
    • Parçaları sıkıştırılmış formata transcode ederek, yüksek kaliteli ses arka planda inerken anında çalınabilecek kayıplı bir sürüm sunmak
  • UI veri katmanı, kullanıcının niyetine göre hemen gereken verinin hızlı sürümünü ve gerçekten kullanılan tüm sesin yüksek kaliteli sürümünü yüklemeyi yönetiyor
    • Tarayıcının IndexedDB API’si, çok kademeli cache ve content-addressable saklama için kullanışlı; otomatik eviction yönetimiyle kullanılırsa kalıyor, kullanılmazsa kayboluyor
  • Tüm bu işleme ve yerel cache tamamlandıktan sonra UI’nin geri kalanı, ses üzerinde hızlı rastgele erişim olduğunu varsayıp düzenleme iş akışına odaklanabiliyor

Neden local-first bir uygulama yerine sunucu + tarayıcı UI yapıldı?

  • Obsidian gibi sunucusuz tamamen çalışan local-first uygulamalar tercih ediliyor; özellikle güvenilir bir çıkış yolu sunarken aynı zamanda bulut tabanlı ücretli deneyim sağlayan türler beğeniliyor
  • Başlangıçta, yerel dosya sistemi kaydı ve isteğe bağlı sunucu senkronizasyonu olan bir Tauri uygulaması seçeneğiyle yola çıkıldı
    • UI, ister sunucu ister yerel uygulama tarafından sağlansın aynı veri arayüzüne göre kuruldu
    • Böylece ileride hiçbir finansman, uygulamayı lock-in ile daha kârlı hale getirme yönünde ayartamasın diye bir güvence oluşturuldu
  • Sonrasında bunun bir SaaS değil, partneri ve birkaç arkadaşıyla kullanmak istediği bir şey olduğu anlaşıldı
    • Yanlış kullanma teşviki ortadan kalktı, kalıcı işletme maliyeti de düşük kaldı; bu yüzden en kolay yöntem seçildi
  • Yaklaşık 3 saniyelik cold start başarılınca kimse yerel uygulama indirip kurmaya vakit harcamak istemedi
  • Umut, ses uygulamalarının bugünkü masaüstü odaklı dünyadan, senkronizasyon seçeneklerine sahip local-first bir dünyaya doğrudan sıçraması ve aradaki 10–20 yıllık SaaS lock-in dönemini atlaması

Automerge güvenli mi ve web ölçeğinde çalışır mı? Bir startup’ta kullanılmalı mı?

  • Buna neşeyle bilmediğini söyleyebiliyor; bu bir reddiye değil, gerçekten bilinmediği anlamına geliyor
  • İşe ilk başladığında çakışmasız gerçek zamanlı çok oyunculu düzenleme sihir gibiydi; 10 yıl önce bazı özel problemlerin bilinen çözümleri vardı ama bunlar fonlu ekipler ve çok alanlı uzmanlık gerektiriyordu
    • Bugün ise tek bir bağımlılık ekleyip büyük ölçüde sezgisel bir UI kurarak arkadaşlarla gerçek zamanlı işbirliği yapmak mümkün
  • Güvenlik açısından Ducking şu anda sınırlı ağ erişimi ve Automerge sunucu websocket bağlantısı oluşturulurken yapılan bir yetkilendirme (authorization) adımıyla korunuyor
    • Kullanıcılar davet edilmedikleri projeleri bulamıyor veya düzenleyemiyor
    • Düzenleme ve yorumların kullanıcıya atfedilmesi yalnızca kısmen güvenli; arkadaşların kötü davranmayacağı varsayımına dayanıyor
    • Sadece yorum yapma / düzenleme yapamama, projenin sadece bir bölümünü düzenleme, keşfedilebilirliği kontrol etme gibi ince taneli yetkiler dikkatli tasarım gerektiriyor
  • Ink & Switch’in geliştirdiği Keyhive, kriptografik olarak güvenli yetenek tabanlı bir erişim kontrol modeli sunuyor
    • Güvenilmeyen kullanıcılara Automerge uygulamalarını açık paylaşmayı kolaylaştırabilir, ancak henüz hazır değil

Automerge daha mı iyi?

  • Bu alandaki diğer çözümlerden biri Yjs; ancak hangisinin uygun olduğunu sizin yerinize değerlendiremez
  • Değişmeyen tavsiye
    • Problemi derinlemesine düşünün, karşılaşacağınız sınırlar için kabaca hesap yapın, birden fazla alternatifle prototip geliştirin ve belki de probleminizin o kadar zor olmadığını, dolayısıyla en yeni ve en üst düzey çözüme ihtiyaç duymadığını dürüstçe kabul edin
  • Ducking örneğinde, hızlı prototipler ve dokümantasyon incelemesiyle Automerge’in bu kullanım için yeterince olgun ve performanslı olduğu görüldü
  • Daha da önemlisi, Ink & Switch ekosistemi estetik olarak çekici bulundu
    • Automerge’in yalnızca bir senkronizasyon ve sürümleme motoru değil; yazılımı daha güvenli, daha işbirlikçi, daha esnek, daha keyifli ve daha kişisel hale getiren daha büyük bir vizyonun parçası olması etkileyici
    • Keyhive ve benzerlerinin başarılı olması, az sayıda insan için yapılmış küçük ama büyülü yazılımların çoğalması umuluyor

Henüz yorum yok.

Henüz yorum yok.