

หน้าที่แสดงสถานะงานหรือข้อมูลที่เปลี่ยนเป็นระยะ อาจใช้ Server-Sent Events เพื่อให้ server ส่งข้อมูลมาถึงหน้าเว็บโดยไม่ต้องถามซ้ำทุกช่วงเวลา พอเริ่มรับได้ เราจะเห็นเหตุการณ์เข้ามาต่อเนื่องและปรับหน้าจอตามนั้น
แต่พอเครือข่ายหลุดชั่วคราว คำถามถัดไปคือข้อมูลที่เกิดระหว่างนั้นหายไปหรือจะกลับมาครบ Browser อาจต่อช่องทางให้อีกครั้งได้เอง แต่การมี connection ใหม่ยังไม่ได้ตอบว่าฝั่งบริการเก็บข้อมูลเก่าไว้หรืออ่านต่อจากจุดเดิมได้หรือไม่
จึงควรแยกการ reconnect ออกจากการฟื้นข้อมูลครับ แล้วกำหนดสัญญาของ event ID กับทางรับสถานะปัจจุบันให้ตรงกับสิ่งที่หน้าจอต้องใช้
EventSource เป็น API ฝั่ง browser สำหรับรับ event stream ตามรูปแบบ SSE โดยการสื่อสารข้อมูลในช่องนี้เป็นทิศทางจาก server มายัง client หากผู้ใช้ต้องส่งคำสั่งกลับ ยังต้องมีทางเรียกบริการที่ออกแบบไว้แยกตามงาน
คำตอบของ stream ใช้ชนิด text/event-stream และข้อความตามรูปแบบที่กำหนด ไม่ใช่ส่ง JSON หลายก้อนติดกันแล้วถือว่า browser จะรู้ขอบ event ให้เอง แต่ละบล็อกต้องมีการแบ่งบรรทัดกับจุดจบที่ parser ใช้แยกได้
ตัวอย่างสมมติต่อไปนี้มีชื่อ event กับข้อมูลสถานะ โดยรหัสและชื่อ job เป็นเพียงตัวอธิบายรูปแบบ ไม่ใช่ข้อมูลจากงานที่รันจริง
id: sample-7
event: status
data: {"job":"example","state":"running"}
หากกำหนดชื่อ event ก็ต้องรับด้วย listener ที่สอดคล้อง ไม่ใช้เฉพาะ onmessage แล้วสรุปว่าบริการไม่ส่งอะไร เพราะ event ที่มีชื่อถูก dispatch ตามชื่อนั้นตามกติกา

เมื่อ stream กำหนด id ค่านั้นใช้เป็น last event ID ตามรูปแบบที่ browser รับ และในการกลับมาเชื่อมใหม่ EventSource สามารถส่ง Last-Event-ID ให้ server เพื่อบอกจุดอ้างอิงที่เกี่ยวข้องได้
แต่ header นี้ยังต้องมีบริการที่รู้ว่าจะใช้รหัสนั้นอ่านอะไรต่อ หาก server เพียงปล่อยข้อมูลสดออกมาโดยไม่เก็บประวัติ ก็ไม่มีชุดข้อมูลที่พลาดให้ส่งกลับเพียงเพราะ client ขออ่านต่อ การมี id จึงเป็นส่วนของสัญญา ไม่ใช่กลไกเก็บทุก event ในตัว
ฝั่งออกแบบต้องระบุว่ารหัสอยู่ในขอบเขตใด เช่น stream ของงานหนึ่งหรือรายการทั้งหมดของผู้ใช้ และมีลำดับที่ตีความอย่างไร ไม่ใช้ลำดับในหน่วยความจำของ process เดียวโดยยังไม่ดูผลหลัง restart หรือเมื่อคำขอไปถึงอีก instance
การจำรหัสเพื่อ reconnect ของ EventSource ที่ยังทำงานอยู่ก็ต่างจากการเปิดหน้าใหม่หรือสร้าง object ใหม่ หากต้องฟื้นหลังปิดหน้า ต้องกำหนดวิธีเก็บจุดอ่านต่อหรือเริ่มจาก snapshot เอง ไม่ถือว่ารหัสเดิมจะถูกเก็บถาวรข้ามทุกการเปิดหน้าโดย API ให้อัตโนมัติ
ถ้าเก็บประวัติเพียงช่วงหนึ่ง client ที่หายไปนานอาจส่งรหัสที่เก่ากว่าข้อมูลที่เหลืออยู่แล้ว ควรมีผลที่บอกว่าอ่านต่อไม่ได้และทางรับสถานะชุดใหม่ ไม่เปิด stream ต่อด้วยข้อมูลล่าสุดแล้วทำเหมือนช่องว่างก่อนหน้าถูกเติมครบ
Snapshot ช่วยให้หน้าเว็บกลับมารู้สภาพปัจจุบันได้ในงานที่ต้องการสถานะล่าสุด แต่ไม่แทนประวัติทุกเหตุการณ์ หากหน้าต้องแสดงลำดับการเปลี่ยนทั้งหมดก็ยังต้องมีแหล่งข้อมูลที่รักษาลำดับตามข้อกำหนดนั้นต่างหาก
ระหว่างรับ snapshot กับเริ่มตาม event ใหม่ก็อาจมีข้อมูลเปลี่ยนได้ จึงควรออกแบบจุดอ้างอิงที่สัมพันธ์กัน เช่น snapshot บอก cursor ของชุดที่อ่าน แล้วเริ่มตามต่อจากขอบเขตนั้นตามสัญญา ไม่ทำสองขั้นแยกโดยยังไม่คิดว่าช่วงรอยต่ออาจข้ามข้อมูล

