انتقل إلى المحتوى
use-cases / the-webhook-fan-out-you-didnt-have-to-build / hero
PIPE · تفرّع HTTP

تفرُّع الـ webhook الذي لم تضطر لبنائه

Stripe يُرسل جسم الحدث بـ POST إلى مسار أنبوب مع ?n=12. اثنا عشر مشتركاً يطلبون نفس المسار بـ GET مع ?n=12. الأنبوب يحتفظ بالرسالة حتى يتّصل الجميع، ثم يبثّ إلى الاثني عشر دفعةً واحدة. لا وسيط، لا مجموعة مستهلِكين، لا DLQ.

اقرأ توثيق Pipe
use-cases / the-webhook-fan-out-you-didnt-have-to-build / mechanism

رابط واحد. اثنا عشر قارئاً. ضغط عكسي لكل اتّصال.

Hoody Pipe بثّ HTTP بوضع متعدّد المستقبِلين. أضف ?n=N على روابط المرسِل والمستقبِل والأنبوب ينتظر حتى يلتصق N قارئاً، ثم يعكس الجسم لكلّهم في الوقت ذاته. البطيئون يخنقون اتّصالهم — السريعون يستمرّون في التدفّق.

01خطوة 01 · الاستقبال

Stripe يُرسل POST إلى الأنبوب

نقطة نهاية Stripe لديك تُمرِّر جسم الحدث مباشرةً إلى /api/v1/pipe/billing?n=12. الاتّصال محصور ريثما ينتظر الأنبوب اجتماع الاثني عشر مستقبِلاً.

02خطوة 02 · الاجتماع

اثنا عشر مشتركاً يلتصقون

كل مشترك حلقة curl في حاوية، تطلب نفس المسار بـ GET مع ?n=12. الأنبوب يحتفظ بالجسم في الذاكرة حتى يتّصل القارئ الثاني عشر — لا طابور على القرص، لا شيء يجب تفريغه.

03خطوة 03 · بثّ

تفرّع، ثم نسيان

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

stripe-webhook.sh
# جانب المرسل — معالج webhook الخاص بك بـ Stripe.
# الأنبوب يحمل الجسم حتى 12 قارئ متصلين.
curl -X POST "https://api.hoody.com/api/v1/pipe/billing?n=12" \
  -H "Authorization: Bearer $HOODY_TOKEN" \
  -H "Content-Type: application/json" \
  --data-binary "@stripe-event.json"

# جانب المتلقي — واحد من اثني عشر حاوية مشترك.
# نفس المسار، نفس n. بث جسم الحدث حين التوزيع جاهز.
curl -N "https://api.hoody.com/api/v1/pipe/billing?n=12" \
  -H "Authorization: Bearer $HOODY_TOKEN" | ./billing-handler.sh

# n يجب أن تطابق على كلا الجانبين — عدم التطابق يرجع 400.
# الافتراضي n=1 من نقطة إلى نقطة. n=12 للتوزيع إلى اثني عشر.

نفس الرابط، نفس سلسلة الاستعلام، على الطرفَين. اتّصال المرسِل هو الوسيط؛ اتّصالات القرّاء هي مجموعة المستهلِكين. الضغط العكسي لكل مقبس، لا لكل موضوع، لأنّه لا يوجد موضوع — هناك جسم واحد في الطيران واثنا عشر مقبساً يسحبان منه.

use-cases / the-webhook-fan-out-you-didnt-have-to-build / fleet

المشتركون يأتون ويذهبون كالعمليّات

إضافة مشترك هي curl إضافي في حاوية إضافيّة. إزالته هي قتل curl. لا إعداد وسيط، لا إعادة توازن مجموعة مستهلِكين، لا DLQ يجب تفريغه — طوبولوجيا العنقود هي ببساطة العمليّات التي تصادف أنّها تعمل الآن.

فروق المشتركين · آخر 5 دقائقلا حاجة لإعادة توازن
  • + مُضاف
    WHKAUD
    حاويتان جديدتان شُغِّلتا
  • − محذوف
    MIX
    حاوية قُتلت، curl خرج
  • = ثابت
    BILANLLOGFRDSUCSLACRMCDNNOT
    لا يزالون على نفس مسار n=12

