اشتراكات GraphQL والأنماط المتقدمة
اشتراكات GraphQL والأنماط المتقدمة
تتناول هذه الدرس أربع قدرات GraphQL على مستوى الإنتاج: البيانات الفورية عبر @Subscription وPubSub، وحلّ العلاقات المتداخلة بـ @ResolveField، والقضاء على مشكلة N+1 الشهيرة بـ DataLoader، وإعادة الأخطاء المنظّمة عبر معالجة أخطاء GraphQL. تجتمع هذه المفاهيم لترفع الواجهة البرمجية من مستوى أساسي إلى جودة المؤسسات.
البث الفوري بـ @Subscription وPubSub
تدفع الاشتراكات البيانات إلى العملاء عبر اتصال WebSocket دائم. يربطها NestJS بواسطة @Subscription() على دالة المُحلِّل وكائن PubSub الذي يعمل كحافلة أحداث داخل العملية. لعمليات النشر ذات الخادم الواحد، تكفي PubSub المدمجة من graphql-subscriptions؛ أما في البيئات متعددة العُقد فاستبدلها بـ pub/sub مدعوم بـ Redis.
installSubscriptionHandlers: true (Apollo Server 2) أو إضافة subscriptions-transport-ws أو graphql-ws مُهيَّأة على GraphQLModule. بروتوكول HTTP وحده لا يستطيع دفع البيانات إلى العملاء.
حلّ الأنواع المتداخلة بـ @ResolveField
يعلّم @ResolveField() نظامَ NestJS كيفية ملء حقل لا توجد قيمته مباشرةً على الكيان الأصل — مثل جلب كائن author كلّما أُعيد Post. تتلقّى الدالة الكائنَ الأصلَ كوسيط أول (يُحقَن بـ @Parent()) لتنفّذ بحثًا مستهدفًا:
مشكلة N+1 وDataLoader
تنشأ مشكلة N+1 حين يُطلق جلب قائمة من N منشورات استعلامًا منفصلًا عن المؤلّف لكلّ منشور، ما يُنتج استعلام قائمة واحدًا + N استعلامًا للمؤلّفين. يحلّ DataLoader هذا بـالتجميع: يجمع كل معرّفات المؤلّفين المُجمَّعة خلال دورة تنفيذ GraphQL واحدة في استعلام واحد، ثم يوزّع النتائج على كلّ مُحلِّل.
- التثبيت:
npm install dataloader - أنشئ مُحمِّلًا يقبل مصفوفة من المعرّفات ويُعيد مصفوفة كيانات بالترتيب ذاته.
- اجعل نطاق المُحمِّل الطلب (استخدم مزوّدًا بنطاق
REQUESTأوDataLoaderInterceptorفي NestJS) ليكون التجميع لكل طلب وليس عالميًا.
معالجة أخطاء GraphQL
ينبغي أن تكون أخطاء GraphQL ذات معنى ومُصنَّفة. يُمرّر NestJS استثناءاته (مثل NotFoundException) إلى مصفوفة errors في الاستجابة، لكن يمكنك أيضًا رمي GraphQLError مباشرةً للحصول على رموز خطأ أكثر ثراءً للعميل:
- رمي استثناءات NestJS — تُترجَم تلقائيًا إلى أخطاء GraphQL مع الحفاظ على الرسالة.
- رموز خطأ مخصّصة — استخدم
extensions.codeعلىGraphQLErrorليتمكّن العملاء من التمييز بين أنواع الأخطاء برمجيًا. - تنسيق الأخطاء عالميًا — هيّئ
formatErrorعلىGraphQLModuleلحذف تتبّع المكدّس في الإنتاج.
formatError لإعادة رسالة آمنة فقط ورمز قابل للقراءة آليًا. سجّل التفاصيل الكاملة على جانب الخادم.
الخلاصة
يُرسل @Subscription + PubSub الأحداث الفورية عبر WebSockets؛ استبدل بـ Redis PubSub للنشر متعدد العُقد. يملأ @ResolveField الأنواع المتداخلة بنظافة. يُجمِّع DataLoader (بنطاق REQUEST) الاستعلامات المتداخلة ويُزيل مشكلة N+1. تحمي معالجة الأخطاء المنظَّمة بـ formatError العملاءَ من تسرّب التفاصيل الداخلية مع توفير رموز قابلة للتنفيذ. هذه الأنماط الأربعة هي أساس واجهات NestJS GraphQL الجاهزة للإنتاج.