HTTP error ที่มักเจอบ่อย ๆ หากใช้งาน application gateway (พวก load balancer หรือ reverse proxy)

เวลาใช้ application gateway (พวก load balancer หรือ reverse proxy) ตัว error ที่พบได้บ่อย ๆ จะมี 3 ตัวหลัก ๆ (โน๊ตไว้สำหรับอธิบายในอนาคต)

1. HTTP 502 Bad Gateway
คือ request ที่เข้ามาไม่สามารถส่งต่อไปยัง back-end ได้
โดยมักจะเกิดจาก
– service ที่ handle port listening นั้นดับไป
– IP ผิด
– DNS ที่ resolve IP มาไม่ได้ IP ที่ถูกต้อง
– โดน firewall block

2. HTTP 503 Service Unavailable
คือ request ที่เข้ามาส่งต่อไปยัง back-end แล้วได้รับการตอบกลับมาเป็น Error Code ที่ถูกตั้งค่าว่าไม่ปรกติ (มักจะเป็นพวกที่ไม่ใช่ HTTP 200 OK หรือพวก HTTP 301/302 Redirect) โดยทั่วไปเกิดจากแอปส่งผลตอบกลับเป็น HTTP 500 Internal Server Error (หาก config เพิ่มเติม เราสามารถใช้การส่ง error ตัวนี้ในการปกปิด Error Code หรือ Exception Message ที่มีความเสี่ยงออกไปยัง user ได้)

3. HTTP 504 Gateway Timeout
คือ request ที่เข้ามาแล้วส่งต่อไปยัง back-end แล้ว application gateway รอการตอบกลับมานานเกินกว่าค่า timeout ที่ตั้งไว้ (ปรกติจะตั้งไว้ 30-60 วินาที) ซึ่งมักเกิดจากตัวแอปด้านหลังประมวลผลนานเกิน โดยปัญหาเกิดจากเข้าใช้งานเยอะจนตัวแอปตอบสนองต่อการใช้งานไม่ทัน (แอปอาจจะ query ข้อมูลอย่างหนัก และฐานข้อมูลก็ทำงานตอบสนองต่อตัวแอปไม่ทันอีกต่อหนึ่ง)

ปล. back-end อาจจะเป็น Web Server หรือ Application Server ก็ได้

Ref: List of HTTP status codes

 


GOV.UK voter registration – 504 Gateway Time-out error

เปรียบเทียบรูปโปสเตอร์เลือกตั้งที่เป็นรูปแถมจากซีดีเธียร์เตอร์ AKB48 52nd Single「Teacher Teacher」และรูปที่ปริ๊นต์จากร้านอัดรูป “Kamera no Kitamura” ที่ญี่ปุ่น

เปรียบเทียบรูปโปสเตอร์เลือกตั้งที่เป็นรูปแถมจากซีดีเธียร์เตอร์ AKB48 52nd Single「Teacher Teacher」และรูปที่ปริ๊นต์จากร้านอัดรูป “Kamera no Kitamura” ที่ญี่ปุ่น ที่ได้รับลิขสิทธิ์เพื่อปริ๊นต์ ภาพอย่างถูกต้องจาก AKS

ความละเอียดของภาพไม่หนีกันเลย โดยดูจากตรงเส้นผมที่จะมาเป็นเส้นที่ชัดมากทั้งสองแบบ

โทนสว่างและมืดของภาพ ภาพจากซีดีจะมืดกว่านิด ๆ ภาพที่ปริ๊นต์เองจะสว่างกว่าเล็กน้อย (ไม่จับผิดนี่มองไม่ออก)

ด้านล่างของรูปจากซีดีจะใส่ที่มาว่ามาจากซีดี AKB48 Teacher Teacher ซึ่งมีขนาดใหญ่กว่าจากการปริ้นต์ที่จะบอกแค่บริษัทที่ถือลิขสิทธิ์ ทำให้พื้นที่ในการวางรูปโปสเตอร์ของรูปแถมจากซีดีเล็กกว่าเล็กน้อย

