1 คะแนน โดย GN⁺ 2023-10-27 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Flawless คือ เอนจินการรันการคำนวณที่ทนทาน ซึ่งช่วยให้โค้ดรันจนจบได้แม้เกิดความขัดข้อง
  • เวิร์กโฟลว์เขียนเป็น ฟังก์ชัน Rust ปกติ แต่จะไม่คอมไพล์เป็นโค้ดเนทีฟ แต่คอมไพล์เป็น WebAssembly เพื่อรันในสภาพแวดล้อมที่กำหนดผลลัพธ์ได้แน่นอน
  • ผลข้างเคียงแบบไม่กำหนดแน่นอน จะเกิดขึ้นเฉพาะจุดที่โค้ดติดต่อกับโลกภายนอก เช่น การส่งคำขอ HTTP หรือการสร้างเลขสุ่ม และ Flawless จะบันทึกสิ่งเหล่านี้ไว้ในล็อก
  • หากการรันถูกขัดจังหวะ จะใช้ล็อกที่บันทึกไว้เพื่อไล่รันกลับไปให้ถึงสถานะเดิม และจะไม่ทำซ้ำผลข้างเคียงที่เคยทำไปแล้ว
  • นักพัฒนาสามารถแสดงสถานะถาวรผ่านโค้ดและตัวแปรภายในได้ โดยไม่ต้องจำลองสถานะทั้งหมดลงในฐานข้อมูลเอง ทำให้หลังรีสตาร์ตเซิร์ฟเวอร์ก็สามารถรันต่อจากจุดที่หยุดไว้ได้

โมเดลการรันที่แสดงสถานะถาวรด้วยโค้ด

  • Flawless คือเอนจิน การคำนวณที่ทนทาน ซึ่งทำให้โค้ดรันไปจนเสร็จแม้เกิดความขัดข้องของฮาร์ดแวร์หรือซอฟต์แวร์
  • ประสบการณ์ผู้ใช้ที่ซับซ้อนต้องการ UI และสถานะที่ซับซ้อน แต่การจำลองสถานะทั้งหมดไว้ในฐานข้อมูลโดยตรงเป็นเรื่องยาก
  • แอปพลิเคชันสมัยใหม่จำเป็นต้องมี การจัดเก็บแบบถาวร เพื่อไม่ให้ผู้ใช้สูญเสียความคืบหน้าแม้เผลอรีเฟรชหน้าเว็บ
  • Flawless มีเป้าหมายให้สามารถจำลองสถานะถาวรด้วยโค้ดและตัวแปรภายใน เพื่อช่วยแสดงพฤติกรรมที่ซับซ้อนของแอปพลิเคชันได้ง่ายขึ้น

การรันบน WebAssembly และการกู้คืนจากความขัดข้อง

  • เวิร์กโฟลว์เขียนเป็น ฟังก์ชัน Rust ปกติ และสามารถมีตรรกะใด ๆ ก็ได้
  • ฟังก์ชันจะถูกคอมไพล์เป็น WebAssembly แทนโค้ดเนทีฟ และรันในสภาพแวดล้อมที่กำหนดผลลัพธ์ได้แน่นอนอย่างสมบูรณ์
  • ความไม่กำหนดแน่นอนจะถูกนำเข้ามาเฉพาะเมื่อโต้ตอบกับโลกภายนอก เช่น การส่งคำขอ HTTP หรือการสร้างเลขสุ่ม
  • Flawless จะบันทึก ล็อกผลข้างเคียงแบบไม่กำหนดแน่นอน เหล่านี้ไว้เพื่อใช้ในการกู้คืน
    • หากการรันเวิร์กโฟลว์ถูกขัดจังหวะ จะรันใหม่เพื่อไล่ตามไปจนถึงสถานะเดียวกัน
    • ผลข้างเคียงที่ทำไปแล้วจะไม่ถูกทำซ้ำ
    • ลดปริมาณข้อมูลที่ต้องจัดเก็บให้เหลือน้อยที่สุด และส่วนที่เหลือจะคำนวณใหม่ตามความจำเป็นเมื่อเกิดความขัดข้อง
  • โมเดลการรันนี้ช่วยให้สังเกตพฤติกรรมของทั้งระบบได้ดียิ่งขึ้น
    • สามารถวิเคราะห์เส้นทางการรันที่แม่นยำของเวิร์กโฟลว์ที่เสร็จแล้วหรือที่กำลังรันอยู่ได้
    • สภาพแวดล้อมการรันแบบกำหนดผลลัพธ์แน่นอนช่วยให้จัดการบั๊กที่ทำซ้ำได้ยากได้ง่ายขึ้น
  • นักพัฒนาสามารถลดภาระเรื่องการจัดเก็บสถานะ และมุ่งเน้นการเขียน ตรรกะทางธุรกิจ ได้มากขึ้น
  • แม้ต้องรีสตาร์ตเซิร์ฟเวอร์เพื่อบำรุงรักษา เมื่อเริ่มเอนจิน Flawless ใหม่ เวิร์กโฟลว์ก็จะรันต่อจากจุดที่หยุดไว้
  • ณ วันที่ 9 ธันวาคม 2024 มี Flawless Beta 3 ให้ใช้งานแล้ว

