สร้างตัวแก้ไขพอดแคสต์แบบหลายผู้เล่นด้วย Automerge
(adamsolove.com)- เมื่อไม่กี่ปีก่อน การซิงก์ข้อมูลแบบหลายผู้เล่นเรียลไทม์ยังเป็นหนึ่งในปัญหาที่ยากที่สุด ซึ่งต้องใช้ผู้เชี่ยวชาญเฉพาะทางและการลงทุนระดับองค์กร แต่ตอนนี้สามารถสร้าง UI แบบหลายผู้เล่นได้แม้ในโปรเจ็กต์งานอดิเรกด้วย การ
npm installเพียงครั้งเดียว - Automerge เป็นเครื่องมือสำหรับสร้างโมเดลข้อมูลที่มีคุณสมบัติ local-first, ปลอดภัยสำหรับหลายผู้เล่น, และมีการจัดการเวอร์ชัน โดยจัดการการคงอยู่ของข้อมูล, ประวัติการเปลี่ยนแปลง, การกระจายข้อมูลไปยังผู้ร่วมงาน, และการแก้ conflict ให้อัตโนมัติ โดย UI ไม่ต้องคอยกังวล คล้ายกับแพตเทิร์น
useStateของ React - ในกรณีของ Ducking ตัวแก้ไขเสียงแบบหลายผู้เล่นบนเบราว์เซอร์ สิ่งสำคัญคือการออกแบบโมเดลข้อมูลให้ แมปกับโอเปอเรชันของ CRDT ได้อย่างเป็นธรรมชาติ
- ในกรณีอย่างการจัดลำดับรายการใหม่ ซึ่ง Automerge ยังไม่รับประกันพฤติกรรมที่ต้องการ จำเป็นต้องเขียน โค้ดในชั้นแอปพลิเคชัน เพื่อบังคับ invariant ที่เข้มงวดยิ่งขึ้นเอง
- ใจความสำคัญคือ การแก้ไขแบบร่วมมือกันเรียลไทม์ซึ่งเคยเป็นเวทมนตร์ระดับอุตสาหกรรม บัดนี้สามารถนำมาใช้ได้อย่างอิสระแม้กับแอปเล็กๆ สำหรับคนเพียงไม่กี่คน
เบื้องหลัง — โปรเจ็กต์ Ducking
- ช่วงหลายเดือนที่ผ่านมา ผู้เขียนได้สร้าง Ducking ซึ่งเป็น ตัวแก้ไขเสียงแบบหลายผู้เล่นบนเบราว์เซอร์ สำหรับพอดแคสต์ของพาร์ตเนอร์
- รู้สึกแปลกที่โลกของการตัดต่อเสียงยังคงติดอยู่กับแอปเดสก์ท็อปผู้ใช้คนเดียวอายุ 20 ปี และการส่งไฟล์ไปมาระหว่างกัน
- ในขณะที่คนหนึ่งกำลังตัดคลิป อีกคนก็ควรแก้ transcript หรือปรับค่า EQ ได้ด้วย ต้องการ workflow แบบร่วมมือกันคล้าย Google Docs หรือ Figma
- และยังต้องการเครื่องมือการทำงานร่วมกันสมัยใหม่ เช่น คอมเมนต์, ประวัติ, และการติดตามการเปลี่ยนแปลง
- บทความก่อนหน้านี้อธิบาย UI ที่มีเอกลักษณ์และโมเดลเลย์เอาต์เสียง ซึ่งช่วยให้ตัวแก้ไขสำหรับผู้ใช้คนเดียวดีขึ้น แต่สิ่งที่ต้องการจริงๆ คือ workflow ที่ร่วมมือกันได้มากกว่าเดิม
วิธีการทำงานของ Automerge
- ข้อมูลทั้งหมดของ Ducking ยกเว้น audio blob จะถูกเก็บไว้ใน เอกสาร Automerge
- แพตเทิร์นหลักมีหน้าตาคล้ายสิ่งที่นักพัฒนา React คุ้นเคย: ดึงข้อมูลด้วย hook แล้ว render จากนั้น dispatch คำขอเปลี่ยนแปลงแบบ async และเมื่อข้อมูลเปลี่ยน hook ก็จะ trigger การ re-render
- ตัวอย่างการใช้ hook
useDocument: รับเอกสารในรูปconst [doc, changeDoc] = useDocument<Episode>(docUrl)แล้วเมื่อค่า input เปลี่ยนก็อัปเดตด้วยchangeDoc((d) => { d.title = e.target.value })
- ตัวอย่างการใช้ hook
- โอเปอเรชันอัปเดตข้อมูลดูเหมือน imperative แต่ไม่เหมือน object และ array ของ JS ปกติ
- มีเมธอดน้อยกว่า, ไม่ mutate ทันที, และดักจับการเปลี่ยนแปลงเพื่อนำไปแปลงเป็น รายการใน changelist ของประวัติเอกสาร ด้วยตัวมันเอง
- Automerge ช่วยจัดการสิ่งที่ต้องการได้ในกรณีทั่วไป แต่ไม่ใช่เวทมนตร์ และ invariant ของมันก็ไม่ได้ตรงกับความหมายที่เราต้องการเสมอไป ดังนั้น การออกแบบโมเดลข้อมูลอย่างรอบคอบ จึงสำคัญ
- ควรทำให้การกระทำของผู้ใช้ที่มีความหมายส่วนใหญ่ตรงกับโอเปอเรชันเดี่ยวที่ Automerge มีให้
- และทำให้การกระทำของผู้ใช้ที่แยกจากกันแต่กระทบข้อมูลที่เกี่ยวข้องกัน สามารถถูกรวมได้อย่างเป็นธรรมชาติภายใต้มุมมอง invariant ของโอเปอเรชัน Automerge นั้น
- แยกให้ชัดระหว่างข้อมูล canonical ที่เก็บจริง กับข้อมูล derived ที่คำนวณขึ้นมา
การออกแบบข้อมูลสำหรับหลายผู้เล่น
- ในโมเดลข้อมูลของ Ducking clip คือหน้าต่างที่เล่นบางส่วนของแหล่งเสียงต้นฉบับที่เปลี่ยนแปลงไม่ได้ โดยรับผิดชอบช่วงการเล่น, การใช้เอฟเฟกต์, และการกินพื้นที่บนไทม์ไลน์
- เอฟเฟกต์ที่พบบ่อยที่สุดคือการให้คลิปปรับระดับเสียงของแหล่งเสียงต้นฉบับตามเวลา เพื่อทำ crossfade หรือลดเสียงรบกวน
- ตอนแรกแต่ละคลิปมีรายการ ระดับเสียงตามดัชนีเวลาโดยอ้างอิงจากจุดเริ่มต้นของคลิป แต่เกิดปัญหาเพราะการเปลี่ยนระดับเสียงส่วนใหญ่เกี่ยวกับเสียงต้นฉบับ ไม่ใช่คลิป
- ถ้าเลื่อนเวลาเริ่มของคลิปให้เร็วขึ้นนิดเดียว การเปลี่ยนระดับเสียงทั้งหมดจะไปมีผลกับคนละส่วนของเสียง
- การเขียนโค้ดให้อัปเดต timestamp ของระดับเสียงทั้งหมดทุกครั้งที่เวลาเริ่มคลิปเปลี่ยน เป็น ทางเลือกที่ไม่ดี
- หากผู้ร่วมงานสองคนแก้เวลาเริ่มคลิปพร้อมกัน แต่ละการแก้จะพ่วงทั้งเวลาเริ่มและการเปลี่ยน timestamp ของ volume automation ทั้งหมดไปด้วย
- Automerge ไม่รู้จัก ความสัมพันธ์เชิงเหตุ (causal relationship) ระหว่างการเปลี่ยนแปลงเหล่านั้น จึงอาจ merge ออกมาอย่างสับสน
- นี่คือปัญหาคลาสสิกเมื่อการกระทำที่เป็นหน่วยความหมายเดียว พยายามอัปเดตข้อมูลที่ persistent หลายส่วนในแบบเชิงเหตุที่ CRDT ไม่เข้าใจ
- ทางแก้คือย้ายข้อมูลเอฟเฟกต์เสียงจากคลิป ไปอิงกับ กรอบเวลาของเสียงต้นฉบับ แทน
- เมื่อเปลี่ยนจุดเริ่มหรือความยาวของคลิปก็ไม่ต้องอัปเดตอะไร ทำให้เมื่อผู้แก้ไขหลายคนเปลี่ยนเวลาเริ่ม, volume automation, หรือเอฟเฟกต์อื่นๆ พร้อมกัน ข้อมูลเหล่านั้นจะเป็นอิสระต่อกันและมีโอกาส merge ได้ถูกต้องมากกว่า
- ความต่างระหว่าง UI สำหรับผู้ใช้คนเดียวกับหลายผู้เล่น
- ใน UI ผู้ใช้คนเดียว อาจคงโมเดลข้อมูลเดิมไว้แล้วเพิ่มการคำนวณตอนเขียนข้อมูลให้ใช้งานได้
- แต่ใน UI แบบหลายผู้เล่น การย้ายโมเดลข้อมูลเกิดขึ้นบ่อยกว่ามาก เพื่อให้ข้อมูลที่เก็บถาวรทั้งหมดอยู่ในสถานะที่ ตั้งฉากกัน (orthogonal)
- แนวทางนี้ทำให้เริ่ม ชอบทำฝั่งเขียนให้ง่าย และย้ายภาระไปคำนวณฝั่งอ่าน อย่างชัดเจน เพื่อใช้ประโยชน์จากการ merge อัตโนมัติของ Automerge ให้เต็มที่
- คำแนะนำเรื่องการ migration รูปแบบข้อมูล
- ควรยอมรับตั้งแต่ต้นว่าระหว่างพัฒนาจะต้องมีการย้ายรูปแบบข้อมูล และควรใช้เวลาช่วงแรกฝึกทำไว้ล่วงหน้า เพื่อไม่ให้กลัว migration ใหญ่ครั้งแรก
- มีหลายแพตเทิร์น เช่น จัดการตอนอ่านบนไคลเอนต์ หรืออัปเกรดข้อมูลทั้งชุดบนเซิร์ฟเวอร์
- ถ้าหา invariant ที่สะดวกในการตรวจว่า ก่อนและหลัง migration เหมือนกันหรือไม่ งานจะง่ายขึ้นมาก
- ใน Ducking มีการ export เสียงของทุกโปรเจ็กต์ก่อนและหลัง migration แล้วตรวจด้วย audio fingerprint เพื่อยืนยันว่าไม่มีอะไรเปลี่ยน ทำให้ปล่อย schema change ใหญ่ๆ ได้อย่างไม่กังวล
การทำ list reordering
- บางครั้งจำเป็นต้องเขียน โค้ดระดับแอปพลิเคชัน เอง เพื่อให้ได้ invariant ที่เข้มกว่า guarantee ที่ Automerge มีให้
- ปัญหานี้เกิดขึ้นตอนสร้าง magnetic timeline ของ Ducking (รายการคลิปที่เรียงลำดับเพื่อเล่น)
- Automerge มีโอเปอเรชัน array สำหรับลบและแทรกรายการตาม index แต่ไม่มีโอเปอเรชัน re-order แบบ atomic สำหรับย้ายรายการเดิม
- มีแนวทางแก้ที่เป็นที่รู้จักอยู่แล้ว
- Martin Kleppmann มีงานวิจัยเกี่ยวกับโอเปอเรชันจัดลำดับ list ใหม่แบบ atomic
- และร่วมกับ Liangrun Da ออกบทความ "Extending JSON CRDTs with Move Operations"
- ยังมี draft PR สำหรับเพิ่มความสามารถนี้เข้า Automerge แต่ยังไม่ถูกรวม
- ปัญหาของวิธี reorder แบบง่าย
- คือการลบ object จาก index ปัจจุบัน แล้วเพิ่มกลับเข้าไปที่ index ปลายทาง
- แม้รวม invariant ของสองโอเปอเรชันนี้เข้าด้วยกัน ก็ยังไม่รับประกัน invariant ที่ต้องการคือ "เมื่อมีการ reorder พร้อมกันหลายครั้ง object จะอยู่ในรายการ เพียงครั้งเดียวอย่างถูกต้อง"
- ถ้ามี delete และ insert พร้อมกันหลายชุด object อาจไปโผล่หลายตำแหน่งใน list ได้ (ถ้า Alice และ Bob ต่างย้าย B ด้วย delete+insert การลบทั้งสองจะรวมเป็น tombstone เดียว แต่การแทรกทั้งสองจะสร้าง element ใหม่คนละตัวและรอดทั้งคู่ ทำให้ B โผล่มาสองครั้ง)
- วิธีบังคับ invariant "มีเพียงครั้งเดียว" ที่ระดับแอปพลิเคชัน
- ให้ semantic id กับคลิปตอนถูกแทรกลงไทม์ไลน์
- เวลา reorder ก็ trigger โอเปอเรชันลบและแทรกแบบเดิม
- ตอนอ่าน แอปพลิเคชันจะสแกนหาข้อมูลซ้ำที่มี semantic id เดียวกัน เลือกรายการแรกที่ยังไม่ถูกลบแบบ arbitrary แล้วมองข้ามที่เหลือ
- วิธีนี้ทำให้ object ปรากฏในรายการเพียงครั้งเดียว และผู้อ่านทุกคนจะได้สถานะสุดท้ายแบบเดียวกันเสมอ
- การ reorder list เป็นโอเปอเรชันเดียวใน Ducking ที่ Automerge ยังไม่มี และคาดว่าเมื่อ PR ถูกรวมแล้ว logic ระดับแอปพลิเคชันนี้ก็จะไม่จำเป็นอีกต่อไป
ประวัติเอกสาร (Document history)
- UI แบบหลายผู้เล่นที่ดีต้องมี เครื่องมือจัดการประวัติ เพราะผู้ร่วมงานต้องการดูว่ามีอะไรเปลี่ยนไปตอนที่ตนไม่อยู่, ทำ diff comments, เปรียบเทียบเวอร์ชันเก่า และ rollback ได้
- Automerge ติดตามประวัติเวอร์ชันของเอกสาร และมี primitive ที่ดีมากสำหรับจัดการประวัติและการเปรียบเทียบ
- แต่การจะเปิดเผยข้อมูลนั้นอย่างไร และจะนำเสนอแนวคิดใดให้ผู้ใช้เห็น ยังเป็นหน้าที่ของนักพัฒนาแอปพลิเคชัน
- แนะนำ Patchwork lab notes ของ Ink & Switch
- โดยเฉพาะงานที่เปิดเผย branch ให้ผู้ใช้เห็น และงานเกี่ยวกับ universal comments ที่น่าสนใจมาก
- Ducking ลงเอยด้วยโมเดลการร่วมมือและประวัติที่ค่อนข้างเรียบง่าย
- เป็นประวัติเวอร์ชันเชิงเส้นที่มี checkpoint ตั้งชื่อได้เอง โดย checkpoint เป็นทั้งหน่วยของการจัดกลุ่มการเปลี่ยนแปลง และหน่วยของการอภิปราย, diff, และ rollback
- มี comment thread ที่ผูกกับจุดใดจุดหนึ่งของเสียง, บริเวณหนึ่งของ transcript, หรือ version checkpoint ก็ได้
- ตอนนี้ยังไม่มีเหตุผลมากพอที่จะเพิ่ม branch แต่ก็กล่าวไว้ว่าน่าจะมีประโยชน์ในอนาคต
ข้อความและ marks
- งาน rich text เป็นปัญหาที่ชวนปวดหัวมาก โดยเฉพาะเมื่อพยายามซ้อน logic แบบกำหนดเองลงบนข้อความที่แก้ไขได้
- แนะนำ งานวิจัย Peritext ซึ่งอธิบายความยากของ rich text และซอฟต์แวร์แบบหลายผู้เล่นโดยรวม
- schema rich text ของ Automerge มี marks ซึ่งเป็นคำอธิบายประกอบที่ผูกกับช่วงข้อความ และยังคงความสอดคล้องได้แม้มีการแก้ข้อความ
- ปกติใช้กับการจัดรูปแบบอย่างตัวหนาและตัวเอียง แต่ก็สามารถสร้าง mark แบบกำหนดเองเฉพาะแอปได้เช่นกัน
- การใช้ custom mark ใน Ducking มีสองแบบ
- ติดตามช่วงของ transcript ที่เป็นเป้าหมายของ comment thread
- ติดตาม timestamp ของคำใน transcript โดยยังแก้ไขข้อความได้ตามปกติ
- บริการถอดเสียงจะเก็บ transcript ลงใน Automerge เป็น richtext object ที่มี mark ข้อมูล timing ของแต่ละคำ
- ถ้าแก้แค่คำเดียวจากการพิมพ์ผิด mark จะยังคงอยู่ ทำให้ข้อมูลเวลาเก็บครบทั้งหมด
- ถ้าแก้ทั้งประโยค mark บางส่วนตรงกลางอาจหายไป แต่ mark ต้นและท้ายประโยคยังอยู่ จึงยังมีข้อมูลเวลาโดยประมาณขั้นต่ำ
- ข้อจำกัดอย่างหนึ่งของ marks คือ datum ต้องเป็นค่าเรียบง่าย (โดยทั่วไปคือ string) และไม่ถูก merge แบบหลายผู้เล่น
- ข้อมูลเล็กๆ และไม่เปลี่ยน เช่น timing ของ transcript จะถูก serialize JSON เป็น string
- ข้อมูลที่ซับซ้อนหรือเปลี่ยนได้มากกว่า เช่น comment thread จะเก็บ เฉพาะ id ใน mark และเก็บข้อมูลจริงไว้ที่อื่นในเอกสาร
- marks จึงเป็นรากฐานที่ดีเยี่ยมสำหรับต่อยอดฟีเจอร์ระดับแอปพลิเคชันบน rich text แบบหลายผู้เล่น
บทความถัดไป — โครงสร้างซีรีส์
- บทความนี้เป็นตอนที่ 2 ของซีรีส์ 3 ตอนเกี่ยวกับการสร้าง Ducking
- ตอนที่ 1: อธิบายการออกแบบ UI ที่มีเอกลักษณ์ของซอฟต์แวร์
- ตอนที่ 2 (บทความนี้): แนะนำให้ลองพิจารณา Automerge และชี้ให้เห็นว่าการสร้างโปรเจ็กต์หลายผู้เล่นสำหรับงานอดิเรกนั้นเป็นไปได้
- ตอนที่ 3 ซึ่งจะเป็นตอนสุดท้าย: ทบทวนประสบการณ์ในการสร้าง Ducking
- สิ่งที่กล่าวถึงสำหรับตอนที่ 3
- ใช้ การช่วยเหลือจาก LLM ไม่ใช่เพื่อเร่งงานให้หนักขึ้น แต่เพื่อให้มีเวลาสำหรับการสเก็ตช์และการนอนเล่นบนเปลญวนมากขึ้น
- ความสุขของการสร้าง ซอฟต์แวร์แบบ narrowcast ที่มีไว้เพื่อทำให้คนเพียงไม่กี่คนพอใจ
คำถามที่คาดว่าจะถูกถาม
แล้วข้อมูลเสียงล่ะ?
- ข้อมูลหลายผู้เล่นทั้งหมดถูกเก็บใน Automerge แต่ audio blob ต้นฉบับไม่ได้เก็บใน Automerge เพราะต้องแยกจัดการเพื่อให้เล่นได้เร็ว
- เป้าหมายคือให้ผู้ร่วมงานใหม่เริ่มฟังและแก้ไขได้ภายใน 4 วินาที หลังโหลดหน้า ซึ่งเร็วกว่าการเปิดแอปเดสก์ท็อป และเร็วกว่าการดาวน์โหลดไฟล์ทั้งโปรเจ็กต์มาก
- ตอนหนึ่งยาว 1 ชั่วโมง อาจพึ่งพาเสียงรวม ราว 1 กิกะไบต์ ซึ่งมาจากการอัดเสียงคุณภาพสตูดิโอ 4 ชั่วโมง บวกเอฟเฟกต์และดนตรีประกอบ
- สิ่งที่บริการเสียงทำตอนอัปโหลด เพื่อให้ cold start เร็ว
- สำรองไฟล์เสียงต้นฉบับ
- ถอดเสียงพูดเพื่อใช้ในมุมมอง transcript
- สร้าง waveform สำหรับมุมมอง timeline
- slice เสียงเป็นหน้าต่างสั้นๆ เพื่อให้ถ้าใช้เพียง 1 นาทีจากไฟล์อัด 40 นาที ไคลเอนต์ส่วนใหญ่ก็จะต้องรับมาแค่ชิ้นเล็กๆ หนึ่งหรือสองชิ้น
- transcode ชิ้นเหล่านั้นเป็นฟอร์แมตบีบอัด เพื่อให้มีเวอร์ชัน lossy ที่เล่นได้ทันที ขณะที่ไฟล์เสียงคุณภาพสูงดาวน์โหลดอยู่เบื้องหลัง
- ชั้นข้อมูลของ UI จะจัดการโหลดทั้งข้อมูลเวอร์ชันเร็วที่ต้องใช้ทันทีตามเจตนาของผู้ใช้ และไฟล์เสียงคุณภาพสูงฉบับเต็มของส่วนที่ถูกใช้งานจริง
- IndexedDB API ของเบราว์เซอร์มีประโยชน์มากสำหรับการทำแคชหลายชั้นและการเก็บแบบ content-addressable ใช้แบบมี auto eviction คือถ้าใช้ก็จะอยู่ ถ้าไม่ใช้ก็จะหายไป
- เมื่อผ่านขั้นตอนทั้งหมดนี้และมีการแคชในเครื่องแล้ว ส่วน UI ที่เหลือก็สามารถสมมติได้ว่ามี random access ที่รวดเร็วต่อข้อมูลเสียง และโฟกัสกับ workflow การตัดต่อได้เลย
ทำไมถึงสร้างเป็น UI แบบเซิร์ฟเวอร์+เบราว์เซอร์ แทนที่จะเป็น local-first app
- ผู้เขียนชอบ แอปแบบ local-first อย่าง Obsidian ที่ทำงานได้สมบูรณ์โดยไม่ต้องพึ่งเซิร์ฟเวอร์ โดยเฉพาะแบบที่มีทางออกที่เชื่อถือได้ พร้อมประสบการณ์คลาวด์แบบเสียเงินควบคู่กัน
- ตอนแรกเริ่มจากตัวเลือก แอป Tauri ที่เก็บข้อมูลใน local filesystem และมี server sync แบบเลือกใช้
- สร้าง UI บนอินเทอร์เฟซข้อมูลที่ไม่ว่าจะมาจากเซิร์ฟเวอร์หรือแอปในเครื่องก็รองรับได้
- เป็นมาตรการป้องกันไม่ให้ในอนาคต เงินทุนรูปแบบใดมาล่อลวงให้ทำแอปให้ monetization มากขึ้นด้วยการ lock-in
- ต่อมาพบว่าสิ่งนี้ไม่ใช่ SaaS แต่เป็นของที่อยากใช้กับพาร์ตเนอร์และเพื่อนไม่กี่คน
- แรงจูงใจในการใช้งานในทางผิดจึงหายไป ต้นทุนการดูแลระยะยาวก็ตํ่า จึงตัดสินใจทำด้วยวิธีที่ง่ายที่สุด
- พอทำ cold start ได้ราว 3 วินาที ก็ไม่มีใครอยากเสียเวลากับการดาวน์โหลดและติดตั้ง native app อีก
- ผู้เขียนหวังว่าแอปเสียงจะกระโดดจากโลกเดสก์ท็อปอย่างเดียวในปัจจุบัน ไปสู่โลกแบบ local-first ที่มีตัวเลือกซิงก์ได้โดยตรง โดยข้ามช่วงกลาง 10–20 ปีของ SaaS lock-in ไปเลย
Automerge ปลอดภัยและรองรับ web-scale ไหม? ควรใช้กับสตาร์ตอัปหรือเปล่า?
- คำตอบคือไม่รู้ และตอบแบบ อย่างมีความสุข ได้เลย ซึ่งไม่ได้หมายถึงการปฏิเสธ แต่หมายถึงไม่รู้จริงๆ
- ตอนที่เริ่มทำงาน การแก้ไขแบบหลายผู้เล่นเรียลไทม์ที่ไม่มี conflict ยังเหมือนเวทมนตร์ และเมื่อ 10 ปีก่อน แม้จะมีวิธีแก้สำหรับปัญหาบางประเภทแล้ว ก็ยังต้องใช้ทีมที่มีทุนสนับสนุนและความเชี่ยวชาญหลายด้าน
- แต่วันนี้แค่ติดตั้ง dependency หนึ่งตัว ก็สามารถสร้าง UI ได้อย่างค่อนข้างเป็นธรรมชาติและร่วมงานกับเพื่อนแบบเรียลไทม์ได้แล้ว
- ด้านความปลอดภัย ตอนนี้ Ducking ป้องกันด้วยการเข้าถึงเครือข่ายแบบจำกัด และมีขั้นตอน authorization ตอนสร้างการเชื่อมต่อ websocket กับเซิร์ฟเวอร์ Automerge
- ผู้ใช้จะไม่สามารถค้นพบหรือแก้ไขโปรเจ็กต์ที่ไม่ได้รับเชิญได้
- การผูกผู้ใช้เข้ากับการแก้ไขและคอมเมนต์ยังปลอดภัยเพียงบางส่วน และอาศัยสมมติฐานว่าเพื่อนๆ จะไม่ทำตัวไม่ดี
- เรื่อง สิทธิ์แบบละเอียด เช่น คอมเมนต์ได้แต่แก้ไขไม่ได้, แก้ไขได้แค่บางส่วนของโปรเจ็กต์, หรือควบคุมการค้นพบโปรเจ็กต์ จำเป็นต้องออกแบบอย่างระมัดระวัง
- Keyhive ที่ Ink & Switch กำลังพัฒนา ให้โมเดลควบคุมการเข้าถึงแบบ capability-based ที่ปลอดภัยเชิงเข้ารหัส
- น่าจะช่วยให้แชร์แอป Automerge ต่อสาธารณะกับผู้ใช้ที่ไม่น่าเชื่อถือได้ง่ายขึ้น แต่ตอนนี้ยังไม่พร้อม
Automerge ดีกว่าหรือไม่?
- มีทางเลือกอื่นในสายนี้คือ Yjs แต่ผู้เขียนไม่อาจประเมินแทนได้ว่าอะไรเหมาะที่สุด
- คำแนะนำที่ไม่เคยเปลี่ยนคือ
- คิดกับปัญหาให้ลึก, ลองคำนวณคร่าวๆ ถึงข้อจำกัดที่อาจเจอ, สร้าง prototype ด้วยหลายแนวทาง, และยอมรับอย่างซื่อสัตย์ว่าบางทีปัญหาของคุณอาจไม่ได้ยากขนาดนั้นจนต้องใช้วิธีที่ล้ำและซับซ้อนที่สุด
- สำหรับ Ducking การทำ prototype อย่างรวดเร็วและสำรวจเอกสารช่วยยืนยันว่า Automerge โตเต็มที่พอและมีประสิทธิภาพดี สำหรับงานนี้
- ที่สำคัญยิ่งกว่านั้นคือผู้เขียนชอบ ระบบนิเวศของ Ink & Switch ในเชิงสุนทรียะ
- เพราะ Automerge ไม่ได้เป็นแค่เอนจินซิงก์และจัดการเวอร์ชัน แต่เป็นส่วนหนึ่งของวิสัยทัศน์ที่ใหญ่กว่า ในการทำให้ซอฟต์แวร์ปลอดภัยขึ้น, ร่วมมือกันได้มากขึ้น, ยืดหยุ่นขึ้น, สนุกขึ้น และมีความเป็นส่วนตัวมากขึ้น
- และหวังว่า Keyhive กับโครงการอื่นๆ จะประสบความสำเร็จ จนได้เห็นซอฟต์แวร์เล็กๆ แต่มีมนตร์ขลังสำหรับคนเพียงไม่กี่คนแพร่หลายมากขึ้น
ยังไม่มีความคิดเห็น