ด้านหลังรูป ในส่วนรูปแถม จะมีลายน้ำ AKB48 Teacher Teacher ส่วนรูปปริ้นต์จะเป็นกระดาษอัดรูปที่เราคุ้นเคยกัน คือบอกยี่ห้อกระดาษ แต่มีลายน้ำระบุชื่อไฟล์รูป และหมายเลขลำดับรูปที่สั่งปริ้นต์ออกมาแต่ละรูปจะมีลำดับเลขรันไปเรื่อยๆ

โครงการ Music We Choose You เราส่งรหัสโหวตเลือกตั้งด้วยวิธีอัตโนมัติอย่างไร

ก่อนอ่านผมอยากทำความเข้าใจก่อนว่าผมเป็นเพียงหนึ่งในทีมงาน Music We Choose You กว่าหลายสิบชีวิตเท่านั้น มีทีมงานส่วนอื่น ๆ ที่ต้องอ่านบัตรโหวต และกรอกด้วยมือโหวตลงไปบนเว็บเองอีกหลายพันโหวต ที่ไม่ได้เกิดจากกระบวนการนี้ และใน blog นี้ อาจไม่ได้กล่าวถึงชื่อทีมงานหลังบ้านเป็นรายคนได้ เพราะเพิ่งได้เจอหน้ากันก็ตอนวันลุ้นผลคะแนนเสียงเลือกตั้ง และบางคนที่เป็นทีมงานฝั่งญี่ปุ่นก็ยังไม่เจอหน้ากันจนวันนี้ แต่ทุกคนทำงานอย่างหนัก เพื่อให้ได้ซึ่งรหัสโหวตเลือกตั้งมาเข้ากระบวนการ และสุดท้ายคือผู้สนับสนุนเงินที่ร่วมกันโดเนทเข้าโครงการเพื่อให้มีเงินจำนวนมากในการจัดหารซีดี และรหัสโหวตเลือกตั้งมา นั้นหมายความว่า 18,502 คะแนน เกิดจากความร่วมแรงร่วมใจกันของทีมงาน และผู้สนับสนุนทุกคน ผมไม่ขอรับเครเดิตเหล่านี้ไว้เพียงคนเดียว ถ้ามีรายชื่อที่แน่ชัด เดี่ยวจะนำลงมาใส่ให้อีกครั้ง

ในส่วนของกระบวนการนี้ไม่ได้เป็นสิ่งใหม่อะไร แต่เป็นการสังเกต และมีต้นแบบจากคลิปจากแฟนคลับฝั่งญี่ปุ่นที่ได้ลงแนวทางปฏิบัติไว้ เรานำมาปรับปรุงและเปลี่ยนแปลงในหลาย ๆ ส่วนเพื่อให้สอดคล้องกับการทำงานในทีมอีกรอบ (ใน blog นี้บางขั้นตอนเรามี source code เปิดเผยให้ลองนำไปศึกษาต่อด้วย)

ฉะนั้นการเล่าเรื่องของกระบวนการในส่วนนี้จึงเป็นเหมือนบันทึกความทรงจำ เป็นข้อมูลอ้างอิงในอนาคตสำหรับนำไปปรับปรุงกระบวนการ และสำหรับบุคคลที่สนใจ

ตัวอย่างกระบวนการ และสิ่งที่ผมนำเป็นต้นแบบจากฝั่งญี่ปุ่น

การเขียนใน blog นี้จะมี 2 ช่วง คือช่วงก่อนประกาศผลด่วน กับช่วงหลังประกาศผลด่วน ซึ่งผมพยายามแทรกช่วงก่อนประกาศผลด่วนเพื่อให้รู้ว่าก่อนประกาศผลด่วน เราทำอะไร และนำมาปรับปรุงให้ดีขึ้นอย่างไรหลังจากประกาศผลด่วนเพื่อให้ส่งรหัสโหวตให้ได้ทัน เพราะทีมงานก็เสียดายคะแนนอีกหลายร้อยคะแนนที่ส่งขึ้นไปช่วงผลด่วนไม่ทัน เนื่องจากเรายังประสานงานระหว่างทีมกันไม่ดี ตัวชุดโปรแกรมที่ทำงานในช่วงนั้นยังเจอปัญหาติดขัด และรวมไปถึงเว็บรับรหัสโหวต AKB48 ล่มช่วงประมาณตี 2-5 ในช่วงก่อนปิดรับผลด่วน จนทำให้เราโหวตช่วงผลด่วนไปได้ไม่ตามเป้าที่วางไว้

