IlmHamroh
JavaScript Full-stack/29-qism. Backend integratsiyalar: fayl, to'lov, bot, realtime43/69-dars15 daqiqa
Mundarija (24)

Tayyor realtime xizmatlari va CRDT: Centrifugo, Pusher, Ably va Yjs

Qisqacha: O'z realtime serveringiz — ulanishlar, masshtab, presence, tarix — hammasi sizning zimmangizda. Tayyor yechimlar ikki xil: o'zingiz o'rnatadigan server (Centrifugo, Soketi) va bulut xizmati (Pusher, Ably, Supabase Realtime). Ular kanonda sinalmagan — tanlov mezonlari hujjat bo'yicha. Ikkinchi mavzu — ziddiyat: ikki kishi bir matnni oflayn tahrirlasa, "oxirgi yozgan yutadi" (LWW) birining ishini yo'qotadi. CRDT (Yjs) esa ikkalasini birlashtiradi: kanonda "Non olish, sut" va "Bugun: Non sotib olish" → "Bugun: Non sotib olish, sut".

Bu darsda

  • O'z serveringiz va tayyor xizmat o'rtasida mezonlar bilan tanlaysiz.
  • Centrifugo, Pusher, Ably, Soketi va Supabase Realtime nima ekanini bilasiz.
  • LWW nega ma'lumot yo'qotishini kodda ko'rasiz.
  • Yjs bilan oflayn tahrirni birlashtirish natijasini va narxini (bayt, tombstone) o'qiysiz.
  • O'zingiz eng sodda CRDT'larni (G-Counter, LWW-Map) yozasiz.

Oldin bilishingiz kerak: Realtime'ni masshtablash, Amaliyot: chat va bildirishnomalar, Optimistic concurrency, Managed va serverless Postgres (vendor lock-in).

Oldingi darsda chatni o'zimiz qurdik va har detalni — saqlash, holatlar, oflayn — qo'lda hal qildik. Bugun ikki savol: buni umuman o'zingiz qurishingiz shartmi va bir matnni ikki kishi o'zgartirsa nima bo'ladi?

1. Nega bu kerak?

Jasur aka jamoasi uchun ichki ilova qilyapti. Unga uchta realtime funksiya kerak: bildirishnoma, chat va hujjatni birga tahrirlash. Oldingi darslar bo'yicha hisoblaymiz: Socket.IO serveri, Redis adapter, presence TTL bilan, sticky session yoki faqat WebSocket, tarix, monitoring. Bu — alohida xizmat, uni kimdir qo'llab-quvvatlashi kerak.

Ikkinchi muammo — birga tahrir. Aziz poyezdda internetsiz vazifa izohini o'zgartirdi, Dilnoza ofisda o'sha izohni boshqacha o'zgartirdi. Aziz internetga ulanganda kimning matni qoladi?

O'xshatish: to'y. Oshni o'zingiz damlashingiz mumkin (qozon, o'tin, oshpaz — hammasi sizda) yoki oshxonaga buyurtma berasiz (tez, lekin menyu va narx ularniki). Ikkinchi savol — mehmonlar ro'yxati: ikki qarindosh alohida qog'ozga yozgan, ikkalasidan bittasini emas, birlashtirilgan ro'yxatni olish kerak.

2. Qurish yoki tayyorini olish

2.1 Tayyor yechimlar xaritasi

Quyidagilar kanonda sinalmagan — hisob yoki alohida server kerak edi. Tavsif rasmiy hujjat va repolar bo'yicha (2026-10-28 da o'qildi):

Yechim Turi Qisqacha
Centrifugo o'zingiz o'rnatasiz ochiq kodli realtime xabar serveri (Go, Apache-2.0)
Soketi o'zingiz o'rnatasiz Pusher protokoliga mos ochiq kodli server
Pusher Channels bulut kanallarga nashr/obuna, private va presence kanallar
Ably bulut pub/sub, tarix, presence, yetkazish kafolatlari
Supabase Realtime bulut yoki o'zingiz Postgres o'zgarishlari, broadcast, presence

