نوشن چطور ویرایش همزمان رو با CRDT حل کرد
خلاصهٔ کاملتر
تیم نوشن میگه ادیتورشون تا قبل از ۲۰۲۵ واقعاً مشترک نبوده. متن هر بلاک به شکل یه رکورد دیتابیس ذخیره میشد و سرور هر آپدیت رو همونطور که میرسید اعمال میکرد، پس عملاً قانون «آخرین نوشتن برندهست» حاکم بود: اگه دو نفر همزمان یه بلاک رو عوض میکردن، تغییر یکیشون کامل پاک میشد. هرچی تعداد همکارها بیشتر، احتمالش بیشتر. با اومدن حالت آفلاین هم خطرش خیلی بالاتر میرفت.
راهحلشون CRDT بود، یعنی ساختار دادهای که چند کلاینت نسخهی محلی خودشون رو دارن و تغییرات همزمان به شکل قطعی و بدون گم شدن با هم ادغام میشه. نسخهای که استفاده میکنن بر پایهی RGA ـه: یه درخت که همهی کاراکترهایی که تا حالا وارد شدن رو با یه شناسهی پایدار نگه میداره. حذف هم واقعاً پاک نمیکنه، فقط آیتم رو به عنوان tombstone علامت میزنه تا عملیاتهای در راه یا آفلاین بدونن باید کجا اعمال بشن.
شناسهی هر آیتم دو تیکهست: session ID که نشست هر کلاینت رو جدا میکنه، و Lamport clock که یه شمارندهی منطقی بالاروندهست. آیتمهایی که به یه مبدأ اشاره میکنن بر اساس تازهتر بودن این شمارنده مرتب میشن و اگه شمارندهها برابر بودن، session ID تصمیم میگیره؛ پس همهی کلاینتها به یه ترتیب یکسان میرسن. برای صرفهجویی هم به جای تکتک کاراکترها، به یه رشتهی پیوسته از کاراکترهای یه نشست یه شناسه و یه طول میدن.
برای متن قالبدار از ایدههای الگوریتم Peritext استفاده کردن: عملیات اضافه و حذف annotation (همون بولد و ایتالیک و لینک) روی خود درخت ذخیره میشه و موقع خوندن درخت اعمال میشه. هر annotation یه لنگر شروع و پایان داره که درست قبل یا بعد از مرز یه آیتم میشینه. همین مشخص میکنه که قالب کشداره یا نه: بولد کشداره، پس متنی که پشتش تایپ میکنی هم بولد میشه، ولی هایپرلینک کشدار نیست.
سختترین قسمت وقتیه که یکی وسط بلاک Enter میزنه و متن بین دو بلاک تقسیم میشه، در حالی که یکی دیگه همزمان داره به همون متن اضافه میکنه. برای این «text slice» و «text instance» رو ساختن: عملیات به جای شناسهی بلاک به شناسهی instance اشاره میکنه و یه جدول نگاشت میگه کدوم بلاکها تیکهای از اون instance رو دارن. عیبش اینه که اگه یه بلاک ۹۹ بار split بشه، برای یه درج ساده باید ۱۰۰ بلاک رو بخونی.
جواب این مشکل «search label» ـه: هر تیکه با برچسب خالی شروع میشه و هر بار که split میشه یه L یا R به برچسبش اضافه میشه، پس کوئری فقط بلاکهایی رو میگیره که برچسبشون با برچسب عملیات شروع میشه. تو عمل هم رشتهای مثل LRL ذخیره نمیشه و یه کدگذاری فشرده دارن که ذخیرهسازی رو پنج برابر بهینهتر میکنه. این سیستم از جولای ۲۰۲۵ رو پروداکشنه و پایهی حالت آفلاین و همکاری agent ها هم هست.
نکات کلیدی:
- قبل از این تغییر، متن هر بلاک با قانون «آخرین نوشتن برندهست» ذخیره میشد و ویرایش همزمان روی یه بلاک تغییرات یکی رو کامل پاک میکرد.
- CRDT نوشن بر پایهی RGA ـه و حذفها به شکل tombstone تو درخت باقی میمونن.
- شناسهی هر آیتم ترکیب session ID و Lamport clock ـه و همین ترتیب یکسان رو روی همهی کلاینتها تضمین میکنه.
- قالببندی با ایدههای Peritext پیاده شده: بولد کشداره، هایپرلینک نه.
- سیستم از جولای ۲۰۲۵ رو پروداکشنه و دقیقهای میلیونها عملیات CRDT پردازش میکنه.