การติดต่อประสานงานระหว่างทีมงานหลัก ๆ คือใช้ LINE และ Discord สำหรับ LINE จะใช้เพื่อสื่อสารแบบเร่งด่วน และสื่อสารกับทีมฝั่งญี่ปุ่น ส่วน Discord จะใช้ประสานงานช่วงส่งรหัสโหวต และพูดคุยแก้ไขรหัสโหวตในช่วงกลางคืนตั้งแต่ประมาณ 3 ทุ่มถึงตี 2 (มีบางวันตี 3) เหตุผลที่เราใช้เพราะการสื่อสารด้วยเสียงมันไม่ต้องพิมพ์ เพราะมือพิมพ์รหัสโหวต หรือแก้ไขข้อมูลกันอยู่ การพิพม์ LINE ทำให้งานส่วนแก้ไขรหัสโหวตหยุดชะงักได้ แล้วคุณภาพเสียงของ Discord ค่อนข้างดีไม่ค่อยเจอดีเลย์อีกด้วย

เริ่มด้วยการแสกนบัตรโหวตด้วย Fujitsu ScanSnap iX500 ซึ่งเป็น Sheet Fed Scanner ยอดนิยมมากสำหรับงานแบบนี้ โดยเราแสกนออกมาเป็น JPEG ไฟล์ โดยเหตุผลที่เราไม่แสกนออกมาเป็น PDF เพราะ ไฟล์รูปภาพบริหารจัดการง่ายกว่า หรือนำไปเปิดไฟล์เพื่ออ่านกับอุปกรณ์หลากหลาย

ScanSnap iX500_006
ScanSnap iX500_006 @ flickr

เมื่อได้ไฟล์รูปภาพ ทีมงานฝั่งญี่ปุ่น-ไทยตกลงกันว่าจะอัพโหลดรูปภาพผ่าน Google Drive จากญี่ปุ่นมาไทยโดยการแชร์ Folder กลางตัวหนึ่ง เพื่อใช้สำหรับการส่งไฟล์รูปภาพบัตรโหวต และเอาไว้ค้นหาสำหรับกรอกทบทวน-แก้ไขรหัสโหวตในกรณีที่นำไฟล์รูปดังกล่าวไป OCR (Optical character recognition – การแปลงไฟล์ภาพเอกสารที่เป็นรูปภาพ ให้เป็นไฟล์ข้อความตัวอักษรโดยอัตโนมัติ) แล้วไม่ได้รหัสโหวตออกมาอย่างถูกต้อง โดยเราจัดแบ่ง Folder ตามรอบที่ส่งมาจากฝั่งญี่ปุ่น โดยคนที่กำหนดชื่อเป็นฝั่งญี่ปุ่น เพราะต้องให้ทางนั้นกำหนดรหัสอ้างอิงที่เข้าใจง่ายสำหรับคนทำงานฝั่งต้นทางที่มีจำนวนแผ่น และต้องดูแลจัดการบัตรโหวตจำนวนมาก เพราะจำนวนคนฝั่งญี่ปุ่นน้อยกว่าฝั่งไทยมาก เราต้องคิดถึงการจัดการหน้างานฝั่งนั้นเป็นหลัก