Umumiy naqsh — hammasida bir xil: brauzer xizmatga ulanadi (WebSocket yoki SSE), sizning backend'ingiz esa xizmatga HTTP API orqali "shu kanalga shu xabarni yubor" deydi. Ulanishlar, masshtab, qayta ulanish — xizmatning ishi.

flowchart LR
  B[Brauzer] -->|WebSocket| X[Realtime xizmat]
  B -->|REST| API[Sizning API]
  API -->|HTTP publish| X
  API -->|auth token| B
  API --> DB[(Postgres)]

Diagrammaga qarang: sizning API realtime ulanishlarni umuman ushlamaydi. U faqat ikki ish qiladi: foydalanuvchiga xizmatga ulanish uchun token beradi (qaysi kanallarga ruxsat bor) va voqea bo'lganda xizmatga nashr qiladi. Bu Realtime'ni masshtablash darsidagi Redis adapterning "bulutdagi" varianti.

2.2 Auth: kanalga ruxsat

Private kanalga ulanishda mijoz sizning backend'ingizdan imzolangan ruxsat oladi: Pusher'da auth endpoint (ruxsat beradigan maxsus manzil), Centrifugo'da JWT (imzolangan token; uni 28-qismda batafsil o'rganasiz). Mantiq oldingi darslardagidek: "bu foydalanuvchi loyiha:7 kanalini ko'ra oladimi?" — sizning bazangiz hal qiladi. Xizmat faqat imzoni tekshiradi. Imzo kaliti — server sirida (Sirlarni boshqarish), brauzerda emas.

sequenceDiagram
  participant B as Brauzer
  participant API as Sizning API
  participant X as Realtime xizmat
  B->>API: loyiha:7 kanaliga ruxsat so'rayman
  Note over API: bazada tekshiradi (a'zomi?)
  API-->>B: imzolangan token
  B->>X: ulanish + token
  Note over X: faqat imzoni tekshiradi
  X-->>B: obuna tayyor
  API->>X: HTTP publish (loyiha:7, xabar)
  X->>B: xabar

Ketma-ketlikka qarang: qaror (ruxsat bormi) doim sizning API'da. Xizmat faqat "imzo to'g'rimi" deb tekshiradi va xabarni yetkazadi.

2.3 Mezonlar

Jadvalda bitta yangi so'z bor: lock-in (bog'lanib qolish) — bir xizmatga shunchalik moslashasizki, boshqasiga o'tish qimmat va uzoq ishga aylanadi.

Savol O'zingiz (Socket.IO, SSE) Tayyor xizmat
Ulanishlar 1 000 gacha bitta Node bemalol ortiqcha bo'lishi mumkin
100 000+ ulanish, ko'p mintaqa katta ish asosiy afzalligi
Narx server + vaqtingiz ulanish/xabar bo'yicha to'lov
Ma'lumot qayerda sizda xizmat serverlarida
Savol O'zingiz (Socket.IO, SSE) Tayyor xizmat
Lock-in yo'q protokol va SDK'ga bog'lanasiz
Moslashuvchanlik to'liq xizmat imkoniyatlari bilan
Kim tuzatadi siz xizmat jamoasi

