دراسة حالة لمشروع متكامل
Tournwa
الواجهة الخلفية التي تشغّل Tournwa، منصّة رياضية إماراتية — محرّك منافسات بأربعة صيغ من التصنيف حتى ترتيب الدوري، ورسوم اشتراك عبر Stripe Connect، وتسجيل للرياضيين فرديًا أو ضمن فرق أو كثنائيات.
- الدور
- قائد تطوير الواجهة الخلفية
- المدة
- 8 أشهر — مستمر
- السنة
- 2026
- التقنيات
- Node.js · Express.js · PostgreSQL · Redis · Stripe
- مباشر
- tournnwa.com

01 / المشكلة
المنافسة الحقيقية تحتاج أكثر من استمارة تسجيل.
يحتاج منظّمو المنافسات الرياضية المهيكلة إلى فئات وتصنيف ومرحلة مجموعات وجداول إقصاء ونقاط لكل شوط ونقاط دوري — إضافةً إلى رسوم الاشتراك والموافقات وحدود السعة وموافقة الوليّ للقاصرين. ويحتاج الرياضيون إلى العثور على الأحداث والتسجيل فرديًا أو ضمن فريق أو مع شريك في الزوجي. لا جدول بيانات يصمد أمام ذلك.
المستخدمون المستهدفون
ثلاثة أدوار: المنظّمون — أندية وأكاديميات تدير البطولات والتدريبات والمباريات الودّية؛ والرياضيون، ومنهم القاصرون خلف مسارات موافقة الوليّ؛ ومشرفو المنصّة.
02 / الحل
واجهة خلفية واحدة، ثلاثة تطبيقات.
واجهة Express واحدة تخدم ثلاث واجهات — تطبيق جوّال للرياضي، وتطبيق ويب للمنظّم، ولوحة إشراف — عبر 338 نقطة نهاية موزّعة على 31 مجموعة مسارات. يحمل محرّك المنافسات الفئة من التصنيف مرورًا بالمجموعات والجداول وصولًا إلى تسوية النقاط؛ ويوجّه Stripe Connect رسوم الاشتراك إلى المنظّمين المميّزين مع اقتطاع عمولة المنصّة تلقائيًا لكل حدث؛ وخمسة طوابير في الخلفية تُبقي الرسائل النصية والبريد والإشعارات خارج مسار الطلب.
لماذا هذه التقنيات
- PostgreSQL — فهارس فريدة جزئية وأقفال صفوف ومعاملات تحمي المال
- Redis — تخزين مؤقت وقائمة JWT السوداء ومخزن OTP وحدود المعدّل في قطعة واحدة
- BullMQ — خمسة طوابير تُبقي Twilio و SMTP و Expo خارج مسار الطلب
- عنقود Node — عمّال متعدّدو الأنوية بحصص اتصال محسوبة لكل عامل
03 / الميزات
ما الذي تقوم به المنصّة.
مصادقة بأربع طرق
بريد و Google و Apple ورمز OTP بالهاتف مع قائمة رموز سوداء في Redis
محرّك المنافسات
تصنيف ومجموعات وجداول ونقاط لكل شوط وترتيب يفضّ التعادل
Stripe Connect
مدفوعات موجَّهة مع عمولة منصّة لكل حدث وتحويلات للمنظّمين
تسجيل مرن
فردي أو فريق أو زوجي — مع اشتراط موافقة الوليّ للقاصرين
نقاط الدوري
نماذج تحويل المراكز إلى نقاط تُسوّى في سجلّ يُضاف إليه فقط
فضاءات المنظّمين
مجتمعات خاصة لا تتسرّب أبدًا إلى القوائم العامة
04 / التحديات التقنية
الأجزاء الصعبة — وكيف تجاوزتها.
محرّك منافسات بأربع صيغ
إقصاء مباشر، ودوري من مجموعة واحدة أو عدّة مجموعات، ومرحلتان من المجموعات إلى الإقصاء — مع الإعفاءات وطرق التصنيف ومباريات المركز الثالث، وقواعد يجب أن تتجمّد لحظة انطلاق اللعب.
كيف حللتها
تُكمَّل الجداول إلى أقرب قوّة للعدد اثنين، وتُرتَّب المصنَّفون بمرآة تعاودية 1 مقابل N مع توصيل مسبق لحوافّ الفائز والخاسر، فينتقل أثر إنهاء أي مباراة آليًا؛ والإعفاءات تُحسم ذاتيًا عند التوليد. وتُوزَّع المجموعات بأسلوب الأفعى وتُجدوَل بطريقة الدائرة. وتفرض الحرّاس حالات مباريات لا رجعة فيها وتجمّد إعدادات المنافسة بمجرّد وجود تصنيف — كل تعديل ضمن معاملة، وإبطال التخزين المؤقت مؤجَّل إلى ما بعد الإيداع.
مدفوعات محصّنة ضد التسابق
قد تصل الإنهاءات مرّتين — من الويب هوك ومن استطلاع العميل —، ويرسل المستخدمون النوايا مرّتين، ويجب ألّا يوافق دفعٌ على تسجيل مرّتين ولا يحجز مقعدًا مرّتين.
كيف حللتها
فهرسان فريدان جزئيان يسمحان بدفعة نشطة واحدة ودفعة مكتملة واحدة لكل تسجيل؛ والإنهاء يأخذ قفل صف، ويعود فورًا إن كان قد تمّ، ثم يوافق على التسجيل ويحجز المقعد وينشّط المشاركين في معاملة واحدة. ومفاتيح Stripe للإتمام مرّة واحدة تُشتقّ من معرّفات داخلية، ورسائل الإيصال محميّة مرّتين بمعرّفات مهام مُزال تكرارها وتحديث مشروط بقيمة فارغة.
نقاط تُسوّى مرّة واحدة بالضبط
عند اكتمال البطولة يجب أن تتحوّل المراكز إلى نقاط دوري مرّة واحدة بالضبط لكل فئة حتى مع إعادة المحاولة — وأن تبقى قابلة للتصحيح إن عدّل المنظّمون نماذج النقاط لاحقًا.
كيف حللتها
تشتقّ التسوية المراكز حسب الصيغة وتتخطّى أي فئة لها قيد سابق في السجلّ لهذه البطولة. والتصحيحات تقارن المجاميع المطلوبة بمجموع السجلّ وتكتب أسطرًا معوّضة — فلا يُعدَّل التاريخ ولا يُحذف. وتُرتَّب لوحات الصدارة في SQL مع مشاركة التعادل خلف تخزين مؤقت لخمس دقائق مفتاحه رقم النسخة.
05 / البنية
كيف يتكامل النظام.
THREE CLIENT APPS
جوّال الرياضي · ويب المنظّم · الإشراف
EXPRESS 5 API
338 نقطة نهاية · JWT + RBAC · عنقود
POSTGRESQL
نحو 60 نموذجًا · معاملات · أقفال صفوف
STRIPE CONNECT
رسوم الاشتراك والتحويلات
REDIS + BULLMQ
تخزين مؤقت · OTP · خمسة طوابير
TWILIO · SMTP · EXPO
رسائل · بريد · إشعارات
CLOUDFLARE R2
رفع وسائط موقّع مسبقًا
خدمات خارجية
06 / لقطات الشاشة
المنتج، عن قرب.


