1 คะแนน โดย GN⁺ 2023-09-11 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • เพื่อหลีกเลี่ยงปัญหาพิซซ่าที่จุดเติมเสบียงหมดในงาน Nebraska Gravel Worlds Long Voyage จึงสร้างระบบอัตโนมัติให้สั่งพิซซ่าของ Casey's ล่วงหน้าตามตำแหน่ง GPS ของจักรยาน
  • โครงสร้างคือ AWS Location geofence ตรวจจับการออกจากพื้นที่ของ GPS tracker แล้ว Lambda จะสั่งอาหารออนไลน์ให้ตรงกับ ETA ของจุดพักถัดไป
  • เนื่องจาก Casey's ไม่มี API สั่งอาหารแบบสาธารณะ จึงใช้ Playwright ทำ screen scraping เว็บไซต์ที่สร้างด้วย React และตั้งค่าให้รับผลการสั่งผ่าน push notification บน iPhone และ Apple Watch
  • ในการแข่งขันจริง มีการแจ้งเตือนว่าสั่งสำเร็จ แต่ที่ร้านไม่มีบันทึกคำสั่งซื้อ ทำให้เห็น false positive ของการทำ browser automation บนคลาวด์
  • หลังจากนั้นเมื่อปรับให้บันทึกวิดีโอการทำงานของเบราว์เซอร์ลง S3 คำสั่งซื้อทดสอบก็สำเร็จ แต่ในสภาพแวดล้อม Lambda การทดสอบเฉพาะบนเครื่อง local ยังไม่พอให้มั่นใจเรื่องเสถียรภาพ

เหตุผลที่อยากให้ได้พิซซ่าระหว่างแข่ง

  • เข้าร่วมการแข่งขันจักรยาน Gravel Worlds Long Voyage ที่รัฐ Nebraska ในช่วงฤดูเก็บเกี่ยวของ Midwest
  • ปีก่อน นักปั่นที่เร็วกว่าไปถึงก่อนและหยิบพิซซ่าของ Casey's ที่จุดเติมเสบียงไปหมด ตอนที่ไปถึงจึงไม่เหลือพิซซ่าแล้ว
  • เป้าหมายปีนี้คือสั่ง พิซซ่าสดใหม่ ล่วงหน้าให้ตรงกับเวลาจอดพัก
  • ตั้งใจจะต่อยอดจากระบบ GPS tracker จักรยานแบบ serverless ที่มีอยู่เดิม โดยเพิ่มวิธีให้รันสคริปต์สั่งอาหารเมื่อออกจาก geofence ที่กำหนด

วิธี trigger การสั่งซื้อด้วย GPS และ Lambda

  • การออกแบบโดยรวมคือใช้ geofence ของ AWS Location เฝ้าติดตาม GPS tracker
    • เมื่อ tracker ออกจาก geofence จะ trigger ฟังก์ชัน Lambda
    • Lambda คำนวณ ETA ไปยังจุดพักถัดไป
    • สั่งพิซซ่า Casey's ให้สอดคล้องกับเวลาที่คำนวณได้
  • Casey's ไม่มี public API สำหรับสั่งอาหารออนไลน์ จึงเลือกทำ screen scraping เว็บไซต์
    • เว็บไซต์ของ Casey's เป็นแอป React ซับซ้อนที่ render ฝั่ง client
    • ใช้ Playwright แทน scraper ทั่วไป
    • ขั้นตอนการรัน Playwright บน Lambda ยุ่งยากถึงขนาดแยกเขียนเป็นอีกบทความได้
  • เพื่อยืนยันสถานะคำสั่งซื้อ ตั้งค่าให้ส่ง push notification ไปยังโทรศัพท์และนาฬิกาเมื่อสำเร็จหรือล้มเหลว
    • การตั้งค่าให้ Web Push ทำงานบนอุปกรณ์ iOS ก็เป็นเรื่องที่เขียนแยกได้อีกบทความเช่นกัน

