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

Aug 18 2020

ฉันมีเว็บไซต์ที่อัปโหลดประกาศรับสมัครงานไปยัง API ของฉันมีหลายขั้นตอนในการดำเนินการนี้:

  1. อัปโหลดภาพโลโก้ไปยังที่เก็บไฟล์

  2. แทรกข้อมูลเกี่ยวกับประกาศรับสมัครงานลงในฐานข้อมูล

  3. ดำเนินการชำระเงินกับผู้ให้บริการบุคคลที่สาม

  4. ส่งอีเมลผ่านผู้ให้บริการบุคคลที่สาม

โดยทั่วไปคุณสามารถจินตนาการถึงขั้นตอนอื่น ๆ ที่มีอยู่ที่นี่ในแอปพลิเคชันต่างๆเช่นการรับข้อมูลบางอย่างจาก API ของบุคคลที่สามการตรวจสอบ ReCAPTCHA การอัปเดต Google Indexing API การส่ง SMS ฯลฯ เป็นต้น

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

คำถามของฉันคือข้อผิดพลาดในการดำเนินการหลายขั้นตอนประเภทนี้ระหว่างไคลเอนต์และเซิร์ฟเวอร์โดยทั่วไปจะจัดการในระบบการผลิตอย่างไร มีมาตรฐานหรือแนวทางปฏิบัติที่เป็นที่ยอมรับหรือไม่?


ฉันได้พิจารณา:

  1. ไม่จัดการข้อผิดพลาดและหวังว่าทุกอย่างจะผ่านพ้นไปโดยไม่มีข้อผิดพลาด

  2. การกำหนดฟังก์ชัน 'เลิกทำ' บนแบ็กเอนด์สำหรับแต่ละขั้นตอนและหากขั้นตอนใดขั้นตอนหนึ่งล้มเหลวให้เรียกสิ่งนั้นในขั้นตอนก่อนหน้านี้ ด้วยการดำเนินการที่ประกอบด้วยหลายขั้นตอนสิ่งนี้สามารถเปลี่ยนเป็นรหัสสปาเก็ตตี้ได้อย่างรวดเร็วและบางขั้นตอนไม่สามารถยกเลิกได้อย่างง่ายดายเช่นการส่งอีเมล

  3. การสร้างจุดสิ้นสุดแยกต่างหากบนแบ็กเอนด์สำหรับแต่ละขั้นตอนและปล่อยให้ไคลเอนต์โทรหาทีละรายการ นอกจากนี้ยังสามารถใช้จุดสิ้นสุด API 'เลิกทำ' ได้ดังนั้นหากไคลเอ็นต์ได้รับข้อผิดพลาดในขั้นตอนใดขั้นตอนหนึ่งก็สามารถยกเลิกขั้นตอนก่อนหน้านี้ทั้งหมดได้ สิ่งนี้มีข้อดีคือช่วยให้ลูกค้าสามารถประเมินความคืบหน้าของการดำเนินการที่เสร็จสมบูรณ์กล่าวคือสามารถแสดง '1 จาก 5 ขั้นตอนที่เสร็จสมบูรณ์' ให้กับผู้ใช้

  4. การสร้างแถวใน DB (หรือฐานข้อมูลในหน่วยความจำ?) สำหรับแต่ละการกระทำและเมื่อแต่ละขั้นตอนเสร็จสมบูรณ์แล้วให้ทำเครื่องหมายคอลัมน์ที่เกี่ยวข้องว่าเสร็จสมบูรณ์ เมื่อทุกคอลัมน์ในแถวเสร็จสมบูรณ์แล้วให้ส่งคำตอบกลับไปยังผู้ใช้

คำตอบ

1 RalfKleberhoff Aug 19 2020 at 13:30

กระบวนการหลายขั้นตอนนี้เป็นการทำธุรกรรมโดยเปลี่ยนจากสถานะเริ่มต้นที่สอดคล้องกัน ("ไม่มีอะไรเกิดขึ้น") ไปเป็นสถานะสุดท้าย ("ประกาศรับสมัครงานเสร็จสิ้น") โดยมีขั้นตอนกลางที่ทำให้แอปของคุณอยู่ในสถานะที่ไม่สอดคล้อง

คุณไม่ควรมอบหมายการจัดการธุรกรรมให้กับลูกค้าของคุณโดยเฉพาะอย่างยิ่งอย่าแยกกระบวนการออกเป็นการโทรแต่ละครั้ง (มิฉะนั้นเขาอาจจะข้ามขั้นตอนการชำระเงินซึ่งไม่ดีต่อธุรกิจ)

หากขั้นตอนหนึ่งล้มเหลวการดำเนินการต่อเป็นเรื่องไร้สาระอย่างแน่นอนคุณต้องย้อนกลับไปยังสถานะที่ยอมรับได้ไม่จำเป็นต้องเป็นสถานะเริ่มต้น เช่นฉันไม่เห็นความจำเป็นอย่างยิ่งที่จะต้องลบภาพที่อัปโหลดออกจากที่เก็บไฟล์