ในโครงการนี้ในส่วนของการโหวต เรามีทีมงาน 2 ส่วน คือทีมกรอกมือ และกดโหวต แล้วนำรหัสโหวตที่โหวตเสร็จแล้วมาใส่ใน Google Sheets ส่วนอีกทีมคือทีมที่ผมลงมาช่วยเป็นส่วนหนึ่งของทีมงาน ซึ่งทำผ่าน OCR โดยจุดรวมของรหัสโหวตทั้ง 2 ทีมนี้ คือใช้ Google Sheets ตัวหนึ่ง เพื่อใช้สำหรับทำงานร่วมกันเพื่อแชร์ข้อมูลรหัสโหวต และการแก้ไขข้อมูล โดยทั้ง 2 ทีมมีคนกว่า 10 คนช่วยกันดู ช่วยกันแก้ไขรหัสโหวต เราเก็บรหัสโหวตต่างๆ พร้อมกับชื่อไฟล์รูปจากใน Google Drive เพื่อช่วยอ้างอิงย้อนกลับไปยังรูปต้นฉบับที่รหัสโหวตนั้นถูกกรอกมา เพราะหากรหัสโหวตนั้นใช้ไม่ได้ด้วยเหตุผลใด ๆ เราสามารถกลับไปค้นหาได้ง่าย

ในรอบส่งรหัสโหวตก่อนประกาศผลด่วนเมื่อเราได้รับการยืนยันรูปที่จะทำ OCR ได้แล้ว เราเอารูปเหล่านั้นไปเข้า OCR ทันที แล้วพบว่าความเร็วและข้อผิดพลาดมีเยอะพอสมควร ในระดับความผิดพลาด ~35% และความเร็วควรจะเร็วได้มากกว่านี้

แต่หลังจากรอบผลด่วนเราปรับปรุงกระบวนการเพิ่มด้วยการใช้โปรแกรมที่ชื่อ XnView เข้ามาเพื่อทำ resize/crop แบบ batch (GitHub – Source Code) ในส่วนของรูปก่อนส่งเข้า OCR เพื่อให้ตัว OCR มันอ่านเฉพาะจุดที่จำเป็นต้องอ่าน และได้ผลตอบกลับที่เร็วขึ้น โดยรูปหมื่นกว่ารูปผ่านกระบวนการ batch นี้ เพื่อช่วยเรื่องลดความผิดพลาดจาก OCR ให้ได้มากที่สุด และยังลดจำนวนข้อมูลที่จะต้องส่งขึ้นระบบของ Google Cloud Vision API ได้ด้วย เราเคยจับเวลา รูปบัตรโหวตกว่า 2,000 รูป เราใช้เวลาไม่ถึง 15 นาที โดยนับเวลาตั้งแต่ resize/crop รูปบัตรโหวตจำนวนดังกล่าว มาจนได้ตัวเนื้อ Text กลับออกมาจาก Google Cloud Vision API กว่า 1,800 รายการ ซึ่งเกือบทั้งหมดที่สามารถนำไปส่งรหัสโหวตเข้าระบบได้ทันที ระดับความผิดพลาดลดต่ำลงเหลือ ~20% นั้นทำให้เราได้ประโยชน์จากการใช้ไฟล์รูปภาพแทน PDF เพราะเราสามารถหาชุดโปรแกรมที่สามารถทำการ resize/crop ได้ง่ายกว่า

รูปภาพต้นฉบับ

จะได้รูปภาพที่โดน resize/crop แบบด้านล่าง

 

สำหรับ OCR ที่เราใช้คือ Google Cloud Vision API  ด้วยเหตุผลตั้งต้นดังนี้

  1. การหา OCR Library แบบ Offline ไม่น่าจะคุ้มค่า เพราะคิดบนฐานค่าใช้จ่ายหากซื้อ License หรือหากใช้ Open source ก็ต้องแน่ใจว่าจะใช้งานได้จริง เราลองผิดลองถูกจุดนี้ไม่ได้มากนัก คำตอบของโจทย์จึงตกมาที่ Cloud Service แทน
  2. การเชื่อมต่อกับ Google Sheets API บน Credential ตัวเดียวกันได้ ทำให้การพัฒนาส่วนนี้เร็วขึ้น

