Automerge ile Çok Oyunculu Bir Podcast Editörü Yapmak
(adamsolove.com)- 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 installile 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
useStatedesenine 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
useDocumenthook kullanım örneği:const [doc, changeDoc] = useDocument<Episode>(docUrl)ile belge alınır, giriş değeri değiştiğindechangeDoc((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ü
-
- bölüm: yazılımın özgün UI tasarımını anlatıyor
-
- 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.