تسليم إشعارات مبسطة لعمليات الإدخال المجمعة
تخيل أنك تدير نظامًا يتم فيه تعيين قسائم لمئات الموظفين بناءً على معايير مختلفة مثل القسم أو الدرجة أو الخبرة. إنها مهمة هائلة لإخطار كل موظف بكفاءة دون التسبب في اختناقات في النظام. 🔔 يصبح هذا التحدي أكثر صعوبة عندما تهدف إلى تجنب تعقيدات المقابس أو آليات الاقتراع.
في مثل هذه السيناريوهات، تظهر الأحداث من جانب الخادم (SSE) كحل قوي ومباشر. من خلال الاستفادة من SSE في تطبيق NestJS الخاص بك، يمكنك إنشاء قناة اتصال في الوقت الفعلي لإخطار مجموعات محددة من الموظفين بناءً على معايير ديناميكية. على سبيل المثال، عندما يتم تخصيص القسائم لقسم المبيعات، يجب أن يتلقى هؤلاء الموظفون فقط الإخطارات، مما يضمن تحديثات دقيقة وذات معنى.
من خلال هذه المقالة، سنتعمق في مثال عملي يوضح كيفية دمج SSE في عملية الإدراج المجمعة باستخدام NestJS. سنتعرف على دورة الحياة، بدءًا من تشغيل الأحداث في الواجهة الخلفية وحتى الاستماع إلى التحديثات على الواجهة الأمامية، كل ذلك مع الحفاظ على الأداء السلس. 💼
سواء كنت تقوم بتطوير أداة للموارد البشرية أو تطبيق مالي، فإن فهم سير العمل هذا سيمكنك من تقديم إشعارات مخصصة في الوقت الفعلي. دعنا نكشف عن بساطة SSE وكيف يمكنها تحسين تجربة مستخدم التطبيق الخاص بك.
يأمر | مثال للاستخدام |
---|---|
@Sse | يستخدم مصمم NestJS لتحديد نقطة نهاية الأحداث من جانب الخادم (SSE). على سبيل المثال، @Sse('الموظف المعتمد') يقوم بإعداد نقطة نهاية لدفق التحديثات في الوقت الفعلي إلى العميل. |
fromEvent | دالة من RxJS تقوم بتحويل حدث منبعث من ملف EventEmitter في تيار يمكن ملاحظته.
على سبيل المثال، fromEvent(this.eventEmitter, 'قسيمة بعد الإضافة') يستمع لحدث معين |
Observable | مفهوم أساسي من RxJS يستخدم لإدارة تدفقات البيانات غير المتزامنة.
إنه ضروري للتعامل مع الأحداث من جانب الخادم في NestJS، مثل يمكن ملاحظتها<MessageEvent> . |
@InjectQueue | مصمم ديكور NestJS الذي يُدخل مثيل قائمة الانتظار، وهو مفيد لإدارة معالجة المهام باستخدام مكتبات مثل Bull.
على سبيل المثال، @InjectQueue('allotVoucher') يوفر الوصول إلى قائمة الانتظار المسماة "allotVoucher". |
WorkerHost | فئة أساسية من BullMQ تسمح بتحديد معالجات المهام المخصصة في NestJS.
على سبيل المثال، AllotVoucherConsumer يمتد الصف WorkerHost للتعامل مع وظائف محددة. |
@OnWorkerEvent | مصمم ديكور يستخدم للاستماع إلى أحداث دورة حياة محددة لوظيفة قائمة الانتظار.
على سبيل المثال، @OnWorkerEvent('مكتمل') يتعامل مع الحدث "المكتمل" للوظيفة. |
createMany | أمر Prisma يستخدم لإدراج سجلات متعددة في قاعدة بيانات مرة واحدة.
على سبيل المثال، prisma.employee Voucher.createMany إضافة جميع قسائم الموظفين في عملية واحدة. |
EventSource | واجهة برمجة تطبيقات JavaScript لتلقي الأحداث المرسلة من الخادم (SSE) من الواجهة الخلفية.
على سبيل المثال، مصدر الأحداث الجديد('http://localhost/vouchered-employee') يؤسس اتصالاً لتدفق البيانات. |
add | طريقة من قوائم انتظار Bull لإضافة وظيفة جديدة إلى قائمة الانتظار.
على سبيل المثال، allotVoucherQueue.add('قسيمة التخصيص'، بيانات العمل) جدولة مهمة للمعالجة. |
@OnEvent | مصمم ديكور NestJS الذي يستمع لأحداث معينة منبعثة داخل التطبيق.
على سبيل المثال، @OnEvent('قسيمة ما بعد التخصيص') يطلق طريقة عندما ينبعث هذا الحدث. |
إشعارات فعالة مع الأحداث وقوائم الانتظار من جانب الخادم
توضح البرامج النصية المقدمة نظامًا يتم فيه إرسال إشعارات في الوقت الفعلي إلى الموظفين بعد الإدراج المجمع لسجلات القسائم في قاعدة البيانات. تبدأ العملية في تخصيص قسيمة التحكم، والذي يعرض نقطة نهاية لإنشاء مهام تخصيص الإيصالات. عندما يتم إنشاء مهمة، فإنها تنبعث حدثا اسمه بعد تخصيص القسيمة. يعد هذا الحدث ضروريًا لبدء الخطوات اللاحقة، مما يضمن أن النظام يعتمد على الحدث ومعياريًا. يسمح هذا التصميم بالفصل الواضح بين الاهتمامات، مما يجعل النظام أكثر قابلية للصيانة وقابلة للتطوير. 🎯
في طبقة الخدمة، تخصيصVoucherService يتعامل مع منطق ترتيب المهام باستخدام BullMQ. بعد استلام بعد تخصيص القسيمة الحدث، فإنه يضيف وظيفة إلى قائمة الانتظار المسماة قسيمة التخصيص. تسمح قائمة الانتظار هذه بالمعالجة غير المتزامنة، مما يضمن بقاء النظام مستجيبًا حتى عند معالجة مجموعات البيانات الكبيرة. على سبيل المثال، إذا قمت بتخصيص إيصالات لـ 200 موظف في قسم المبيعات، فإن قائمة الانتظار تضمن أن العملية لا تمنع الطلبات الأخرى. يتضمن تكوين قائمة الانتظار خيارات مثل RemoveOnComplete للحفاظ على نظافة Redis بعد إكمال المهمة.
تتم معالجة وظائف قائمة الانتظار بواسطة AllotVoucherConsumer فصل. هنا، يتم تنفيذ منطق تحديد الموظفين المعنيين وإدراج سجلات القسائم في قاعدة البيانات. أمر بريزما createMany يتم استخدامه لإدراج السجلات دفعة واحدة في ملف قسيمة الموظف الجدول الأمثل للأداء. بعد اكتمال عملية قاعدة البيانات، يتم إطلاق حدث آخر لإعلام المشتركين. يضمن هذا الحدث عدم إعلام الموظفين إلا بعد معالجة الإدراج المجمع بنجاح، مما يضيف الموثوقية إلى نظام الإعلام. 🌟
على الواجهة الأمامية، يستمع مكون React إلى الأحداث المرسلة من الخادم من خلال مصدر الحدث. عندما يتم إخطار الموظفين، يتم تحديث التفاصيل الخاصة بهم ديناميكيًا في واجهة المستخدم دون الحاجة إلى تحديث الصفحة. يوفر هذا النهج تجربة مستخدم سلسة، تشبه التحديثات في الوقت الفعلي التي يتم مشاهدتها في تطبيقات الويب الحديثة مثل النتائج الرياضية المباشرة أو إشعارات الوسائط الاجتماعية. على سبيل المثال، لن يرى الموظفون في قسم الموارد البشرية التحديثات المخصصة للمبيعات، حيث تقوم الواجهة الخلفية بتصفية الأحداث بدقة بناءً على معايير التخصيص. تعمل هذه الخصوصية على تحسين الأداء والملاءمة، وإنشاء نظام يركز على المستخدم. 🖥️
إرسال الإشعارات بشكل مجمّع باستخدام الأحداث من جانب الخادم (SSE) في NestJS
يوضح هذا الحل أسلوب الواجهة الخلفية لاستخدام NestJS مع Prisma والأحداث من جانب الخادم (SSE) للعمليات المجمعة. يتضمن بنية تعتمد على الأحداث ونظام انتظار.
// Backend: AllocateVoucherController
import { Controller, Post, Body, Sse, OnEvent } from '@nestjs/common';
import { AllocateVoucherService } from './allocate-voucher.service';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { Observable } from 'rxjs';
import { map, fromEvent } from 'rxjs';
@Controller('allocate-voucher')
export class AllocateVoucherController {
constructor(
private readonly allocateVoucherService: AllocateVoucherService,
private readonly eventEmitter: EventEmitter2
) {}
@Post()
async create(@Body() createDto: any) {
const result = await this.allocateVoucherService.create(createDto);
return result;
}
@Sse('vouchered-employee')
updatedEmployeeEvent(): Observable<MessageEvent> {
return fromEvent(this.eventEmitter, 'after-added-voucher').pipe(
map((data) => new MessageEvent('after-added-voucher', { data })),
);
}
}
تحديثات في الوقت الفعلي للإدراجات المجمعة باستخدام NestJS وReact
يستخدم مثال الواجهة الأمامية هذا React للاستماع إلى الأحداث من جانب الخادم وتحديث واجهة المستخدم ديناميكيًا عند تلقي البيانات. فهو يضمن إخطار الموظفين في الوقت الفعلي بعد عمليات الإدراج المجمعة.
// Frontend: React Component for SSE
import React, { useEffect, useState } from 'react';
const EmployeeUpdates = () => {
const [employees, setEmployees] = useState([]);
useEffect(() => {
const eventSource = new EventSource('http://localhost:3000/allocate-voucher/vouchered-employee');
eventSource.onmessage = (event) => {
const newEmployee = JSON.parse(event.data);
setEmployees((prev) => [...prev, newEmployee]);
};
return () => eventSource.close();
}, []);
return (
<table>
<thead>
<tr><th>Name</th><th>Voucher</th></tr>
</thead>
<tbody>
{employees.map((emp) => (
<tr key={emp.id}><td>{emp.name}</td><td>{emp.voucher}</td></tr>
))}
</tbody>
</table>
);
};
export default EmployeeUpdates;
إشعارات اختبار الوحدة لعمليات الإدخال المجمعة
يضمن اختبار Jest هذا أن تعمل آلية إرسال الحدث والإشعارات بشكل صحيح في الواجهة الخلفية للأحداث من جانب الخادم في NestJS.
// Jest Test: AllocateVoucherService
import { Test, TestingModule } from '@nestjs/testing';
import { AllocateVoucherService } from './allocate-voucher.service';
import { EventEmitter2 } from '@nestjs/event-emitter';
describe('AllocateVoucherService', () => {
let service: AllocateVoucherService;
let eventEmitter: EventEmitter2;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [AllocateVoucherService, EventEmitter2],
}).compile();
service = module.get(AllocateVoucherService);
eventEmitter = module.get(EventEmitter2);
});
it('should emit after-allocate-voucher event', async () => {
jest.spyOn(eventEmitter, 'emit');
const result = await service.create({ someData: 'test' });
expect(eventEmitter.emit).toHaveBeenCalledWith('after-allocate-voucher', result);
});
});
تعزيز أنظمة الوقت الحقيقي باستخدام SSE في NestJS
بينما قمنا باستكشاف تنفيذ الأحداث من جانب الخادم (SSE) لإخطار الموظفين بتخصيصات القسائم، هناك حالة استخدام أوسع لـ SSE في أنظمة الوقت الفعلي. يتألق SSE في السيناريوهات التي يحتاج فيها العملاء إلى البقاء على اطلاع دائم ببيانات الخادم دون الاستقصاء المستمر. على سبيل المثال، فكر في منصة للبيع بالتجزئة عبر الإنترنت تتتبع تحديثات المخزون المباشر أثناء عملية بيع سريعة. باستخدام SSE، يمكنك دفع التحديثات بكفاءة إلى جميع العملاء المتصلين، مما يضمن عرضهم لأحدث مستويات المخزون دون تحميل الخادم غير الضروري. ويضمن هذا النهج قابلية التوسع مع الحفاظ على سلاسة تجربة المستخدم. 🛒
دمج أنظمة الانتظار المتقدمة مثل BullMQ، كما فعلنا مع قسيمة التخصيص قائمة الانتظار، يضيف المتانة إلى مهام معالجة البيانات المجمعة. تضمن قائمة الانتظار أنه حتى في حالة حدوث إعادة تشغيل للخادم، تظل المهام المعلقة سليمة، ويتم استئناف المعالجة. بالإضافة إلى ذلك، يمكن تكوين آليات إعادة المحاولة، مما يضمن إعادة محاولة المهام الفاشلة (على سبيل المثال، بسبب التوقف المؤقت لقاعدة البيانات) تلقائيًا. على سبيل المثال، إذا واجه التخصيص لـ 300 موظف عبر الأقسام خطأً مؤقتًا، فإن مرونة قائمة الانتظار تضمن عدم ترك أي سجلات دون معالجة، مما يضيف الموثوقية إلى نظامك.
بالإضافة إلى الإشعارات في الوقت الفعلي، يمكن لـ SSE أيضًا استكمال خدمات البريد الإلكتروني للمهام التي تتطلب ملخصات مفصلة. بعد إرسال جميع إشعارات القسائم عبر SSE، يمكن للواجهة الخلفية إنشاء تقرير بشكل غير متزامن وإرسال بريد إلكتروني موحد إلى المديرين. يضمن هذا الاتصال متعدد القنوات الحصول على إشعارات فورية ومتابعة شاملة، مما يلبي مجموعة واسعة من تفضيلات المستخدم. يعمل هذا التكامل على تحسين مرونة نظامك، مما يؤدي إلى إنشاء تجربة مستخدم شاملة. 📧
الأسئلة المتداولة حول SSE في NestJS
- ما فوائد استخدام الأحداث من جانب الخادم عبر WebSockets؟
- يعد SSE أسهل في التنفيذ ويستخدم HTTP، مما يجعله صديقًا لجدار الحماية. على عكس WebSockets، فإنه لا يتطلب سوى اتصال واحد أحادي الاتجاه، وهو أمر فعال للتحديثات في الوقت الحقيقي.
- هل يمكنني استخدام @Sse مع نقاط نهاية متعددة في وحدة تحكم؟
- نعم، يمكنك تحديد متعددة @Sse نقاط النهاية في نفس وحدة التحكم لخدمة تدفقات البيانات المختلفة للعملاء بناءً على الاحتياجات المحددة.
- كيف أتعامل مع الأخطاء أثناء معالجة قائمة الانتظار؟
- باستخدام BullMQ، يمكنك تحديد خيارات إعادة المحاولة واستخدام مستمعي الأحداث مثل @OnWorkerEvent('failed') لتسجيل الأخطاء وإعادة معالجة المهام إذا لزم الأمر.
- هل بريزما createMany طريقة دعم التراجع عن المعاملات؟
- نعم بريزما createMany يمكن أن تكون ملفوفة في الصفقة. في حالة فشل أي عملية في المعاملة، يتم التراجع عن كافة العمليات من أجل التناسق.
- ماذا يحدث إذا انقطع اتصال العميل أثناء تدفق SSE؟
- يتوقف الخادم عن إرسال التحديثات بمجرد اكتشاف انقطاع الاتصال. يمكنك تنفيذ منطق إعادة الاتصال على العميل باستخدام EventSource واجهة برمجة التطبيقات.
- هل يمكن استخدام SSE للاتصال ثنائي الاتجاه؟
- لا، SSE أحادي الاتجاه (من الخادم إلى العميل). للاتصال ثنائي الاتجاه، استخدم تدفقات WebSockets أو HTTP2.
- كيف أقوم بتأمين نقاط نهاية SSE في NestJS؟
- استخدم الحراس أو البرامج الوسيطة، مثل @UseGuards، لفرض المصادقة والترخيص لنقاط نهاية SSE الخاصة بك.
- هل يمكن لـ SSE العمل مع العملاء الذين لا يستخدمون المتصفح؟
- نعم، يمكن لأي عميل يدعم تدفق HTTP والأحداث (على سبيل المثال، Node.js، cURL) أن يستهلك تدفقات SSE.
- ما هو الحد الأقصى لعدد العملاء الذين يمكنهم الاتصال بنقطة نهاية SSE؟
- يعتمد هذا على تكوين الخادم الخاص بك وحدود الموارد. يمكن أن تساعد موازنة التحميل والتجميع على التوسع لدعم المزيد من العملاء.
- هل من الممكن إرسال بيانات JSON عبر SSE؟
- نعم، يمكنك إجراء تسلسل للكائنات إلى سلاسل JSON وإرسالها باستخدام new MessageEvent في NestJS.
إشعارات فعالة في الوقت الحقيقي في NestJS
تنفيذ أنظمة الوقت الحقيقي باستخدام SSE في NestJS يبسط الاتصال بين الخادم والعملاء. تعمل هذه الطريقة على تقليل حمل الخادم مقارنةً بالاستقصاء المستمر وتمكين الاستهداف الدقيق للإشعارات. على سبيل المثال، يمكن لأداة الموارد البشرية إخطار 200 موظف في المبيعات بشأن القسائم الجديدة دون تعطيل الآخرين. 🎯
باستخدام أدوات مثل BullMQ وPrisma، يضمن هذا الإعداد معالجة غير متزامنة للمهام وعمليات قاعدة بيانات فعالة. إن مرونة البنية القائمة على الأحداث تجعلها حلاً قابلاً للتطوير لمختلف متطلبات الوقت الفعلي، مما يعزز مشاركة المستخدم وموثوقية النظام.
المصادر والمراجع
- وثائق مفصلة عن إطار عمل NestJS لبناء تطبيقات قابلة للتطوير من جانب الخادم.
- دليل على استخدام BullMQ لإدارة قائمة انتظار المهام بشكل قوي في تطبيقات Node.js.
- رسمي توثيق بريزما لعمليات قاعدة البيانات واستخدام ORM.
- رؤى على الأحداث المرسلة من الخادم (SSE) للتواصل في الوقت الحقيقي بين العميل والخادم.
- أمثلة عملية على تنفيذ الواجهة الأمامية من وثائق ReactJS لبناء واجهات المستخدم التفاعلية.