الأنبوب لا يتتبّع من المشترك. ينتظر فقط n اتّصالات لكل حدث. ارفع n على الطرفَين والحدث التالي ينتظر العدد الجديد. لا حالة عضويّة يمكن أن تتلف لأنّه لا توجد عضويّة.

use-cases / the-webhook-fan-out-you-didnt-have-to-build / advantages

ما لم تعد تُشغّله

كل سطر أدناه فئة عمل تختفي حين يكون الوسيط هو البروتوكول. لا بنية تحتيّة لتوفيرها، لا تجريدات لتعلّمها — فقط curl و?n.

  • لا طابور لتوفيره

    لا SQS، لا عنقود Kafka، لا exchange في RabbitMQ. الأنبوب هو الطابور، ويحيا لرسالة واحدة في كل مرّة.

  • لا محاسبة لمجموعات مستهلِكين

    لا offsets، لا commits، لا rebalances. الأنبوب يحتفظ بالجسم حتى تلتصق n مقابس — هذا هو نموذج التنسيق بأكمله.

  • لا DLQ يجب تفريغه

    إن انفصل المرسِل دون استعداد n قرّاء، الأنبوب ينتهي وقته (TTL 5 دقائق) وStripe يُعيد المحاولة. لا دلو رسائل سامّة لتتفقّده.

  • لا SDK لكل لغة

    المشتركون حلقات curl. المرسِلون curl. البروتوكول HTTP. أيّ شيء يستطيع ضرب رابط يستطيع الانضمام إلى العنقود.

  • ضغط عكسي لكل مقبس

    قارئ بطيء يخنق اتّصاله. الأحد عشر الآخرون يستمرّون بكامل السرعة. لا حظر رأس-الطابور عبر الأسطول.

  • نسّاء افتراضياً

    الجسم يختفي لحظة فصل آخر قارئ. لا سياسة احتفاظ يجب ضبطها، لا ضغط سجلّ يجب جدولته، لا مهمّة GDPR delete-on-request يجب كتابتها.

use-cases / the-webhook-fan-out-you-didnt-have-to-build / punchline

اثنا عشر مشتركاً، رابط واحد، لا وسيط.

الوسطاء أدناه هم الأشياء التي اعتدت تثبيتها قبل أن يصبح تفرّع HTTP مُعامل استعلام. الجانب الأيمن هو ما يستبدلها — مسار واحد، n واحد، واثنتا عشرة عمليّة curl لا تعرف أنّها عنقود.

ما لا تُشغّله
  • AWS Lambda + SQS/SNS
  • Apache Kafka
  • RabbitMQ exchanges
  • موجِّهات webhook مُخصّصة
ما تستدعيه بدلاً منه
POST /api/v1/pipe/billing?n=12

اثنا عشر مستقبِلاً يطلبون نفس المسار بـ GET مع نفس n. الأنبوب هو الوسيط — وينسى الرسالة لحظة فصل آخر قارئ.

اقرأ قسم التفرّع
use-cases / the-webhook-fan-out-you-didnt-have-to-build / replaces

ما يستبدله هذا

إن مدّيتَ يدك إلى أيّ من هذه لبثّ webhook إلى N مستهلِكاً، نموذج الأنبوب يقوم بالمهمّة نفسها في استدعاءَي curl — مرسِل على جانب، مستقبِلون على الآخر.

  • AWS Lambda + SQS/SNSوسيط لكل موضوع، IAM لكل مشترك
  • Apache Kafkaعنقود، ZooKeeper/KRaft، مجموعات مستهلِكين
  • RabbitMQ exchangesربطات، vhosts، واجهة إدارة لكل بيئة
  • موجِّهات webhook مُخصّصةخدمة لصيانتها، إعادات محاولة لاختراعها
  • خدمات Pub/Subفوترة لكل رسالة، ربط بـ GCP/AWS
  • إضافات تفرّع HTTPإضافة بوّابة لكل حزمة، لا ضغط عكسي
use-cases / the-webhook-fan-out-you-didnt-have-to-build / cta

التفرّع الذي اعتدت كتابة سبرنت لأجله صار مُعامل استعلام. أضف ?n=12 وأطلق.

اقرأ توثيق Pipe
use-cases / the-webhook-fan-out-you-didnt-have-to-build / related

اقرأ الآخرين