แต่สุดท้ายในเหตุผลข้อที่ 2 ไม่ได้ถูกนำไปใช้หลังจากวันประกาศผลด่วน แม้จุดประสงค์คือส่งรหัสโหวตขึ้น Google Sheets ให้ทีมงานคนอื่นเห็นรหัสโหวตชุดนั้นร่วมกันได้ทันที แต่เจอปัญหาใหญ่คือติด rate limit API และทำเรื่องของ request จากทีม support ของ Google แล้วการตอบสนองไม่ทันต่อการใช้งาน (รอตอบกลับ 3 วัน) ผมจึงตัดสินใจย้ายไปใช้ฐานข้อมูลอย่าง MariaDB บน Cloud แทน แล้วเอารหัสโหวตที่ได้จาก OCR ใส่ย้อนหลับไปบน Google Sheets ด้วยมือ (Google Sheets API – Usage Limits = 500 requests per 100 seconds per project, and 100 requests per 100 seconds per user.)

ในขั้นตอน OCR จนได้รหัสโหวตมานี้ ช่วยลดจำนวนงานหลังบ้านที่จะต้องกรอกรหัสโหวตลงใน Google Sheets ได้เยอะมาก โดยเราเหลือกำลังคนไว้แก้รหัสโหวตที่ผิดพลาดประมาณ 15-20% ที่เหลือแทนได้

ในส่วนของ Script ที่เราใช้ส่งรูปขึ้น Google Cloud Vision API นั้น เราใช้ PHP ที่เขียนแบบ CLI เพื่อส่งไฟล์รูปข้างต้นขึ้น Google Cloud Vision API เพื่อให้ได้ Text ออกมา แล้วใช้ Regular expression กรองรหัสโหวตตาม pattern ที่กำหนดออกมา เป็นไฟล์แบบ CSV ไฟล์ (GitHub – Source Code)

เหตุผลที่เราใช้ CSV เพราะมันสามารถ import เข้าฐานข้อมูลผ่าน HeidiSQL เครื่องมือจัดการฐานข้อมูล MariaDB (ใช้งานกับ MySQL หรือ SQL Server ก็ได้) ได้ทันที และยังสามารถเปิดแก้ไขบน Spreadsheet อย่าง Microsoft Excel หรือ Google Sheets ได้ด้วย

โดยตัว HeidiSQL สามารถ export ตัวข้อมูลย้อนกลับมาเป็น CSV เพื่อนำไปทำงานบน Google Sheets ได้ทันที ทำให้เราไม่จำเป็นต้องใช้ Script อีกตัววิ่งส่งข้อมูลไปอัพเดทผ่าน Google Sheets API ตลอดเวลา และจุดสำคัญ การได้ CSV ไฟล์ดังกล่าว สามารถเอาไฟล์ CSV นั้นไปใช้กับโปรแกรมส่งรหัสโหวตอัตโนมัติที่เราเตรียมไว้ได้ด้วย

บางคนอาจจะคิดว่าทำไมไม่ใช้ฐานข้อมูลกลางเชื่อมต่อกันไปเลย ทำไมใช้ CSV โยนให้โปรแกรมส่งรหัสโหวตอัตโนมัติ?
– เหตุผลคือเรื่องกระจายเครื่องไปหลาย ๆ เครื่องเพื่อส่งรหัสโหวต ตัวโปรแกรมดังกล่าวติดตั้งง่ายไม่ซับซ้อนมาก และคัดลอกตัว Project และ CSV ของรหัสโหวต ปรับค่านิดหน่อย ก็เริ่มต้นทำงานได้แล้ว การเชื่อมฐานข้อมูลกลางอาจจะต้องทำ whitelist IP ฯลฯ อีกหลายตัวเพื่อป้องกันโดน hack อีกชั้น ซึ่งยุ่งยากเกินไป

สำหรับตัวโปรแกรมที่ใช้ในการส่งรหัสโหวตแบบอัตโนมัตินั้น ที่ชื่อ Katalon Studio พระเอกของงานนี้ ซึ่งเป็นเครื่องมือ automation testing solution ของนักพัฒนาซอฟต์แวร์ที่ โดยอ่านข้อมูลรหัสโหวตจากไฟล์ CSV ไปส่งลงฟอร์มของเว็บ AKB48