ผลหน้างานที่ต่างจากการแจ้งว่าสำเร็จ

  • ตั้ง geofence สำหรับ trigger การสั่งซื้อไว้บริเวณหลัก 180 ไมล์ ของการแข่งขัน
  • วางแผนไปรับพิซซ่าที่หลัก 200 ไมล์
  • เมื่อออกจาก geofence ก็มี push notification บนนาฬิกาแจ้งว่าสั่งพิซซ่าสำเร็จ
  • แต่เมื่อไปถึงจุดพัก ที่เคาน์เตอร์ไม่มีคำสั่งซื้อ และในร้านก็ไม่มีบันทึกคำสั่งซื้อเช่นกัน
  • เมื่อตรวจสอบบัญชี พบว่าไม่มีการสร้างคำสั่งซื้อจริง เป็นเพียง false positive ที่เกิดจากการแจ้งว่าสำเร็จเท่านั้น
  • ที่หน้างานมีพิซซ่าหั่นชิ้นที่ทำไว้ล่วงหน้าอยู่ไม่กี่ชิ้น จึงซื้อสิ่งนั้นแทน
  • หลังจากนั้นจนจบการแข่งขัน 300 ไมล์ ก็เอาแต่คิดว่าฟังก์ชัน Lambda ผิดพลาดตรงไหน

วิดีโอ capture ทิ้งเบาะแสไว้แทน log

  • หลังจบการแข่งขัน ตรวจสอบ log แล้วก็ไม่พบข้อมูลที่บอกสาเหตุความล้มเหลว
  • จาก log ดูเหมือนทุกอย่างสำเร็จอย่างเงียบ ๆ จึงแทบไม่มีเบาะแสสำหรับ debug
  • ไม่กี่วันต่อมา ปรับ Lambda ให้ capture เป็นวิดีโอ การทำงานของเบราว์เซอร์และอัปโหลดไปยัง bucket S3
  • เมื่อทดสอบด้วยพฤติกรรมที่ปรับแล้ว คำสั่งซื้อก็สำเร็จจริง และไปรับ Hawaiian pizza ได้ตามปกติ
  • ยังสรุปสาเหตุที่แน่ชัดไม่ได้
    • อาจเป็นไปได้ว่า Lambda จบการประมวลผลทันทีที่ form.submit() สุดท้ายถูกรันใน embedded Playwright browser
    • อาจเป็นไปได้ว่าเว็บไซต์สั่งอาหารออนไลน์ไม่ได้ยืนยันว่าเบราว์เซอร์ได้รับ response สำเร็จ จึงไม่ได้ประมวลผลคำสั่งซื้อจนเสร็จสมบูรณ์
    • เวลาที่เพิ่มขึ้นจากการประมวลผลและอัปโหลดวิดีโออาจทำให้มีเวลาพอสำหรับการเก็บกวาดเบราว์เซอร์