1 ความคิดเห็น

 
GN⁺ 2023-10-27
ความคิดเห็นจาก Hacker News
  • สงสัยว่าจะจัดการ การจัดการเวอร์ชันของเวิร์กโฟลว์ อย่างไร มองว่านี่เป็นปัญหาที่ยากที่สุดในระบบอย่าง Temporal/Cadence

    • ผู้เขียนเองครับ สำหรับเวิร์กโฟลว์ที่รันนาน หรือแทบจะรันไปตลอด ผมคิดว่าวิธีที่เข้าใจง่ายที่สุดคือการอนุญาตให้ อัปเกรดแบบไม่หยุดให้บริการ
      การอัปเกรดจะสำเร็จก็ต่อเมื่อโค้ดใหม่สามารถ replay บันทึก side effect เดิมได้อย่างถูกต้องเท่านั้น คือให้โค้ดใหม่ไล่ตามจากประวัติเดิม พอไล่ทันแล้วก็รันต่อไปตามนั้น
      ถ้าโค้ดใหม่เบี่ยงเบนจากประวัติเดิม การอัปเกรดจะล้มเหลวและย้อนกลับไปใช้โค้ดก่อนหน้า ในกรณีนี้ต้องให้คนเข้ามาตรวจสอบว่าเกิดอะไรผิดพลาด
      มีแนวทางอื่นด้วย แต่ผมมองว่าวิธีนี้เรียบง่ายที่สุดสำหรับการทำความเข้าใจและใช้งานจริง ระหว่างพัฒนาก็สามารถใช้ log เดิมมาทดสอบได้ว่าโค้ดแยกทางหรือไม่
    • สงสัยว่าหมายถึงปัญหาที่มีเวิร์กโฟลว์ที่ยังมีชีวิตและกำลังดำเนินอยู่ แล้วต้องการอัปเดตเวิร์กโฟลว์โดยไม่ทำให้มันพังหรือเปล่า
      และสงสัยด้วยว่าอยากคงหลายเวอร์ชันไว้พร้อมกัน หรือว่าต้องการวิธี migrate งานที่กำลังดำเนินอยู่ไปยัง นิยามเวิร์กโฟลว์ ล่าสุด
    • ใช่แล้ว ส่วนนั้นเป็นสิ่งที่ Conductor จัดการแทนได้ดี
  • รู้สึกว่าสายงานของเรากำลังค่อย ๆ เข้าใกล้สถาปัตยกรรมหรือการแพทย์มากขึ้น เทคโนโลยีแบบนี้ช่วยให้เราพ้นจากขั้นลองเล่นไปสู่ วัฒนธรรมวิศวกรรม ที่จริงจังได้
    ถามสั้น ๆ คือ ในระบบแบบนี้จะป้องกันไม่ให้ ผลของการโจมตี DoS ถูกทำให้คงอยู่ถาวร ได้อย่างไร

    • คำว่า “เข้าใกล้สถาปัตยกรรมและการแพทย์” อ่านแล้วเหมือนคำพูดไร้สาระที่แมชชีนเลิร์นนิงสร้างขึ้น
      สถาปัตยกรรมใกล้เคียงกับการจัดการความเห็นเชิงอัตวิสัยภายใต้ข้อจำกัดด้านกฎระเบียบ ส่วนการแพทย์คือความรู้เชิงประจักษ์ที่ตรวจสอบด้วยการทดลอง ทั้งสองอย่างดูไม่ค่อยคล้ายวิศวกรรม
    • ทั้ง สถาปัตยกรรม และ การแพทย์ ไม่ใช่สาขาวิศวกรรม เลยไม่ค่อยเข้าใจว่าการเข้าใกล้สิ่งเหล่านั้นจะเป็นเส้นทางไปสู่วัฒนธรรมวิศวกรรมได้อย่างไร
      สถาปัตยกรรมใกล้เคียงกับรูปแบบหนึ่งของศิลปะ และภาควิชาสถาปัตยกรรมในมหาวิทยาลัยก็มักอยู่ในคณะศิลปะ
      การแพทย์เป็นวิทยาศาสตร์ประยุกต์เหมือนวิศวกรรม แต่ก็ไม่ใช่สาขาวิศวกรรมโดยตัวมันเอง
  • สงสัยว่า ความเป็น deterministic นี้ขยายไปถึงการคำนวณแบบ floating-point ด้วยหรือไม่
    ในเกมมัลติเพลเยอร์ สถานะฝั่งไคลเอนต์จะค่อย ๆ drift จากการคำนวณ floating-point จนต้องซิงก์กับสถานะเซิร์ฟเวอร์ใหม่เป็นระยะ ๆ และในอดีตนี่เป็นจุดที่ค่อนข้างปวดหัว

    • ตอนผมทำคอมไพเลอร์ WASM แหล่งเดียวของความไม่ deterministic ที่เกี่ยวกับ floating-point คือ การแทนค่า NaN เป็นไบต์ที่แน่นอน เท่านั้น คณิตศาสตร์ floating-point เองเป็น deterministic
      ดู https://webassembly.org/docs/faq/#why-is-there-no-fast-math-... และ https://github.com/WebAssembly/design/blob/main/Nondetermini...
    • นั่นน่าจะใกล้เคียงกับปัญหาที่ GPU ใช้ลูกเล่นเพื่อให้เร็วขึ้นมากกว่า
      https://asawicki.info/news_1741_myths_about_floating-point_n...
      เมื่อก่อนผลลัพธ์จาก CPU ก็อาจต่างกันได้ตาม execution path ดูทวีตในบทความ
    • สงสัยว่าการซิงก์ โครงสร้างเลขขนาดใหญ่ แทน f64 จะเป็นตัวเลือกได้ไหม หรือว่าไม่สมจริงในแง่ความซับซ้อนและขนาด
  • สงสัยว่าสถานะของ side effect ถูกเก็บไว้ที่ไหน เช่น ถ้ามี AWS Lambda ที่อยากทำให้เป็น idempotent, Lambda ไม่มี local storage ที่คงอยู่ระหว่างการรัน
    ถ้าไม่ได้ mount อะไรอย่าง EBS volume สถานะก็จะไม่คงอยู่ ดังนั้นมองได้ไหมว่าสถานะจะเก็บใน DB

    • นั่นน่าจะเป็นส่วนที่ต้องจ่ายเงินใช้เมื่อผลิตภัณฑ์เปิดตัว
  • ชอบ แอนิเมชัน ที่แสดงหลักการสำคัญและวิธีทำงาน ทำออกมาดีมากจริง ๆ

    • ขอบคุณครับ ผมเขียนเองด้วย HTML, CSS, JavaScript ล้วน ๆ และใส่ความพยายามกับความรักลงไปเยอะมาก
      โค้ดอาจไม่สวยมาก แต่ implementation ค่อนข้างตรงไปตรงมา ถ้าอยากดู อยู่ที่นี่: https://flawless.dev/js/how-does-it-work-animation.js
    • ตอนเรียก external endpoint จุดที่พังเพราะ timeout เกิดขึ้นบ่อยกว่ามาก เลยอยากเห็นภาพตอนล้มเหลวใน ขั้นตอนการรัน HTTP ด้วย
  • ดูน่าสนใจ แต่สงสัยว่าวิธีทำเครื่องหมายว่าฟังก์ชัน มี side effect จะทำให้ใช้งานโดยไม่พลาดได้ง่ายแค่ไหน
    ในตัวอย่าง สมมติว่าการสร้างเลขสุ่มเป็น side effect เพราะมาจากตัวสร้างเลขสุ่มที่ flawless ให้มา แล้วถ้าเป็นฟังก์ชัน Rust ปกติจะทำได้ไหม
    คิดว่าน่าจะมี test harness ให้ developer ตรวจสอบเวิร์กโฟลว์ด้วย

    • ผู้เขียน flawless ครับ การใช้ WebAssembly ทำให้ค่อนข้างปลอดภัยโดยพื้นฐาน
      WebAssembly บังคับให้ประกาศ host call ภายในโมดูลอย่างชัดเจน ถ้าพยายามใช้ host call อื่นที่ flawless ไม่ได้ให้ไว้ ก็จะ instantiate โมดูลไม่ได้
      ใน ecosystem ของ WebAssembly ก็มีงานมาตรฐานหลายอย่างกำลังดำเนินอยู่ เช่น ถ้าใช้ crate rand ของ Rust แล้วคอมไพล์เป็น WebAssembly การสร้างเลขสุ่มจะใช้ฟังก์ชัน host ของ WASI
      ระหว่างรอให้ wasi, wasi-http ฯลฯ เป็นมาตรฐาน ตอนนี้จึง expose interface ของตัวเองไปก่อน
      แน่นอนว่ามีข้อเสียใหญ่ด้วย ไม่ใช่โค้ด Rust ทั้งหมดจะคอมไพล์เป็น WebAssembly ได้ แต่ผมมองว่า แนวทางปฏิเสธเป็นค่าเริ่มต้น ที่รับประกันว่า side effect ที่ไม่ได้ตั้งใจจะไม่เกิดขึ้นเลยนั้นดีกว่า
    • ดูจากทั้งตัวสร้างเลขสุ่มและ HTTP request ที่อยู่ใต้ namespace flawless แล้ว น่าจะเป็นการให้ใช้สิ่งคล้าย std::flawless แทนการเปิดให้เข้าถึง ecosystem Rust ทั้งหมด
      harness น่าจะแก้ปัญหาส่วนใหญ่ได้ แต่ก็สงสัยว่าจะ map ฟีเจอร์ได้มากแค่ไหน
      เท่าที่เห็นตอนนี้ดูใกล้เคียงกับ scripting runtime ที่ใช้ Rust มากกว่า
  • ดูเหมือนเป็น ทางเลือกแทน Temporal สำหรับ Rust ที่ใช้ WASM เป็นรันไทม์ ชอบนะ
    ผมเป็นผู้ก่อตั้ง windmill.dev และเราก็ทำเอนจินแบบ durable ที่เขียนด้วย Rust เหมือนกัน เพียงแต่มันสง่างามน้อยกว่ามาก เราแบ่งเวิร์กโฟลว์ออกเป็นขั้นตอนที่ชัดเจนใน Python/TypeScript/Go/Bash และถ้าต้องการกลับมาทำต่อจากขั้นตอนที่ยังไม่เสร็จ ก็เริ่มใหม่จากขั้นตอนสุดท้าย พร้อมบันทึกผลลัพธ์ของแต่ละขั้นอย่างถาวรลงใน jsonb ของ Postgres DB
    กรณีใช้งานต่างกันชัดเจน และ flawless ดูเบามากตามที่เว็บไซต์บอก จนน่าจะใช้โมเดลสถานะของโฟลว์ UI และสเกลได้ถึงหลักล้านบนเซิร์ฟเวอร์ขนาดเล็ก
    ยอดเยี่ยมมาก หวังว่าสักวัน Rust จะขับเคลื่อน ระบบแบบกระจาย ทั้งหมด

  • “โปรแกรม concurrent ที่ซับซ้อนพอซึ่งเขียนด้วยภาษาอื่น จะมี การอิมพลีเมนต์ Erlang ครึ่งใบที่บั๊กเยอะและช้า ตามสเปกไม่เป็นทางการแบบแก้ขัดอยู่ข้างใน” — กฎข้อแรกของการเขียนโปรแกรมของ Virding

    • เป้าหมายของ Flawless ดูเหมือนจะเป็นการบันทึกสถานะกลางทางของเวิร์กโฟลว์ใดๆ แล้วเมื่อเกิดความล้มเหลวก็เริ่มใหม่จากจุดกลางทางนั้น
      สิ่งนี้ค่อนข้างต่างจาก Erlang มาก Erlang ถูกสร้างขึ้นหลักๆ เพื่อพัฒนาซอฟต์แวร์ได้แม้ในช่วงที่มีแค่อุปกรณ์ต้นแบบที่มีปัญหาฮาร์ดแวร์มากมาย
      สำหรับผม สองแนวทางนี้ดูเหมือนอยู่คนละขั้ว Flawless อาจติดอยู่ในลูปเพื่อพยายามทำเวิร์กโฟลว์ที่แครชกลางทางให้จบ แต่ Erlang พร้อมจะทิ้งทราฟฟิก 50% ที่ไปเหยียบบั๊กฮาร์ดแวร์อย่างเต็มใจ
    • บล็อกโพสต์แรกกล่าวถึง Erlang/OTP: https://flawless.dev/essays/when-letting-it-crash-is-not-eno...
    • เรื่องนี้ดูไม่ได้แก้ปัญหาเดียวกับ Erlang เลย
      Erlang แก้ปัญหาโดยแทบกำจัดสถานะถาวรออกไป สถานะแทบทั้งหมดอยู่ในที่อย่างคิวข้อความหรือ DB ภายนอก
      Flawless ดูเหมือนแก้ปัญหาด้วยเทคนิคที่คล้ายกับ filesystem journaling แต่ก็ไม่เหมือนกันทั้งหมด คือเป็นการบันทึกไว้ตอนทำ side effect
      filesystem journaling มีไว้เพื่อรันซ้ำหลังแครช แต่กรณีนี้มีไว้เพื่อทำให้ไม่จำเป็นต้องรันซ้ำ
      ยังไม่ชัดเจนว่าจะเหมาะกับโดเมนไหนแค่ไหน แต่ดูเหมือนจะไม่ได้ทับซ้อนกับโดเมนที่ Erlang เหมาะสมอย่างสมบูรณ์
    • https://codesync.global/media/erlangrt-a-beam-vm-reimplement...
    • ถ้าอย่างนั้น สิ่งที่โปรแกรมบั๊กเยอะตามสเปกไม่เป็นทางการต้องมีเพื่อทำได้เกินความคาดหวัง ก็คือ แค่ต้องเร็ว
  • เจ๋งมาก ใน Ambient ซึ่งเป็นรันไทม์เกมแบบ WASM ก็มีปัญหาคล้ายกัน มีโปรเซสที่แข่งขันกันและอาจต้อง retry การโต้ตอบกัน แนวทางที่แสดงตรงนี้เลยน่าสนใจ
    แต่สงสัยว่ามีความสัมพันธ์กับ Lunatic อย่างไร Lunatic ยังพัฒนาต่ออยู่ไหม อันนี้เป็นโปรเจกต์ข้างๆ หรือว่าแยกกันโดยสิ้นเชิง?
    https://lunatic.solutions/

    • สังเกตได้ดี อันนี้สร้างโดย Bernard Kolobara ซีอีโอและผู้ร่วมก่อตั้งของ Lunatic
      https://kolobara.com
  • “ลองจินตนาการว่า เมื่อเริ่มการคำนวณใดๆ แล้ว ระบบรับประกันว่าจะรันจนเสร็จ และงานทุกอย่างจะถูกทำอย่างถูกต้องหนึ่งครั้งพอดี”
    สงสัยว่ารับประกันได้อย่างไร การส่งแบบ exactly-once ในระบบแบบกระจายเป็นไปไม่ได้ไม่ใช่หรือ?

    • ถ้าใช้ idempotency key บนระบบส่งแบบ at-least-once ก็ทำให้ประมวลผลแบบ exactly-once ได้
    • ถ้าหมายถึงทฤษฎีบท CAP ก็ต้องอธิบายเพิ่มเล็กน้อย: https://www.infoq.com/articles/cap-twelve-years-later-how-th...
    • ไม่ได้เป็นไปไม่ได้ ในทฤษฎีบท CAP ก็เลือก CP ได้ นั่นคือยอมสละ availability
      ถ้าระบบยังเดินหน้าต่อได้ ข้อความจะถูกส่ง exactly once
      ถ้าต้องการหลักฐานว่ามีอยู่จริง NFSv3 ก็ทำให้สิ่งนี้ทำงานได้ตั้งแต่ทศวรรษ 1980 แล้ว ไม่รู้ว่าเป็นรายแรกหรือเปล่า
    • ในบทความเขียนว่า “ลองจินตนาการ” ผมไม่รู้ว่าข้อความที่ยกมานั้นอยู่ตรงไหน และในต้นฉบับก็ไม่พบประโยคนี้เหมือนกัน