ตัว script ภายในเขียนด้วย groovy (GitHub – Source Code) ดักจับผลการส่งรหัสโหวตมี 4 สถานะดังนี้

  1. OK – รูปซ้ายบน
    เราดัก Keyword “投票完了” ที่หมายถึง Vote completed
    สถานะลงคะแนนโหวตสำเร็จ เก็บรวบรวมไปทำข้อที่ 2 อีกทีตอนที่ไม่มีรหัสโหวตส่งเข้าระบบเพื่อบันทึกวัน-เวลา และยืนยันผลอีกรอบ
  2. Already – รูปขวาบน
    เราดัก Keyword “入力したシリアルナンバーは既に投票済みです。” ที่หมาย The serial number you have entered has already been voted.
    เป็นสถานะที่บอกว่ารหัสโหวตนี้ถูกใช้งานกับผู้ลงเลือกตั้งคนนี้ โดยมีเวลากำกับ
    โดยเราจะต้องนำผลของหน้านี้ใช้ Regular expression เอาชุดข้อมูลวันและเวลาที่โหวตออกมาใส่ลงฐานข้อมูลด้วยเพื่อยืนยันวัน-เวลา
  3. Error – รูปขวาล่าง
    เราดัก Keyword “エラーが発生しました。” ซึ่งหมายถึง An error occurred.
    เกิดจากเว็บ AKB48 เกิดข้อผิดพลาด โดยถ้าเราได้ข้อความตัวนี้ คือโหวตไม่เข้า และเท่าที่เจอ คือรหัสโหวตใช้งานได้ เราต้องเอาไปเข้ากระบวนการสำหรับส่งรหัสโหวตเข้าเว็บอีกรอบ
  4. Failed – รูปซ้ายล่าง
    เราดัก Keyword “入力されたシリアルナンバーは無効であるか既に投票済みです。” ที่หมายถึง The serial number entered is invalid or already voted.
    ตรงนี้จะมี 2 ส่วน คือรหัสโหวตผิดจริง ๆ หรือรหัสโหวตถูกนำไปใช้กับผู้สมัครคนอื่นแล้ว หากรหัสโหวตถูกต้องโดยเทียบกับบัตรโหวต แสดงว่ารหัสโหวตใบนั้นถูกนำไปโหวตกับผู้สมัครคนใดคนหนึ่งที่ไม่ใช่คนที่เรากำลังโหวตอยู่ วิธีต่อไปคือเอารหัสดังกล่าวไปกรอกให้กับผู้สมัครคนอื่น ๆ ถ้าคนไหนขึ้นสถานะแบบข้อที่ 2. ก็คือรหัสโหวตนั้นถูกใช้โหวตผู้สมัครคนนั้นไปก่อนหน้านี้

รูปแบบหน้าทั้ง 4 หน้าที่จะเจอเมื่อเราส่งผลโหวต


จากการใช้ Katalon Studio เราจะเก็บผลการทำงานทั้ง HTML ไฟล์ และ Screenshot ของหน้าผลการโหวตเป็น JPEG ด้วย เพื่อใช้ในการตรวจสอบต่อไปหลังจบรอบโหวต

ในช่วงก่อนประกาศผลด่วนเราไม่ได้ตรวจสอบเคสในข้อที่ 3. และ 4. แยกออกจากกัน ทำให้เราพลาดคะแนนบางส่วนไปเพราะเว็บรับรหัสโหวต AKB48 ไม่ได้เสถียรตลอดเวลา จะมีการส่ง “An error occurred.” ออกมาอยู่เรื่อยๆ แม้แต่ช่วงวันท้าย ๆ ก็ยังไม่ได้แก้ไขให้ดีขึ้น มีอยู่หลายช่วงที่เราส่งรหัสโหวตไปกว่า 1,000 รายการ แล้วโดนตีตกด้วย An error occurred. อยู่เกือบ 600 รายการ และสุดท้ายทั้งหมดที่โดนตีตกเป็นรหัสโหวตที่ใช้งานได้ทุกตัว ทำให้เราต้องคัดแยกเพื่อให้ทีมหลังบ้านที่อ่านรหัสโหวตผิดพลาดไม่ต้องไปอ่านข้อมูลที่เกิดจากตัวเว็บ AKB48 แจ้งความผิดพลาดทั้ง ๆ ที่รหัสโหวตไม่ผิดอีก เพื่อลดงานฝั่งคนแก้ไขรหัสโหวตลง

