DAG ไหลยังไง — ท่อพังกลางทาง แล้วขั้นไหนต้องรันใหม่
ต่อยอดจาก LAB.07 ด่านที่ขาออก — ทำไม build ที่ขึ้นว่าสำเร็จยังส่งหน้าที่ผิดออกไปได้
ทดลองอะไร
ตัวคุมลำดับงานแบบกดเล่นได้ ทำคู่กับคู่มือ Airflow · ท่อรับไฟล์รายเดือน 7 ขั้น (รับไฟล์สามสาขา รวมและตรวจ แปลง โหลด แล้วแจ้งผล) วาดเป็นสองมุมของสถานะเดียวกันวางคู่กัน คือกราฟที่บอกว่าอะไรรอใคร กับตารางที่บอกว่าตอนนี้ถึงไหน (แถวคือขั้น คอลัมน์คือรอบ ช่องคือสถานะกับครั้งที่ลอง) · กดที่ขั้นในกราฟเพื่อตั้งว่ารอบถัดไปจะพังชั่วคราวหรือพังถาวร ตั้ง retries ได้ 0–3 เลือกได้ว่า notify รันเมื่อต้นน้ำสำเร็จหรือเมื่อต้นน้ำจบ และเลือกว่า load เขียนลงปลายทางแบบต่อท้าย (append) หรือแทนทั้งเดือน (replace_month) แล้วเดินวงรอบทีละจังหวะ เริ่มรอบใหม่เพื่อเพิ่มคอลัมน์ กดที่ช่องเพื่อดูประวัติทีละครั้ง หรือ Clear ช่องนั้น ซึ่งต้องทายก่อนว่าช่องไหนจะถูกล้าง แล้วเลือกว่าจะรันใหม่แค่ช่องนั้นกับปลายน้ำแบบมีตัวคุม หรือทั้งก้อนแบบสคริปต์เดียว · ใต้ตารางมีแถว "แถวในคลัง" ของแต่ละเดือน ตัวเลขตามตัวอย่าง stock_load.py ในบทที่ 12 · ตรรกะทั้งหมดคือแบบจำลองของบทที่ 4 ในเล่ม ไม่ได้รัน Airflow บนเว็บ
กราฟ — อะไรรอใคร
สีในกราฟ = รอบ 2026-07 · กดที่ขั้นเพื่อสลับจุดพังของรอบถัดไป: ไม่พัง → พังชั่วคราว → พังถาวร
ตาราง — ตอนนี้ถึงไหน
ช่อง failed 0 · รอบ failed 0
| ขั้น | |
|---|---|
| receive_a | |
| receive_b | |
| receive_c | |
| merge_check | |
| transform | |
| load | |
| notify | |
| แถวในคลัง | 0append |
ช่อง = สถานะ + ครั้งที่ลอง · กรอบเน้น = เปลี่ยนในจังหวะล่าสุด · สถานะของรอบดูจากขั้นปลายสุด (notify) อย่างเดียวแถวในคลัง = แถวของเดือนนั้นที่ load เขียนลงปลายทาง เทียบกับไฟล์เดือนละ 99 แถว · กรอบแดง = เบิ้ลหรือค้างครึ่ง · ตารางสถานะข้างบนมองไม่เห็นตัวเลขนี้
กด "เดินหนึ่งจังหวะ" แล้วดูว่าวงรอบหยิบช่องไหน — ทุกช่องในจังหวะเดียวตัดสินจากภาพตารางตอนต้นจังหวะ
บันทึกของวงรอบ
- + เพิ่มคอลัมน์ 2026-07
ได้เรียนรู้อะไร
ข้อแรกคือแบบจำลองของบทที่ 4 เล็กพอจะเขียนซ้ำเป็น TypeScript ได้ทั้งตัวโดยไม่เพี้ยน: กติกาสามข้อของวงรอบ (ต้นน้ำสำเร็จครบ = ลงมือ · ต้นน้ำพัง = upstream_failed · นอกนั้นรอ) กับอีกหนึ่งข้อที่ทำให้มันตรง คือทุกช่องในจังหวะเดียวต้องตัดสินจากภาพตารางตอนต้นจังหวะ · เทสต์ของใบดึงผลรันจริงของหัวข้อ 4.3 ออกจากไฟล์ของเล่มแล้วเทียบทีละบรรทัด ตรงทั้ง 8 จังหวะ ตารางสุดท้าย และสถานะของรอบ ใบกับเล่มจึงผูกกันด้วยเทสต์ ไม่ใช่ด้วยความจำของคนเขียน · ข้อสองคือค่าเริ่มต้นของใบ (transform พังถาวร · notify ตั้ง all_done) เดินจนหยุดแล้วรอบขึ้น success ขณะที่ตัวนับช่อง failed เป็น 1 และรอบ failed เป็น 0 ซึ่งเป็นคู่เดียวกับการ์ดบนหน้า Grid จริงในบทที่ 7 · สลับสวิตช์ตัวเดียวเป็น all_success แล้วรอบถัดไปแดงทันที · ข้อสามคือตัวอย่าง stock_load.py ของบทที่ 12 ลงเครื่องสถานะได้เป็นกติกาเดียว (load ลงมือหนึ่งครั้ง = เขียนลงปลายทางหนึ่งครั้ง สำเร็จทั้งไฟล์หรือพังหลังแถวที่ 50) และเทสต์เทียบบรรทัดผลรันของหัวข้อ 12.2 ได้ตรงทุกตัวอักษรทั้งสองแบบ · ตั้ง retries 0 ให้ load พังถาวร แล้ว Clear load สองครั้ง ได้ 50 → 149 → 248 กับ 0 → 99 → 99 ตามเล่ม ขณะที่ช่อง load ในตารางเป็น success ทั้งสองแบบ ตารางสถานะแยกสองกรณีนี้ไม่ออกจริง · และไม่ต้องมีใครกด Clear ก็เบิ้ลได้: load พังชั่วคราวกับ retries 1 เดินจนหยุดครั้งเดียวได้ 149 เพราะ retry คือการรันซ้ำอัตโนมัติ · ข้อสี่คือคู่เทียบมีตัวคุมกับสคริปต์เดียวต่างกันชัดที่สุดเมื่อพังหลังจาก load เขียนเสร็จแล้ว: notify พัง Clear notify รันขั้นเดียว แถวยัง 99 · รันใหม่ทั้งก้อนรัน 7 ขั้น append กลายเป็น 198 ส่วน replace_month ยัง 99 สองสวิตช์จึงคูณกัน ความเสียหายของการรันใหม่ทั้งก้อนมาจากขั้นที่รันซ้ำไม่ปลอดภัย ไม่ได้มาจากการรันซ้ำเอง · ข้อห้าเห็นได้จากภาพที่แคปจริงเท่านั้น ทั้งที่เทสต์ผ่านหมด: รอบแรกทุกโหนดในกราฟมีป้าย "รอบถัดไป: ไม่พัง" จนโหนดที่ตั้งจุดพังไว้จมหาย ⇒ เหลือป้ายเฉพาะโหนดที่ตั้งไว้ · กล่องบันทึกค้างอยู่ที่จังหวะแรก ๆ หลังกดเดินจนหยุด ⇒ เลื่อนไปบรรทัดล่าสุดทุกครั้งที่ต่อท้าย · และคำอธิบายใต้ตารางเคยอยู่ในกล่องเลื่อนข้างเดียวกับตาราง บนจอ 360 พอตารางเลื่อนไปคอลัมน์หลัง คำอธิบายหลุดจอตามไปด้วย ⇒ ย้ายออกมานอกกล่อง
ที่ยังไม่ถึง
ยังไม่มีใครนอกจากผู้เขียนลองเล่น · ร่องรอยที่อัดจาก Airflow 3.3.2 ในแล็บ (5 สถานการณ์) ยังไม่ได้ใช้ล็อกตัวจำลอง ตอนนี้ล็อกกับผลรันของแบบจำลองในเล่มและกติกา clear ที่บันทึกจากแล็บเท่านั้น จึงยังไม่ได้เทียบสถานะสุดท้ายรายช่องกับ Airflow จริง · วงรอบเดินเป็นจังหวะพร้อมกันทั้งตาราง ส่วนของจริงเปลี่ยนทีละช่อง มีสถานะผ่านทาง scheduled กับ queued และ retry_delay เป็นเวลาจริง · สลับ trigger rule ได้แค่ที่ notify ยังไม่มี watcher และไม่มี skipped · แถวในคลังเทียบกับบล็อก Python ของหัวข้อ 12.2 ไม่ใช่ผลจาก Airflow จริง ทุกเดือนใช้ไฟล์ 99 แถวเท่าเดือนกรกฎาคมในเล่ม และพังหลังแถวที่ 50 ทุกครั้ง ไม่มีแบบ UPSERT ที่เล่มพูดถึง · "รันใหม่ทั้งก้อน" ในใบคือ Clear ทั้งรอบบนตารางเดิม ตัวนับครั้งที่ลองจึงยังนับต่อ ส่วนสคริปต์จริงไม่มีตารางให้นับ · บนจอ 360 สองคอลัมน์ต้องเลื่อนข้างถึงเห็นคู่เทียบครบ (ประโยคสรุปบอกตัวเลขทั้งคู่แทน) · ปุ่มแก้ต้นเหตุล้างจุดพังทั้งรอบในคลิกเดียว ของจริงต้องหาเองว่าต้นเหตุอยู่ที่ไหน
สายการทดลอง
- LAB.07 ด่านที่ขาออก — ทำไม build ที่ขึ้นว่าสำเร็จยังส่งหน้าที่ผิดออกไปได้
- LAB.11 DAG ไหลยังไง — ท่อพังกลางทาง แล้วขั้นไหนต้องรันใหม่ (ใบนี้)