Ikki amaliy eslatma:

  • Ma'lumot joylashuvi. Bulut xizmatlar xabarlarni o'z serverlari orqali o'tkazadi. Shaxsiy ma'lumot bo'lsa, O'zbekiston qonunchiligidagi talablarni tekshiring (shaxsiy ma'lumotlar haqidagi qonun — Web scraping Node'da darsida O'RQ-547 eslatilgan). Bu holda o'zingiz o'rnatadigan yechim (Centrifugo, Soketi) mos keladi.
  • Loyiha faolligi. Soketi README'sida "maintenance bilan muammolar bo'lgani, yangilanishlar kam" deb yozilgan (2026-10-28). Ochiq kodli vositani tanlashdan oldin oxirgi reliz sanasini va issue'larni tekshiring (Paket tanlash va baholash).

Tekshirib ko'ring: 300 xodimli kompaniya ichki portali uchun bildirishnomalar kerak. Server Toshkentda, ma'lumot tashqariga chiqmasligi kerak. Nima tanlaysiz?

Javob

O'zingiz: SSE (bildirishnoma — bir tomonlama) mavjud Node API'da. 300 ulanish — bitta jarayon uchun kichik yuk, bulut xizmati shart emas, ma'lumot tashqariga chiqmaydi. Ikki tomonlama va katta funksiyalar kerak bo'lsa — o'zingiz o'rnatadigan Centrifugo. Bulut xizmati bu yerda ikki shartga (ma'lumot joylashuvi va hajm) mos emas.

3. Ziddiyat: oxirgi yozgan yutadi

3.1 LWW

Eng sodda qoida — LWW (last-write-wins, oxirgi yozgan yutadi): har yozuvda vaqt bor, birlashtirishda kattasi qoladi.

js
// LWW: butun matn — bitta qiymat, vaqti kattasi yutadi
function lwwBirlashtir(a, b) {
  return a.vaqt >= b.vaqt ? a : b;
}

const asl = "Non olish";
const aziz = { matn: asl + ", sut", vaqt: 1000 };
const dilnoza = { matn: "Bugun: Non sotib olish", vaqt: 1005 };

console.log(lwwBirlashtir(aziz, dilnoza).matn);
console.log(lwwBirlashtir(dilnoza, aziz).matn);

Konsolda:

text
Bugun: Non sotib olish
Bugun: Non sotib olish

Ikkala tartibda ham natija bir xil — bu yaxshi (nusxalar bir xil holatga keladi). Lekin Azizning ", sut" qo'shimchasi yo'qoldi. Dilnoza 5 ms keyin saqlagani uchun. Yana bir muammo: vaqt qurilma soatidan olinadi, soati oldinda turgan telefon doim "yutadi".

3.2 Qachon LWW yetarli

Vazifa holati, muddati, ustuvorligi kabi bitta qiymatli maydonlar uchun LWW (yoki undan yaxshisi — Optimistic concurrencydagi versiya bilan "o'zgargan bo'lsa, foydalanuvchiga ayt") odatda yetarli. Kanon xulosasi ham shu: "vazifa matni uchun CRDT ortiqcha (optimistik qulf versiya — 26-qism yetarli)". Muammo — matn, uni ikki kishi bir vaqtda yozganda.

4. CRDT va Yjs

4.1 Nima bu

CRDT (Conflict-free Replicated Data Type — ziddiyatsiz takrorlanadigan ma'lumot turi) — har nusxa mustaqil o'zgaradigan va har qanday tartibda birlashtirilganda bir xil natijaga keladigan ma'lumot tuzilmasi. Server "kim to'g'ri" deb hakamlik qilmaydi — matematik qoida hal qiladi.

Matn uchun g'oya: har belgiga noyob ID (kim yozgan + uning hisoblagichi) beriladi va "qaysi belgidan keyin" yozilgani saqlanadi. Ikki kishi turli joylarga yozsa, ikkalasi ham o'z joyida qoladi. O'chirilgan belgi esa butunlay yo'qolmaydi — "o'chirilgan" belgisi bilan qoladi (tombstone), boshqa nusxaning o'zgarishlari unga tayanishi mumkin.

Yjs — JavaScript'dagi eng ko'p ishlatiladigan CRDT kutubxonasi: Y.Text, Y.Map, Y.Array turlari, o'zgarishlarni ixcham ikkilik "update"larga kodlaydi.

4.2 Kanon tajribasi: oflayn tahrir

Kanon kodi (yjs 13.6.33, formatlangan):

js
import * as Y from "yjs";

const asl = new Y.Doc();
asl.getText("izoh").insert(0, "Non olish");
const boshlangich = Y.encodeStateAsUpdate(asl);

const aziz = new Y.Doc(); Y.applyUpdate(aziz, boshlangich);
const dil = new Y.Doc(); Y.applyUpdate(dil, boshlangich);

aziz.getText("izoh").insert(9, ", sut"); // oxiriga
dil.getText("izoh").insert(0, "Bugun: "); // boshiga
dil.getText("izoh").delete(7 + 4, 5); // "olish" ni o'chiradi
dil.getText("izoh").insert(7 + 4, "sotib olish");

// har biri faqat boshqasida yo'q o'zgarishlarni yuboradi
const uA = Y.encodeStateAsUpdate(aziz, Y.encodeStateVector(dil));
const uD = Y.encodeStateAsUpdate(dil, Y.encodeStateVector(aziz));
Y.applyUpdate(aziz, uD);
Y.applyUpdate(dil, uA);

Natijada uchinchi qatorga qarang: birlashgandan keyin ikkala nusxadagi matn va bir xil belgisi.

text
Aziz (oflayn): "Non olish, sut"
Dilnoza (oflayn): "Bugun: Non sotib olish"
birlashgandan keyin Aziz: "Bugun: Non sotib olish, sut" | Dilnoza: "Bugun: Non sotib olish, sut" | bir xil: true
farq update'lari: Aziz → 21 bayt, Dilnoza → 48 bayt

Nima bo'ldi? Ikkala o'zgarish ham saqlandi: Dilnozaning "Bugun:" va "sotib", Azizning ", sut" — hammasi joyida. Ikkala nusxa bir xil. encodeStateVector — "menda kimdan nechtagacha o'zgarish bor" degan qisqa ro'yxat; unga qarab faqat yetishmayotgan qism yuboriladi — 21 va 48 bayt, butun hujjat emas.

Kanon chiqishidagi keyingi qator ("LWW bo'lganda natija: … yoki … — bittasining o'zgarishi yo'qoladi") o'lchov emas, izoh: kanon skriptida u matn sifatida yozilgan. Yuqoridagi LWW kodimiz buni haqiqatan ko'rsatdi.

4.3 Y.Map: maydon darajasida LWW

Matnda CRDT ikkala o'zgarishni birlashtiradi. Bitta maydonga ikki xil qiymat yozilsa-chi? Ikkalasini "birlashtirib" bo'lmaydi — muddat yoki 28, yoki 30. Kanon:

js
const m1 = new Y.Doc(); const m2 = new Y.Doc();
m1.getMap("vazifa").set("muddat", "2026-10-28");
m2.getMap("vazifa").set("muddat", "2026-10-30");
m2.getMap("vazifa").set("ustuvorlik", "yuqori");
Y.applyUpdate(m1, Y.encodeStateAsUpdate(m2));
Y.applyUpdate(m2, Y.encodeStateAsUpdate(m1));
text
m1: {"muddat":"2026-10-30","ustuvorlik":"yuqori"} m2: {"muddat":"2026-10-30","ustuvorlik":"yuqori"} — ikkalasida bir xil; maydon darajasida LWW

ustuvorlik — faqat m2 yozgan, ziddiyat yo'q. muddat da biri yutdi. Qaysi biri? Biz shu tajribani 20 marta qaytardik (yjs 13.6.33, Node 24.21.0) va har safar clientID larni ham yozdik:

text
{
  'bir xil 2026-10-30 (katta clientID: m2)': 12,
  'bir xil 2026-10-28 (katta clientID: m1)': 8
}

Har safar ikkala nusxa bir xil qiymatga keldi — CRDT kafolati. Lekin g'olib almashib turdi: clientID kattaroq hujjatniki yutdi, clientID esa har new Y.Doc() da tasodifiy. Ya'ni bu "oxirgi yozgan" emas, "tasodifiy, lekin hamma uchun bir xil" g'olib. Bitta maydon uchun foydalanuvchi niyatini CRDT bilmaydi — kerak bo'lsa ziddiyatni foydalanuvchiga ko'rsating.

4.4 Narxi: hajm va tombstone

Kanon o'lchovida "holat" baytlarini matn uzunligi bilan solishtiring:

text
10 000 insert: 64 ms; holat 10015 bayt (matn 10 000 bayt); V2 kodlash 10029 bayt
1000 marta yozish+o'chirish (natija 5000 belgi): holat 32954 bayt — o'chirilganlar "tombstone" sifatida qoladi
  • Ketma-ket yozilgan 10 000 belgi — atigi 15 bayt qo'shimcha: Yjs ketma-ket qo'shimchalarni bitta bo'lakka birlashtiradi.
  • 1 000 marta "10 belgi yoz, 5 tasini o'chir" — natija 5 000 belgi, lekin holat 32 954 bayt: o'chirilganlar izi qoladi. Ko'p tahrirlangan hujjat vaqt o'tishi bilan o'sadi.
  • 64 ms — bitta o'lchov, kanon mashinasida.

Bu raqamlar CRDT bepul emasligini ko'rsatadi. Shuning uchun uni haqiqatan birga tahrirlanadigan joyda ishlating.

5. Yjs ni tarmoqqa ulash

Yjs faqat ma'lumot tuzilmasi — update'larni yetkazish sizning ishingiz. Odatda "provider" ishlatiladi: WebSocket orqali (y-websocket, Hocuspocus serveri), WebRTC orqali yoki IndexedDB'da oflayn saqlash. Server update'larni tarqatadi va hujjatni bazada saqlaydi. Awareness — kursor joyi va kim hozir hujjatda (presence'ning hujjatdagi shakli). Bu providerlar kanonda sinalmagan — Yjs hujjati bo'yicha (2026-10-28).

Boshqa yo'nalish — OT (Operational Transformation): Google Docs tarixan shunga asoslangan. U markaziy server talab qiladi; CRDT esa oflayn va serversiz (peer-to-peer) ishlashga qulayroq. Bugungi ko'p yangi vositalar (Figma o'z variantida, Notion'ning ba'zi qismlari, tldraw) CRDT g'oyalaridan foydalanadi.

6. Ko'p uchraydigan xatolar

Xato Natijasi To'g'risi
matnni LWW bilan birlashtirish bir kishining ishi yo'qoladi CRDT yoki versiya + ogohlantirish
har maydonga CRDT ortiqcha murakkablik va hajm oddiy maydonga versiya
qurilma soatiga ishonish soati oldindagi "doim yutadi" server vaqti yoki mantiqiy soat
bulut xizmatiga shaxsiy ma'lumot qonun talablari buziladi joylashuvni tekshirish
xizmat kalitini brauzerga qo'yish har kim istalgan kanalga yozadi token faqat backend'da imzolanadi
eski ochiq kodli serverni olish xavfsizlik tuzatishlari yo'q relizlar va faollikni tekshirish

7. Mashqlar

Mashqlar kurs/mashqlar/29/43-crdt/ da.

1-mashq (oson): nima tanlaysiz

Har vaziyatga yechim tanlang (o'z SSE/Socket.IO, o'zingiz o'rnatadigan server, bulut xizmati; LWW/versiya yoki CRDT) va sababini bir gapda ayting:

  1. Startap: 50 000 foydalanuvchili mobil o'yinda reyting jadvali jonli yangilanadi, jamoada 2 dasturchi.
  2. Vazifaning muddat maydonini ikki kishi bir vaqtda o'zgartirdi.
  3. Jamoa hujjatini oflayn ham tahrirlash mumkin bo'lishi kerak.
  4. Davlat tashkiloti, ma'lumot mamlakatdan chiqmasligi kerak, 20 000 ulanish.
Yechim
  1. Bulut xizmati (Pusher, Ably) — kichik jamoa, katta ulanish soni; infratuzilmani xizmat oladi.
  2. Versiya (optimistic concurrency) — bitta qiymat; ikkinchisiga "o'zgargan" deb ayting yoki LWW.
  3. CRDT (Yjs) — matn, oflayn, birlashtirish kerak.
  4. O'zingiz o'rnatadigan server (Centrifugo) yoki o'z Socket.IO + Redis — ma'lumot sizning serverlaringizda.

2-mashq (o'rta): G-Counter

Eng sodda CRDT — G-Counter (faqat o'sadigan hisoblagich): har nusxa faqat o'z katagini oshiradi, birlashtirishda har katakning kattasi olinadi, qiymat — kataklar yig'indisi. Telefon 2 marta, noutbuk 3 marta "like" bosdi. Ikkala tartibda birlashtiring va qiymatni chiqaring; keyin birlashgan holatni yana birlashtirib, natija o'zgarmasligini ko'rsating. Ishora: Object.entries, Math.max, spread (Spread va rest operatori).

Yechim
js
// G-Counter: har nusxa faqat o'z katagini oshiradi
const yangi = () => ({});
const oshir = (s, nusxa, n = 1) =>
  ({ ...s, [nusxa]: (s[nusxa] ?? 0) + n });

function birlashtir(a, b) {
  const natija = { ...a };
  for (const [k, v] of Object.entries(b)) {
    natija[k] = Math.max(natija[k] ?? 0, v);
  }
  return natija;
}

const qiymat = (s) => Object.values(s).reduce((x, y) => x + y, 0);

const telefon = oshir(oshir(yangi(), "telefon"), "telefon"); // 2
const noutbuk = oshir(yangi(), "noutbuk", 3); // 3

const t2 = birlashtir(telefon, noutbuk);
const n2 = birlashtir(noutbuk, telefon);
console.log(qiymat(t2), qiymat(n2));
// bir xil holatni qayta yuborish — natija o'zgarmaydi
console.log(qiymat(birlashtir(t2, n2)), qiymat(birlashtir(t2, t2)));

Konsolda:

text
5 5
5 5

Uch xususiyat CRDT'ni CRDT qiladi: tartib ahamiyatsiz (t2 va n2 bir xil), takror ahamiyatsiz (birlashtir(t2, t2) o'zgarmadi) va guruhlash ahamiyatsiz. Shuning uchun tarmoq xabarni ikki marta yoki boshqa tartibda yetkazsa ham natija to'g'ri. Nega oddiy son emas? Ikki nusxa "4" va "5" deb yuborsa, ulardan haqiqiy yig'indini (2 + 3) chiqarib bo'lmaydi — kataklar kim nechta qo'shganini saqlaydi.

3-mashq (qiyin): LWW-Map

LWW-Map yozing — har maydon { qiymat, vaqt, nusxa } ko'rinishida. yoz(xarita, maydon, qiymat, vaqt, nusxa) yangi obyekt qaytaradi. birlashtir(x, y) har maydonda vaqti kattasini oladi. Vaqt teng bo'lsa — nusxa nomi kattasini (Yjs clientID kabi deterministik qoida). a: muddat = 2026-10-28 (vaqt 5), matn = "Non olish" (7); b: muddat = 2026-10-30 (vaqt 5), ustuvorlik = "yuqori" (6). Ikkala tartibda birlashtirib, faqat qiymatlarni (maydon nomi bo'yicha saralangan) chiqaring.

Yechim
js
// LWW-Map: har maydon alohida; teng vaqtda nusxa nomi hal qiladi
function yoz(xarita, maydon, qiymat, vaqt, nusxa) {
  return { ...xarita, [maydon]: { qiymat, vaqt, nusxa } };
}

function yutadimi(a, b) {
  if (a.vaqt !== b.vaqt) return a.vaqt > b.vaqt;
  return a.nusxa > b.nusxa;
}

function birlashtir(x, y) {
  const natija = { ...x };
  for (const [m, q] of Object.entries(y)) {
    if (!natija[m] || yutadimi(q, natija[m])) natija[m] = q;
  }
  return natija;
}

const korinish = (x) => Object.fromEntries(
  Object.entries(x).sort().map(([m, q]) => [m, q.qiymat]));

let a = yoz({}, "muddat", "2026-10-28", 5, "a");
a = yoz(a, "matn", "Non olish", 7, "a");
let b = yoz({}, "muddat", "2026-10-30", 5, "b");
b = yoz(b, "ustuvorlik", "yuqori", 6, "b");

console.log(korinish(birlashtir(a, b)));
console.log(korinish(birlashtir(b, a)));

Konsolda:

text
{ matn: 'Non olish', muddat: '2026-10-30', ustuvorlik: 'yuqori' }
{ matn: 'Non olish', muddat: '2026-10-30', ustuvorlik: 'yuqori' }

muddat da vaqt teng (5) — "b" > "a", shuning uchun 30-oktabr. Ikkala tartibda bir xil. Teng vaqtda qo'shimcha qoidasiz birlashtir(a, b) va birlashtir(b, a) turli natija berardi — nusxalar hech qachon bir xil holatga kelmasdi. Kanonning Y.Map tajribasidagi "katta clientID yutadi" — aynan shu qoida.

8. Loyiha qadami: kanon tajribasi

Bu dars loyihaga kod qo'shmaydi. Kanon xulosasi: vazifalar dagi vazifa matni uchun CRDT ortiqcha — 26-qismdagi versiya ustuni bilan optimistik qulf yetarli; realtime esa o'z SseHub imiz bilan. Yjs natijalari — kanon o'lchovidan (IlmHamroh, 2026-10; yjs 13.6.33, Node 24.21.0, 2026-10-27). Y.Map g'olibini 20 marta qaytarish, LWW kodi va mashqlar — biz ishga tushirdik (2026-10-28). Centrifugo, Pusher, Ably, Soketi va Supabase Realtime — sinalmagan.

9. Real ishda

  • Figma, Linear, tldraw — hamkorlikda tahrirlash uchun CRDT yoki unga yaqin g'oyalar; Google Docs — tarixan OT.
  • Yjs asosidagi muharrirlar: Tiptap, BlockNote; serverlar — Hocuspocus, y-websocket. Automerge — boshqa mashhur CRDT kutubxonasi.
  • Pusher, Ably — startaplarda tez boshlash uchun; Centrifugo — o'z serverida katta yukni ushlashni xohlaganlar uchun.
  • Intervyuda: "Google Docs'ni qanday loyihalaysiz?", "CRDT va OT farqi?", "LWW qachon yetarli?"

Xulosa

  • Realtime'ni o'zingiz qurish — ulanishlar, masshtab, presence va tarix sizda; tayyor xizmat — buni oladi, evaziga narx, lock-in va ma'lumot joylashuvi.
  • Centrifugo va Soketi — o'zingiz o'rnatasiz; Pusher, Ably, Supabase Realtime — bulut; hammasi kanonda sinalmagan.
  • LWW birining o'zgarishini yo'qotadi: "Non olish, sut" ning ", sut" qismi ketdi.
  • Yjs ikkalasini birlashtirdi: "Bugun: Non sotib olish, sut"; farq update'i 21 va 48 bayt.
  • Y.Map da bitta maydon — deterministik, lekin clientID ga bog'liq g'olib (20 marta: 12 va 8); tombstone hujjatni o'stiradi.

Keyingi dars: Nega navbat kerak — og'ir ishni so'rovdan ajratib, fonda bajaramiz va javob vaqti qanday qisqarishini o'lchaymiz.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!