ถ้าทำใหม่ครั้งหน้าจะเปลี่ยนอะไร

  • การ screen scraping แอป client-side React ด้วยเบราว์เซอร์บนคลาวด์ให้เสถียรนั้นทำได้ แต่ ยุ่งยากมาก
  • ถ้าทำใหม่ อาจพิจารณา reverse engineer แอป native ของ Casey's แล้ว trigger internal API โดยตรง
  • ต้องมี workflow ที่ดี สำหรับจำลองพฤติกรรมเชิงภูมิสารสนเทศ
    • ตอนแรกทดสอบด้วยการสร้าง geofence รอบบ้าน
    • วิธีเดินออกไปทดสอบจริงตอน 5 ทุ่มกลายเป็นภาระอย่างรวดเร็ว
  • ไม่ควรลดการทดสอบในสภาพแวดล้อมจริง
    • ก่อนแข่ง ส่วนใหญ่ทดสอบด้วยการรันฟังก์ชันบน local workstation
    • ความสำเร็จบน local ทำให้มั่นใจผิด ๆ ว่าจะทำงานได้ถูกต้องในสภาพแวดล้อม Lambda ด้วย
  • หากกังวลว่าพิซซ่า Casey's จะหมด อีกวิธีคือทิ้งระยะห่างจากกลุ่มหน้าให้มากกว่า 30 นาที เพื่อให้ร้านมีเวลาทำพิซซ่าหั่นชิ้นชุดใหม่
  • โค้ดเปิดเผยอยู่บน GitHub: https://github.com/mattdsteele/spot-tracker-tracker/…

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

 
GN⁺ 2023-09-11
ความคิดเห็นบน Hacker News
  • Colin สามารถทำพิซซ่าให้ได้ด้วยระหว่างส่งของ: https://youtu.be/YjyJRTM0knE?si=fes2lbRntUlciPSH

    • ถึงจะตลกก็เถอะ แต่คอนเซ็ปต์ในวิดีโอ YouTube นี้เคยเป็นโมเดลธุรกิจจริงของ สตาร์ทอัพที่ SoftBank ลงทุน และได้เงินลงทุน 500 ล้านดอลลาร์
      จุดบกพร่องร้ายแรงของแผนที่ดูไร้ช่องโหว่คือ เวลา truck วิ่งผ่านหลุมบ่อบนถนน พิซซ่าจะปลิวไปมาและเสีย topping ไปหมด: https://gizmodo.com/zume-softbank-ai-pizza-delivery-stellar-...
    • พอเอา GIL ออกก็เป็นแบบนี้สินะ
      วิดีโอนี้ทำให้ผมหัวเราะดังที่สุดในบรรดาที่ดูบน YouTube ปีนี้
    • ผมไม่รู้ว่าความบ้าบิ่นของ Colin เป็นการแสดงแบบ Electroboom หรือว่าเขาบ้าบิ่นจริง ๆ ตามที่เห็น
      จนตอนนี้ก็ยังตัดสินไม่ได้ และแปลกที่มันทำให้ดูยากขึ้น แน่นอนว่าเขาคงไม่ปล่อยวิดีโอที่มีอะไรผิดพลาดหนัก ๆ ออกมาหรอก
    • โอ้โห เย็นวันอาทิตย์หายไปทั้งคืนเลย
      ผมนั่งดูวิดีโอที่คนนี้ ขุดอุโมงค์จากบ้านไปโรงเก็บของ อยู่ 2 ชั่วโมงครึ่ง เป็นช่องที่สนุกจริง ๆ
  • เยี่ยมมาก ให้ความรู้สึกเหมือนการตีความ pizzatool ในแบบศตวรรษที่ 21
    https://donhopkins.medium.com/the-story-of-sun-microsystems-...
    เกร็ดอีกอย่างคือ ร้านพิซซ่า Waypoint Pizza ใน Tiburon ถ้าขอเขาดี ๆ เขาส่งถึงบนผืนน้ำของ San Francisco Bay ได้ด้วย มีประโยชน์มากเวลามีแข่งเรือใบแปลก ๆ แบบไม่ค่อยจริงจัง เช่น Three Bridge Fiasco

    • ปกติส่งพิซซ่าก็อาจเสียเพิ่ม 5–10 ดอลลาร์อยู่แล้ว เลยสงสัยว่า ส่งบนผืนน้ำ ถ้าขอเขาดี ๆ จะต้องจ่ายประมาณเท่าไหร่
  • Dean Karnazes เคยทำอะไรคล้าย ๆ กันในการแข่งอัลตร้ารันนิ่งโดยไม่ใช้เทคโนโลยี
    ว่ากันว่าเขา ม้วนพิซซ่าเหมือนบูร์ริโต แล้วถือวิ่งไปด้วย: https://gffmag.com/the-raw-endurance-of-ultramarathon-man-de...

    • การวิ่ง endurance จริง ๆ แล้วแทบจะเป็นการกินมากกว่า
  • ถ้าเป็นเว็บไซต์ React ก็มีความเป็นไปได้สูงว่าหมายถึงมี API ที่เรียกใช้ได้โดยตรง
    อาจต้องล็อกอินเพื่อเอา token แต่แบบนั้นแข็งแรงกว่ามาก

    • เห็นด้วย ผมสงสัยมาตลอดว่าทำไมไม่เฝ้าดูและ replay network request แทนที่จะ scrape หน้าจอ
      ถูกกว่ามากและแข็งแรงกว่ามาก หรือว่าผมพลาดอะไรไป?
  • ผมสนุกกับบทความนี้มากจริง ๆ
    มีองค์ประกอบดี ๆ เยอะ ทั้งปัญหาทางเทคนิคที่น่าสนุก พิซซ่า การทำให้ผมต้องไปค้นว่า “s-tier” หมายถึงอะไร แค่ premise ก็ขำแล้วแต่ยังมีมุกเพิ่มอีก รวมถึง mea culpa ตอนท้ายและการคาดเดาสาเหตุของบั๊ก ทฤษฎีนั้นก็ดูมีเหตุผลดี แม้จะยังไม่แน่ชัด

    • ผมกลับไม่ชอบเลย เหมือนสร้างเครื่องจักร Rube Goldberg ที่ใช้งานไม่ได้ด้วย abstraction 100 ชั้น กาวและทางแก้เฉพาะหน้าใน cloud
      รู้สึกเหมือนรวมข้อเสียของเทคโนโลยีสมัยใหม่ไว้ทั้งหมด
  • พูดตรง ๆ ว่าค่อนข้างเจ๋งเลย สงสัยว่าจะทำอะไรคล้าย ๆ กันกับบริการอย่าง Deliveroo ได้ไหม
    ถ้าในวันที่กำหนด X เงื่อนไขตรงกัน เช่น ตอนทำงานดึก แล้วอยู่ห่างจากบ้านประมาณ Z ก็สั่งเมนู Y ที่ตั้งไว้ล่วงหน้า ดูเหมือนน่าจะทำได้

    • ทำไมต้องโกหกด้วยว่ามันค่อนข้างเจ๋ง? การบอกชัด ๆ แบบนั้นฟังดูแปลกนิดหน่อย
    • เชื่อมกับ fitness tracker แล้วให้ส่งพิซซ่าแค่พอรักษา calorie deficit ให้ยังน้ำหนักลดได้ก็พอ
    • บริการสั่งอาหารน่าจะมี API ดี ๆ สำหรับกรณีแบบนี้
      มีเหตุผลอะไรที่ไม่ทำให้การสั่งอาหารและจ่ายเงินผสานเข้ากับการ hack แบบ IFTTT ได้ง่าย ๆ บ้างไหม?
  • มีความทรงจำดี ๆ กับการโตมากับการกิน Casey's pizza
    ทุกครั้งที่กลับไป Midwest ก็จะซื้อกิน อธิบายให้ชัดว่ายังไงยาก แต่มันมี เสน่ห์เฉพาะตัว อยู่

    • เพราะมันมันกว่าไหม? พิซซ่ามื้อเช้านี่สุดยอด โดยเฉพาะถ้าเป็นวันถัดจากที่ดื่ม Busch Light
  • อ้อ สุดท้ายก็ไม่ทำงานสินะ
    ถ้ารู้ตอนอยู่ที่ ไมล์ที่ 200 ก็คงหนักเอาเรื่อง

  • ซอฟต์แวร์ จักรยาน พิซซ่า นี่คือสิ่งที่ชอบในชีวิตเลย
    ผมอ่านโปรเจกต์และบทความนี้อย่างสนุกมาก และยังทำให้นึกไอเดียคล้าย ๆ กันออกด้วย

    • พวกนี้ก็เป็นสิ่งที่ผมชอบเหมือนกัน OP กับคุณกับผมน่าจะตั้ง ชมรม กันนะ
  • ถ้าเป็นผมคง โทรแบบ hands-free หรือขอให้เพื่อนช่วยโทร แล้ว trigger ด้วยข้อความแทน
    แล้วก็เรียกว่า “ส่ง” อยู่เรื่อย ๆ แต่จริง ๆ แล้วมันเป็น pickup ไม่ใช่เหรอ?