เราจะแยกตรรกะทางธุรกิจจากการเรียก API ได้อย่างไร

แรงจูงใจและภาพรวม

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

ข้อความค้นหาเหล่านั้นมีลักษณะอย่างไร

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

  1. การเรียกวิธีการ ที่จริงแล้วการเรียกเมธอดสามารถส่งพารามิเตอร์ได้หนึ่งตัว พารามิเตอร์นี้สามารถเป็นสตริง บูลีน ตัวเลข อาร์เรย์ หรือวัตถุ
    methodName ~ {"key" : "val"};
  2. เงื่อนไข. ดำเนินการแบบสอบถามย่อยตามเงื่อนไข ข้อความค้นหาย่อยควรขึ้นต้นด้วย @{;และลงท้ายด้วย };
    ? $varName == "value" @{;
    $result = method ~ $varName;
    } : @{;
    $result = method2 ~ $varName;
    };
  3. กำหนด. การกำหนดค่าให้กับตัวแปร นั่นคือวิธีที่เราสามารถบันทึกข้อมูลเพื่อใช้ต่อไปได้ ชื่อตัวแปรแต่ละตัวควรขึ้นต้นด้วย “$”
    $varName = "value"
  4. ส่งคืนค่า สิ้นสุดแบบสอบถาม ส่งกลับค่า
    =>$reuslt;

ตัวดำเนินการภายในบรรทัดจะถูกดำเนินการตามลำดับที่แสดงด้านบน เราสามารถใช้วงเล็บ () เพื่อเปลี่ยนลำดับได้ นอกจากนี้ เราควรใช้วงเล็บในขณะที่เรียกตัวดำเนินการในการกำหนดวัตถุ JSON:
=>{"key" : (method ~ "val")};

ตัวอย่าง:

$result = method ~ {"key" : "val"}; 
? $result.success == true @{;
    =>$result;
} : @{;
    writeErrorLog ~ $result.error;
    => {
        "success" : false, 
        "error" : "Error during calling /"method/""
   };
};

วิธีการจัดการและการมอบหมาย ดำเนินการสอบถาม

อินสแตนซ์หนึ่งสามารถจัดการวิธีการบางอย่างและมอบหมายวิธีอื่นได้ ถ้าวิธีการได้รับมอบสิทธิ์ การโทรกลับจะได้รับชิ้นส่วนตามวิธีการที่ได้รับมอบสิทธิ์ มิฉะนั้น การโทรกลับจะได้รับเฉพาะพารามิเตอร์ที่กำหนดไว้ในการเรียกเมธอดและชื่อเมธอด

กำลังมอบหมาย

เพื่อมอบหมายวิธีการเราควรเรียกวิธีการ "มอบหมาย" ของอินสแตนซ์

ผู้รับมอบสิทธิ์(ตัวเลือก : วัตถุ) : เป็นโมฆะ
options.regExp : RegExp วิธีการที่ตรงกับ regExp จะได้รับการมอบหมาย
options.handle : Function(query : String) ฟังก์ชันเรียกกลับ

การจัดการ

หากเราต้องการจัดการเมธอดตามอินสแตนซ์ปัจจุบัน เราควรเรียกเมธอด addHandler ของอินสแตนซ์

addHandler(options : object) : void
options.regExp : RegExp วิธีการที่ตรงกับ regExp จะถูกประมวลผลโดยตัวจัดการปัจจุบัน
options.handle : Function(param, methodName) ฟังก์ชันโทรกลับ

addHandlers(Handlers : Array) : void
เพิ่มตัวจัดการหลายตัว

ดำเนินการสอบถาม

เพื่อดำเนินการค้นหา เราเรียกวิธีการ "เรียก" ของอินสแตนซ์

call(query : String) : Promise
query : String แบบสอบถามที่เราต้องการดำเนินการ

