graphql - المزالق

ربما لا توجد تقنيات مثالية. Graphql ليست استثناء. إذا لم تكن لديك خبرة في هذه التقنية ، فأنت بحاجة إلى أن تكون لديك فكرة جيدة عن المشكلات التي قد تواجهها والاستعداد لها مقدمًا.

بادئ ذي بدء ، أقول إنني أكثر من داعم من الخصم لاستخدام graphql حولها حيثما أمكن ذلك. ولن أثني أي شخص على الإطلاق عن مدى ملاءمة استخدام هذه التكنولوجيا. وهذا هو السبب في أنني أطرح أسئلة تتعلق بقضايا لم تحل في إطار تقنية graphql.

على سبيل المثال ، بالنسبة لشخص ما ، قد يكون من غير المتوقع أن يتم وصف كل كائن في graphql مرتين على الأقل: مرة واحدة كنوع إرجاع للكائن ، ومرة ​​أخرى كنوع إدخال الكائن (انظر graphql.org/graphql-js/mutations- وأنواع المدخلات ). ومع ذلك ، قلت هذا لتبدأ ولا تعتبره عيبًا كبيرًا. سنركز اليوم على مثل هذه القضايا ، كقاعدة عامة ، يجب حلها عند تطوير تطبيق باستخدام تقنية graphql:

  1. فصل الوصول للمستخدمين ومجموعات المستخدمين.
  2. خطأ في التعامل.
  3. اختر مشكلة N + 1

فصل الوصول للمستخدمين ومجموعات المستخدمين


graphql لا يعرف أي شيء عن مشاركة الوصول بين المستخدمين والمجموعات. وبالتالي ، فإن كل عمل مشاركة الوصول هو مسؤولية مطور التطبيق. تقوم المعلمة الثالثة بتمرير كائن سياق التطبيق إلى وظيفة محلل البيانات. لذلك ، إذا كنت ، على سبيل المثال ، تعمل مع تطبيق graphql JavaScript + Express ، فيمكنك الحصول على المستخدم الحالي من كائن طلب express.js في معلمة السياق. ولكن يجب إجراء مزيد من العمل بشأن التحكم في الوصول مباشرة في كل محلل:

function(root, {id}, ctx) { return DB.Lists.get(id) .then( list => { if(list.owner_id && list.owner_id != ctx.userId){ throw new Error("Not authorized to see this list"); } else { return list; } }); } 

بطبيعة الحال ، هذا النهج يعقد التحكم في الوصول ل لا توجد طريقة لتعيين حقوق الوصول بطريقة تصريحية ، وتشتت السيطرة على الحقوق على العشرات (بالنسبة لبعض الأنظمة الكبيرة ، على الآلاف) من وظائف محلل البيانات. لذلك ، هناك عدد من المكتبات التي تحل هذه المشكلة. بعضها مشهور جدًا (وفقًا لعدد النجوم على github.com) ، على سبيل المثال github.com/maticzav/graphql-shield .

خطأ في التعامل


إذا كانت الواجهة الأمامية الخاصة بك تتطلب التحقق من صحة المدخلات وتشكيل رسائل مفصلة لكل حقل لم يجتز التحقق منه ، فمن المرجح أن معالجة الأخطاء في graphql لن تكون مرنة على الأرجح بالنسبة لك. على سبيل المثال ، إذا تم وصف معلمة الإدخال كسلسلة وتم تلقي قيمة رقمية ، فستكون رسالة الخطأ ذات فائدة تذكر لهذا:

 { "errors": [ { "message": "Expected type String, found 1.", "locations": [ { "line": 2, "column": 15 } ] } ] } 

إذا كان هناك خطأ فادح في نوع معلمة الإدخال ، فسيتم إنشاء رسالة خطأ تلقائيًا ولا توجد طريقة للتحكم في هذه العملية. إذا نجحت عملية التحقق من الصحة حسب نوع معلمة الإدخال ، فمن الممكن إرسال رسالة خطأ مخصصة إلى العميل عن طريق طرح كائن new Error ('custom message ...') . لن تعمل على إضافة حقول مخصصة إلى كائن الخطأ (يتم تطبيق تخصيص الأخطاء في مكتبات apollo-server-express و apollo-errors عند استخدامها معًا). بالطبع ، هناك دائمًا فرصة لتسلسل الكائن إلى سلسلة message على الخادم وإلغاء تسلسلها على العميل. ولكن هل من الضروري القيام بذلك؟

اختر مشكلة N + 1


نوقشت هذه المشكلة بالتفصيل في الرسالة .

بنيت graphql على وظائف محلل. هذا يعني أن جلب البيانات من قاعدة البيانات يمكن أن يسبب مشكلة تسمى SELECT N + 1. لنفترض أنه في وظيفة المصلح تم الحصول على قائمة بالكائنات التي يتم فيها تمثيل البيانات المرتبطة بهذا الكائن بمعرفات (مفاتيح خارجية). لكل معرف من هذا القبيل ، سيتم استدعاء محلل الوظيفة الخاص به ، والذي (في كل) سيتم تقديم طلب إضافي إلى قاعدة البيانات. وبالتالي ، بدلاً من استعلام قاعدة بيانات واحدة (باستخدام SQL JOIN) ، سيتم تنفيذ العديد من الاستعلامات ، مما يزيد من تحميل قاعدة البيانات باستعلامات.

لحل هذه المشكلة ، طور facebook مكتبة github.com/graphql/dataloader ، التي تستخدم استراتيجية طلب معلقة. بدلاً من تنفيذ الطلب مباشرة في محلل الوظيفة ، يُقترح تجميع المعرفات (المفاتيح الثانوية) في الصفيف ، ثم استلامها فورًا مع طلب واحد.

apapacy@gmail.com
13 مايو 2019

Source: https://habr.com/ru/post/ar451466/


All Articles