การฟื้นหลังหลุดอาจมีข้อมูลที่ client เคยใช้ไปแล้วกลับมาอีกได้ตามวิธีส่งต่อ จึงควรมีเกณฑ์จัดการ ID เดิมหรือ version ที่เก่ากว่า ไม่เพิ่มรายการซ้ำหรือเอาสถานะเก่าทับใหม่เพียงเพราะข้อความนั้นเพิ่งมาถึงหน้าเว็บ
หาก event ใช้เป็นสัญญาณให้ไปอ่านข้อมูลปัจจุบัน ก็ต้องบอกความหมายนั้นให้ชัด ต่างจาก event ที่บรรทุกสภาพของแต่ละจังหวะมาเอง หน้าจอจะได้รู้ว่าควรใช้ข้อมูลในข้อความทันทีหรือดึงฉบับที่มีผลจาก API อีกครั้ง
สำหรับงานที่มีผลข้างเคียง การรับ event ไม่ควรกลายเป็นการสั่งเปลี่ยนข้อมูลซ้ำโดยไม่มีตัวตนของงาน การมีช่องทาง push ไม่ได้ให้คุณสมบัติผลครั้งเดียวกับทุก action ที่คนเขียน listener เพิ่มเข้าไป
แม้ server สร้างบล็อกข้อมูลถูก การตั้งค่าระหว่างทางอาจทำให้ข้อมูลถูกพักรวมก่อนส่งหรือ connection ถูกปิดตามช่วงเวลาที่เกี่ยวข้อง ควรตรวจทั้งจังหวะที่ server ส่งกับสิ่งที่ client ได้จริง ไม่ตัดสินจาก response status ว่า200แล้ว stream ต้องเดินต่อเนื่องครบ
ข้อความ comment ใน stream ใช้เป็นส่วนหนึ่งของการรักษากิจกรรมบน connection ได้ตามการออกแบบ แต่ไม่ได้แก้ทุก timeout หรือรับรองว่า client ยังคงอ่านได้ ต้องดูเงื่อนไขของ proxy ผู้ให้บริการและเส้นทางจริงด้วย โดยไม่คัดลอกช่วงเวลาเดียวไปใช้กับทุกระบบ
การยืนยันตัวตนกับ CORS ก็ต้องตรงตาม client ที่เลือก และสิทธิ์ของผู้ใช้ต้องยังถูกบังคับกับข้อมูลใน stream ไม่เปิดประวัติของอีกงานเพียงเพราะส่ง Last-Event-ID ที่ดูถูกต้องมาได้ รหัสอ่านต่อไม่ใช่สิทธิ์อ่านทุกข้อมูล
เมื่อหน้าเลิกใช้ stream ควรปิดด้วยวิธีที่ API รองรับ ไม่ปล่อยให้ทุกการเปิด component สร้าง connection เพิ่มค้างไว้ และต้องคิดกรณีหลายแท็บที่แต่ละแท็บเปิดของตัวเองตามภาระของระบบ
ชุดตรวจควรมีการหลุดแล้วต่อใหม่ การ restart ฝั่งบริการ รหัสที่หมดช่วงเก็บ และข้อมูลซ้ำ พร้อมดูว่าหน้ากลับมามีสภาพตรงกับแหล่งข้อมูลหรือไม่ เก็บการตรวจจากทั้ง cursor สถานะและข้อมูลที่ใช้จริง ไม่ใช้ข้อความว่า connected เป็นหลักฐานว่าประวัติกลับมาครบแล้ว
SSE ช่วยนำข้อมูลใหม่มาถึงหน้าเว็บและมีทาง reconnect ตามกลไก แต่การรักษาช่วงที่พลาดต้องมีสัญญา event ID ประวัติและ snapshot ร่วมกัน เมื่อขอบเขตเหล่านี้ชัด พร้อมตรวจสิทธิ์กับการรับซ้ำ เราจะฟื้นหน้าจอได้ตามข้อมูลที่มีจริง โดยรู้ว่า connection ที่กลับมาและความครบของสถานะยังต้องตรวจคนละด้าน