Get a quote

مصادر الأحداث في Go: بناء مخزن أحداث append-only مع PostgreSQL

مصادر الأحداث تخزن التاريخ الكامل لما حدث لبياناتك، وليس فقط حالتها الحالية. في السياق الصحيح، تُلغي فئات كاملة من مشاكل التدقيق والتصحيح. هذا المقال يشرح كيفية بناء مخزن أحداث بسيط في PostgreSQL مع Go.

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

ما هي المشكلة التي تحلها مصادر الأحداث فعليًا؟

خذ نظام إدارة الطلبات لسلسلة مطاعم لبنانية. يُنشأ الطلب، تُضاف العناصر، يطلب العميل تعديلًا، تُحدد المطبخ عنصرًا غير متاح، يُصدر استرداد جزئي، وأخيرًا يُنفذ الطلب. في نموذج قاعدة بيانات تقليدي، لديك صف واحد في جدول orders والحالة النهائية لا تعكس شيئًا من هذا التاريخ.

عندما يسأل المالك ماذا طُلب مقابل ما سُلّم، ولماذا صُدر الاسترداد، ليس لديك بيانات.

مصادر الأحداث تحل هذا بجعل التاريخ هو مصدر الحقيقة. لا يوجد تحديث لصف الطلب. هناك فقط تسلسل من الأحداث: OrderCreated، ItemAdded، ItemUnavailable، PartialRefundIssued، OrderFulfilled.

متى تكون مصادر الأحداث الخيار الصحيح؟

مصادر الأحداث تضيف قيمة حقيقية عندما تكون الثلاثة صحيحة:

  1. دورة حياة الكيان معقدة والانتقالات بين الحالات مهمة
  2. تحتاج إلى مسار تدقيق كامل وموثوق لأسباب الامتثال أو الأعمال
  3. تحتاج إلى إعادة بناء مشاهدات مختلفة لنفس البيانات لمستهلكين مختلفين

لمنصة إدارة عيادة لبنانية، سجلات المرضى وتواريخ المواعيد تستوفي الثلاثة معايير. لـ SaaS B2B بسيط بعدد من جداول الإعدادات التي نادرًا ما تتغير، مصادر الأحداث تُضيف احتكاكًا دون فائدة.

كيف تبني مخزن أحداث في PostgreSQL؟

مخزن الأحداث هو جدول واحد للإلحاق فقط. القيد الرئيسي هو أن الأحداث لا تُحدَّث أو تُحذَّف أبدًا:

CREATE TABLE event_store (
    id           BIGSERIAL PRIMARY KEY,
    aggregate_id UUID        NOT NULL,
    tenant_id    UUID        NOT NULL,
    event_type   TEXT        NOT NULL,
    version      INT         NOT NULL,
    payload      JSONB       NOT NULL,
    occurred_at  TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE UNIQUE INDEX event_store_aggregate_version
    ON event_store (aggregate_id, version);

حقل version لكل aggregate هو قفل التزامن المتفائل. عندما يحاول طلبان إضافة الحدث الإصدار 5 لنفس الـ aggregate في وقت واحد، الفهرس الفريد يضمن نجاح واحد فقط.

كيف تعيد بناء aggregate من أحداثه؟

func (o *Order) Apply(event Event) error {
    switch event.EventType {
    case "OrderCreated":
        var p OrderCreatedPayload
        json.Unmarshal(event.Payload, &p)
        o.ID = event.AggregateID
        o.Status = "pending"
    case "ItemAdded":
        var p ItemAddedPayload
        json.Unmarshal(event.Payload, &p)
        o.Items = append(o.Items, OrderItem{ID: p.ItemID, Price: p.Price})
    case "OrderFulfilled":
        o.Status = "fulfilled"
    }
    o.Version = event.Version
    return nil
}

ما هي Projections ومتى تحتاجها؟

إعادة تشغيل الأحداث في كل مرة تحتاج فيها إلى الحالة الحالية مكلفة للـ aggregates التي لها آلاف الأحداث. Projections تحل هذا. Projection هي مشاهدة محسّنة للقراءة لحالة aggregate يتم تحديثها بشكل غير متزامن مع إضافة الأحداث.

التوازن هو الاتساق النهائي. الـ projection دائمًا أقل قليلًا من مخزن الأحداث. لمعظم لوحات تحكم SaaS وشاشات التقارير، هذا التأخير (عادةً أقل من 500ms) مقبول.

ما الذي يجب تجنبه عند تطبيق مصادر الأحداث؟

تجنب مصادر الأحداث للبيانات المرجعية. جداول البحث مثل categories أو product_types لا تستفيد من مصادر الأحداث.

تجنب تصميم الأحداث حول العمليات التقنية. UserFieldUpdated ليس حدثًا. CustomerAddressVerified هو. الأحداث يجب أن تعكس القصد التجاري، وليس التحولات في البيانات.

تجنب PostgreSQL كمخزن أحداث طويل الأمد للأنظمة ذات الحجم الكبير جدًا. لـ SaaS لبناني بـ 10,000 مستخدم نشط يوميًا، يتعامل PostgreSQL مع مصادر الأحداث بشكل مريح.

الدروس الرئيسية من الإنتاج

مصادر الأحداث في خلفية Go مع PostgreSQL تعمل بشكل جيد للكيانات المعقدة الحرجة على التدقيق. ابقِ التطبيق بسيطًا: جدول مخزن أحداث واحد مع قيد إصدار فريد، حالة aggregate تُعاد ببناء من إعادة تشغيل الأحداث، projections لأنماط الاستعلام الكثيفة القراءة.

هل تحتاج إلى مساعدة في البناء؟

فوكسير تصمم وتبني خلفيات SaaS للشركات في لبنان ومنطقة الشرق الأوسط وشمال إفريقيا. إذا كنت تقرر ما إذا كانت مصادر الأحداث تناسب مجالك أو تحتاج إلى مساعدة في هيكلة خلفية Go لنظام تشغيلي معقد، تواصل معنا.

https://voxire.com/get-a-quote/

العودة إلى المدونة
Chat on WhatsApp