ลำดับการดำเนินการแบบสอบถาม

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

  1. สร้างก้อน
  2. ดำเนินการก้อนข้อมูลในเครื่องหรือส่งไปยังอินสแตนซ์อื่น
  3. ผลลัพธ์ของกระบวนการ
  4. ไปที่ข้อ 1 หากไม่เสร็จสิ้น

การแยกและการกำหนดตัวแก้ไข

ในระหว่างการประมวลผล แบบสอบถามจะถูกแบ่งออกเป็นส่วน ๆ ตามวิธีการที่ได้รับมอบสิทธิ์ ในขณะที่แยก เราพยายามลดจำนวนชิ้นข้อมูลและส่งผลให้จำนวนคำขอ API ที่เป็นไปได้ เนื่องจากการสืบค้นอาจมีเงื่อนไข อาจมีบล็อกที่ซ้อนกันและความจำเป็นในการจัดการกรณีต่างๆ เมื่อชิ้นส่วนสิ้นสุดในบล็อกที่ซ้อนกันดังกล่าว เพื่อจัดการกับความท้าทายนี้ เราได้เพิ่มโอเปอเรเตอร์อื่น ->@_bookmark ซึ่งกลับมาที่บุ๊กมาร์ก ตัวดำเนินการนี้จะถูกวางโดยอัตโนมัติในระหว่างการแยกชิ้นส่วน หากชิ้นปัจจุบันส่งคืนบุ๊กมาร์ก การเรียกใช้โค้ดเพิ่มเติมควรเริ่มต้นจากบรรทัดที่ระบุในบุ๊กมาร์ก ตัวอย่างเช่น:

$res1 = resolver1.method1 ~ "string";
? $res1.success == true @{;
    resolver1.method2 ~ "anotherString";
    $res2 = resolver2.method1 ~ $res1;
    ? res2.success @{;
        resolver1.method3 ~ $res2;
    };
    =>resolver2.method2 ~ $res2;
};
=>resolver1.method4 ~ $res1;

สำหรับแบบสอบถามดังกล่าว solver1 จะได้รับถัดไป:

$res1 = resolver1.method1 ~ "string";
? $res1.success == true @{;
    resolver1.method2 ~ "anotherString";
    ->@_0;
};
=>resolver1.method3 ~ $res1;

จากนั้นถ้า $res1.success จะเป็น false solver2 จะไม่ถูกเรียก มิฉะนั้นจะได้รับ:

$res2 = resolver2.method1 ~ $res1;
? res2.success == true @{;
    ->@_1;
};
=>resolver2.method2 ~ $res2;

และถ้า $res2.success เป็นเท็จ solver1 จะได้รับการเรียกครั้งสุดท้าย:

resolver1.method3 ~ $res2;
=>resolver1.method4 ~ $res1;

$res1 และ $res2 จะถูกแทนที่ด้วยข้อมูลจริง

อัลกอริธึมการกำหนดการแยกแบบสอบถามและตัวแก้ไขทั้งหมดมีลักษณะดังนี้:

กรณีการใช้งาน

  1. เรามีไคลเอนต์ที่โต้ตอบกับ API หลายตัว API เหล่านั้นจะแสดงเป็นจุดสิ้นสุด REST และ/หรือ GraphQL ในกรณีนี้ ลูกค้าของเราใช้ Limbo เป็นจุดเดียวในการรับและจัดการข้อมูลจาก API เหล่านั้น

2. เรามีเซิร์ฟเวอร์ที่รับคำถามและประมวลผล

กรณีการใช้งานเหล่านั้นสามารถนำมารวมกันได้ ลูกค้ารายหนึ่งสามารถเรียก API ที่ใช้ Limbo และเรียก API ที่ไม่ได้ใช้งาน ในเวลาเดียวกันเซิร์ฟเวอร์สามารถเรียกใช้ API อื่น ๆ และมอบหมายการสืบค้นให้กับพวกเขาได้

ข้อสรุป

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

เนื่องจากเป็นเพียงการพิสูจน์แนวคิด จึงยังมีช่องว่างสำหรับการปรับปรุง เช่น:

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

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