เมื่อรหัสโหวตทุกส่วนส่งครบหมดจะเหลือเฉพาะรหัสโหวตที่โหวตได้ และรหัสโหวตที่โหวตไม่ได้ เราจะเอา log ของการส่งรหัสโหวตครั้งนั้นมาอ่านด้วย PHP ที่เป็น script ตัวอ่าน log แล้วเข้าไป flag สถานะในฐานข้อมูลตามแต่ละรหัสโหวตที่มี เพื่อบอกว่าโหวตสำเร็จหรือไม่ แล้วทำการสรุปรหัสโหวตที่โหวตได้ และรหัสโหวตที่โหวตไม่ได้ แยก Worksheet บน Google Sheets ออกจากกัน โดยในส่วนของ Worksheet ที่ใส่รหัสโหวตที่ส่งแล้วผิดพลาด จะมีทีมงานอีกส่วนเข้ามาช่วยกันอ่านไฟล์รูปบัตรโหวตและกรอกรหัสโหวตที่ถูกต้องลงไปแทน แล้วเมื่อจบการแก้ไขในแต่ละ Worksheet จะรวบรวมแล้วใช้โปรแกรมอัตโนมัติส่งเข้าเว็บโหวตอีกรอบ และในส่วนรหัสโหวตที่โหวตเรียบร้อย จะมีรอบสำหรับทบทวนวัน-เวลาที่โหวตเพื่อยืนยันรหัสโหวตว่าเมื่อโหวตเข้าไปแล้ว

โดยในขั้นตอนทบทวนวัน-เวลา เราจะใช้ script ส่งรหัสโหวตชุดเดิมส่งรหัสโหวตที่ต้องการวัน-เวลาส่งเข้าไปที่เว็บ AKB48 จนได้สถานะตามข้อที่ 2 แล้วใช้ script อีกชุดเข้าไปอ่านวัน-เวลาในไฟล์ HTML ที่บันทึกไว้ เพื่อนำไปอัพเดทลงฐานข้อมูลเมื่ออัพเดทเสร็จครบทั้งสถานะและวัน-เวลาโหวต เราจะเอาผลทั้งหมดกลับขึ้นไปที่ Google Sheets เพื่อสรุปผลการโหวตในแต่ละรอบเพื่อปิดงานรอบนั้น (ในขั้นตอนทบทวนวัน-เวลานี้เราเอารหัสโหวตที่กรอกด้วยมือไปก่อนหน้านี้ของอีกทีมหนึ่ง มาเข้ากระบวนการนี้ด้วยเช่นกัน)

นั้นหมายความว่า ทุก ๆ รหัสโหวตเราส่งเข้าเว็บ AKB48 เราจำเป็นต้องส่งรหัสโหวตเข้าเว็บโหวตอย่างน้อย 2 ครั้ง แต่ผลดีคือ มันช่วยทำให้เราสรุปยอดในแต่ละวันว่าเราส่งรหัสโหวตเข้าไปได้เท่าไหร่ และช่วยให้เราเก็บคะแนนที่ตกหล่นกลับมาโหวตได้อีกพอสมควร

ตัวอย่างการทำงานในการส่งรหัสโหวตด้วย Katalon Studio