ก่อนอื่นฉันพยายามจัดเรียงขั้นตอนในลักษณะที่ขั้นตอนกลางส่วนใหญ่ยอมรับได้ดังนั้นจึงไม่จำเป็นต้องย้อนกลับ

ขั้นตอนที่ยุ่งยากก็คือการชำระเงินและอีเมล (ถ้าฉันเข้าใจธุรกิจของคุณถูกต้อง)

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

เนื่องจากคุณต้องพึ่งพาการเชื่อมต่อภายนอกฉันไม่เห็นวิธีที่จะหลีกเลี่ยงการทำธุรกรรมของคุณให้เสร็จสมบูรณ์บางส่วนได้อย่างแน่นอนดังนั้นฉันจึงออกแบบกระบวนการในลักษณะที่ทำให้เกิดความล้มเหลวระหว่างกลาง

  • ไม่น่าเป็นไปได้สูง
  • หรือออกจากสถานะที่ยอมรับได้

ฉันจะ

  1. ปิงบริการจากประสบการณ์ทั้งหมดเพื่อให้แน่ใจว่าพร้อมใช้งานและเข้าถึงได้ในขณะนี้
  2. อัปโหลดภาพโลโก้ไปยังที่เก็บไฟล์
  3. แทรกข้อมูลเกี่ยวกับประกาศรับสมัครงานลงในฐานข้อมูล
  4. ส่งอีเมลผ่านผู้ให้บริการบุคคลที่สาม
  5. ดำเนินการชำระเงินกับผู้ให้บริการบุคคลที่สาม

ขั้นตอนการย้อนกลับจะเป็น

  • ลบภาพออกจากที่เก็บไฟล์
  • ลบประกาศรับสมัครงานออกจากฐานข้อมูล
  • หากส่งอีเมลไปแล้ว แต่การชำระเงินล้มเหลวให้ตั้งเวลาคำขอชำระเงินเพื่อลองอีกครั้งในภายหลัง
JacquesB Aug 18 2020 at 21:56

"ดีที่สุด" เห็นได้ชัดขึ้นอยู่กับข้อกำหนด หมายเลข 1 นั้นง่ายที่สุดในการนำไปใช้ แต่ธุรกรรมจะสูญหาย / ไม่สมบูรณ์ในกรณีที่เกิดข้อผิดพลาด บางทีนี่อาจเป็นการแลกเปลี่ยนที่ยอมรับได้จากมุมมองทางธุรกิจ?

วิธีแก้ปัญหาที่มีประสิทธิภาพที่สุดคือการแบ่งกระบวนการออกเป็นชุดขั้นตอนโดยแต่ละขั้นตอนคือธุรกรรม ธุรกรรมจะเสร็จสมบูรณ์หรือล้มเหลวและหากล้มเหลวสามารถลองใหม่ได้อย่างปลอดภัย (ตัวอย่างเช่นการส่งเมลหรือ sms จะเป็นการทำธุรกรรม) แถวฐานข้อมูลจะติดตามว่าขั้นตอนใดเสร็จสมบูรณ์แล้ว

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

การสนับสนุนการเลิกทำมีความซับซ้อนมากขึ้นและ (ตามที่คุณสังเกตเห็น) ไม่สามารถทำได้เสมอไป หากบางขั้นตอนสามารถล้มเหลวในลักษณะที่กระบวนการทั้งหมดควรถูกปฏิเสธ (เช่นกรณีที่บัตรเครดิตไม่สามารถใช้ได้) ฉันคิดว่าควรดำเนินการในขั้นตอนการตรวจสอบความถูกต้องก่อนที่กระบวนการหลายขั้นตอนจะเริ่มขึ้น วิธีนี้จะช่วยให้คุณสามารถให้ข้อเสนอแนะแบบซิงโครนัสแก่ลูกค้าและให้ลูกค้าตรวจสอบและป้อนข้อมูลอีกครั้ง

AdrianL Aug 27 2020 at 01:00

ตามที่คนอื่น ๆ กล่าวไว้คุณควรรวมชิ้นส่วนทั้งหมดที่จำเป็นสำหรับการโพสต์งานที่ประสบความสำเร็จและให้ลูกค้าส่งไปยังแบ็กเอนด์ของคุณในคำขอเดียว ในฐานะนักพัฒนาอุปกรณ์เคลื่อนที่เองฉันมักจะสนับสนุนให้ลูกค้าทำงานให้น้อยที่สุดเท่าที่จะทำได้เพื่อรักษาปริมาณการใช้ข้อมูลและอายุการใช้งานแบตเตอรี่

สำหรับแบ็กเอนด์ฉันขอแนะนำให้ลองแทรกข้อมูลที่สำคัญที่สุดลงใน db ก่อนจากนั้นลองเช่นการแทรกข้อมูลเสริมหลังจากนั้นเช่นภาพโลโก้