07 / النتائج
ما الذي غيّره على أرض الواقع.
- نقطة نهاية
- 0
- حالة اختبار آلية
- 0
- نموذج بيانات
- 0+
- طوابير خلفية
- 0
واجهة برمجية واحدة في الإنتاج خلف تطبيق جوّال للرياضي وتطبيق ويب للمنظّم ولوحة إشراف. يدير المنظّمون منافسات كاملة — تصنيفًا ومجموعات وجداول ونتائج وترتيبات — بينما تُسوّى رسوم الاشتراك عبر Stripe Connect مع اقتطاع عمولة المنصّة تلقائيًا لكل حدث. ومسارات المال والمسارات الحرجة للمحرّك مغطّاة بمجموعة اختبارات Jest من 29 ملفًا.
08 / حزمة التقنيات
بُني بهذه الأدوات.
أُطر العمل
- Node.js
- Express 5
- Sequelize
- Jest
المكتبات
- BullMQ
- Stripe
- ioredis
- Joi
- Twilio
- Expo Push
البنية التحتية
- PostgreSQL
- Redis
- Railway
- Cloudflare R2
- Stripe Connect
09 / مساهمتي
ما الذي بنيته، تحديدًا.
- صمّمتُ وبنيتُ محرّك منافسات البطولات: أربع تركيبات صيغ، وتصنيف مع حسم تلقائي للإعفاءات، وتوزيع مجموعات بأسلوب الأفعى، وجدولة بطريقة الدائرة، وترتيبات بفضّ تعادل تعاودي.
- بنيتُ نظام الدفع عبر Stripe Connect: وضعا تحويل، وإتمام مرّة واحدة عبر فهارس فريدة جزئية وأقفال صفوف، وإنهاء مدفوع بالويب هوك يوافق ويحجز في معاملة واحدة.
- بنيتُ تسوية نقاط الدوري القابلة للتكرار الآمن مع سجلّ تصحيحات يُضاف إليه فقط ولوحات صدارة مرتَّبة في SQL مع مشاركة التعادل.
- بنيتُ فضاءات المنظّمين — مجتمعات خاصة محدّدة بالترويسة مع عزل صارم للظهور، تحقّقت منه اختبارات تسرّب مخصّصة.
- بنيتُ الطبقة التشغيلية: خادم عنقودي مع إيقاف سلس، وتخزين مؤقت في Redis بمفتاح نسخة، وخمسة عمّال BullMQ منهم كنس تذكيرات آمن التكرار، وتحديد المعدّل، ومجموعة الاختبارات الـ186. (زميل الفريق: تكامل المصادقة الاجتماعية وإدارة الفرق.)