สำหรับหน้ารายงานรหัสโหวต และจำนวนโหวตที่ Actual Vote ช่วงแรกเราใช้ Firebase Realtime Database ซึ่งทำการ Sync ข้อมูลกับ Google Sheetes อีกที ช่วงแรกข้อมูล Realtime มาก กดอัพเดทจำนวนคะแนนฝั่งหน้าเว็บรายงานขึ้นคะแนนใหม่ทันที แต่ด้วยความที่เราไม่ได้ optimize อะไรเลย (คือไม่มีเวลาทำ) สุดท้ายมันก็ไม่ได้ Realtime ตลอด เจออาการ Push ไม่ทำงาน เพราะเราไม่ได้ Index ข้อมูล มันเลยหยุด Push เพราะด้วยจำนวนของ node (รหัสโหวต) เริ่มเยอะขึ้น แถมเราเจอ charge ค่า B/W ของ Firebase เยอะตามไปด้วย เลยเปลี่ยนแผนใหม่เป็นการใช้ไฟล์ JSON data แบบอัพมือแทน โดยก็แค่ Sync จาก Google Sheets ไป export เป็นไฟล์ JSON data เดี่ยว ๆ แล้วฝั่งทีมเว็บส่วนรายงานผลแค่เอาไฟล์ไปวางที่เดิมก็จบงาน ลดค่าใช้จ่ายไปได้เยอะมาก แต่ก็มาหนักฝั่ง client ซึ่งก็เป็นเรื่องที่ช่วยไม่ได้ เพราะเอาเร็วเข้าว่า แล้วช่วง 2-3 วันสุดท้ายเราไม่ได้รายงานคะแนนสุดท้าย เพราะคิดว่ารอสรุปยอดทีเดียวหลังปิดโหวตดีกว่า เพื่อให้ทีมงานทุกส่วนได้โฟกัสกับการหาบัตรโหวต และส่งรหัสโหวตเข้าระบบ AKB48 ให้ได้จนหมดโดยไม่ตกหล่น และยืนยันผลให้พร้อมทุกอย่าง เพราะเราพลาดแบบรอบผลด่วนอีกไม่ได้แล้ว

ในส่วนของเครื่องคอมฯ ที่ส่งรหัสโหวตนั้น เราใช้ทั้งหมด 3 ตัวทำงานสลับกัน มี 1 ตัวทำงานตลอด 24 ชั่วโมง 5 วันติดต่อกันเพื่อโหวตเข้าระบบ และทบทวนผลการโหวตออกมาเป็นวัน-เวลาที่โหวตเพื่อให้แน่ใจว่าคะแนนทุกคะแนนที่ถืออยู่จะเข้าระบบจริง ๆ ซึ่งหากจำนวนคะแนนในมือเยอะกว่านี้ อาจส่งไม่ทัน เพราะจากที่ลองทดสอบค่าเฉลี่ยนในการส่งโหวต สามารถทำความเร็วได้ที่ 600-800 รหัสโหวตต่อชั่วโมง (อย่าลืมว่าเราต้องเก็บตกจากเหตุการณ์เจอหน้าเว็บ Error และทวนวัน-เวลาโหวตอีก) แต่เราก็ได้เตรียมแผนรองรับไว้แล้ว ด้วยการเตรียมเช่า Cloud VPS ที่อยู่ญี่ปุ่นเพิ่มเติมสำหรับส่งรหัสโหวตเพิ่มเติมได้ทันที (คิดว่าภายใน 4-6 ชั่วโมงน่าจะสร้างเครื่อง และพร้อมส่งรหัสโหวตได้อย่างน้อย 4 ตัว หรือเพิ่มความเร็วเป็น 2,000-3,000 โหวตต่อชั่วโมง)

สรุปว่าโครงการนี้เน้นถึกเยอะมาก script อะไรต่าง ๆ บางส่วนก็เผา และ workaround กันแบบสุด ๆ เนื่องจากรีบ และไม่มีเวลามาคิดเรื่อง seamless มากนักในบางขั้นตอน (เพราะงานประจำก็ต้องทำ คะแนนที่ต้องส่งก็เยอะขึ้นกว่าที่คาดหวังไว้ด้วย ต้องเผื่อเวลาตกหล่นไว้อย่างน้อย 1-2 วัน) ตามตารางกราฟด้านล่าง

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

แล้วสุดท้ายก็เป็นแบบวิดีโอข้างล่างเนี่ยแหละครับ

หากมีอะไรอัพเดทหรือตกหล่น เดี่ยวค่อย ๆ อัพเดทใน blog ตอนนี้เพิ่มเติมอีกที เพราะตอนนี้นึกออกมาได้ประมาณนี้

ทิ้งท้าย ด้านล่างคือสรุป Workflow การทำงานในช่วง 7 วันสุดท้ายของการโหวต