كانت خطوط بياناتنا هشة وتعمل بالدعاء: كيف أنقذنا Apache Airflow من جحيم ‘شغّل هذا السكريبت يدوياً’؟

يا جماعة الخير، السلام عليكم ورحمة الله.

اسمحوا لي أبدأ بقصة صارت معي قبل كم سنة، قصة بتلخص المعاناة اللي كثير من المبرمجين ومهندسي البيانات بعيشوها بصمت. كانت الساعة حوالي 2 بعد منتصف الليل، وأنا غاطس في النوم. فجأة، صوت رنين الهاتف يمزق سكون الليل. على الطرف الثاني كان صوت المدير التنفيذي، متوتر وقلق: “أبو عمر، آسف على الإزعاج، بس تقرير المبيعات اليومي ما وصل، والمستثمرون ينتظرون الأرقام في اجتماع الصباح الباكر!”.

قلبي وقع في رجلي، زي ما بحكوها. أنا كنت المسؤول عن سلسلة السكريبتات اللي بتجمع البيانات من عدة مصادر، بتنظفها، وبتحللها، وفي النهاية بتطلع التقرير اليومي. النظام كان عبارة عن مجموعة من ملفات البايثون و الـ “كرون جوبز” (cron jobs) المتناثرة على أكثر من سيرفر. أي خطأ في سكريبت واحد كان يعني انهيار السلسلة كلها زي أحجار الدومينو.

بسرعة فتحت اللابتوب، ودخلت على السيرفرات واحد واحد عن طريق SSH. بعد نصف ساعة من البحث والتحقيق، اكتشفت المشكلة: أحد السكريبتات اللي بتسحب البيانات من واجهة برمجية (API) فشل بسبب مشكلة مؤقتة في الشبكة، والسكريبت اللي بعده اشتغل على بيانات قديمة وغير مكتملة، وهكذا دواليك. الحل؟ كان لازم أعيد تشغيل كل سكريبت بالترتيب الصحيح يدوياً، وأنا بدعي ربنا إنه ما يفشل مرة ثانية.

في تلك الليلة، وأنا جالس أمام الشاشة بعيون نصف نائمة، أقسمت أن هذا الجحيم المسمى “شغّل هذا السكريبت يدوياً” يجب أن ينتهي. كانت تلك هي اللحظة التي قررنا فيها البحث عن حل حقيقي، حل ينقلنا من الفوضى إلى النظام. وكان هذا الحل هو Apache Airflow.

الفوضى المنظمة: جحيم “شغّل هذا السكريبت يدوياً”

قبل ما نحكي عن Airflow، خلينا نفصّل أكثر في طبيعة المشكلة اللي كنا عايشين فيها، واللي أنا متأكد إنه كثير منكم بعاني منها:

  • الاعتمادية الهشة (Fragile Dependencies): كان عنا سكريبت (أ) يسحب البيانات، وسكريبت (ب) ينظفها، وسكريبت (ج) يحملها على قاعدة البيانات. كنا نعتمد على توقيت الـ cron jobs. لو السكريبت (أ) تأخر أو فشل، السكريبت (ب) راح يشتغل على بيانات فارغة أو قديمة، والمصيبة تكبر.
  • انعدام الرؤية والمراقبة (No Visibility): شو القصة؟ هل السكريبت شغال؟ هل انتهى؟ هل فشل؟ ليش فشل؟ كلها أسئلة ما كان إلها جواب سهل. كنا لازم ندخل على ملفات الـ logs يدوياً على كل سيرفر لنعرف شو اللي بصير.
  • التعامل مع الأخطاء كابوس (Nightmarish Error Handling): إذا فشل سكريبت، ما كان في آلية تلقائية لإعادة المحاولة. كان لازم حدا يتدخل يدوياً. وإذا كان الفشل في منتصف الليل، الله يعينك.
  • صعوبة التوسع (Scalability Issues): كل ما أضفنا خطوة جديدة في خط البيانات، كانت التعقيدات تزيد بشكل أُسّي. إدارة عشرات الـ cron jobs الموزعة كانت أشبه بترويض الوحوش.

نصيحة من أبو عمر: إذا كان نظامك يعتمد على أنك تتذكر تشغيل شيء ما يدوياً، أو على سلسلة من الـ cron jobs التي لا تتحدث مع بعضها البعض، فأنت لا تملك نظاماً، بل تملك وصفة للكارثة تنتظر الحدوث.

المنقذ Apache Airflow: شو القصة؟

ببساطة، Apache Airflow هي منصة مفتوحة المصدر تمكنك من كتابة، جدولة، ومراقبة سير العمليات (workflows) برمجياً. الكلمة المفتاح هنا هي “برمجياً”. أنت لا تقوم بسحب وإفلات الصناديق في واجهة رسومية، بل تكتب كود بايثون لوصف خط البيانات الخاص بك.

هذا يعني أن خطوط البيانات الخاصة بك تصبح جزءاً من الكود، ويمكنك تطبيق أفضل الممارسات الهندسية عليها: التحكم في الإصدارات (version control) باستخدام Git، مراجعة الكود (code reviews)، والاختبار الآلي (automated testing).

المفاهيم الأساسية في Airflow

عشان نفهم Airflow صح، لازم نعرف كم مصطلح أساسي:

  • DAG (Directed Acyclic Graph): هذا هو قلب Airflow. لا تخاف من الاسم، الموضوع بسيط. الـ DAG هو عبارة عن ملف بايثون يصف كل المهام في سير العمل الخاص بك، وكيفية اعتمادها على بعضها البعض. “Directed” تعني أن لها اتجاه (مهمة أ قبل مهمة ب)، و “Acyclic” تعني أنه لا يوجد حلقات مفرغة (مهمة أ لا يمكن أن تعتمد على نفسها بشكل مباشر أو غير مباشر).
  • Operator: هو قالب جاهز لتنفيذ مهمة معينة. بدك تشغل سكريبت بايثون؟ استخدم PythonOperator. بدك تنفذ أمر bash؟ استخدم BashOperator. بدك تتعامل مع قاعدة بيانات PostgreSQL؟ استخدم PostgresOperator. وهكذا. Airflow مليء بالـ Operators الجاهزة.
  • Task: هي نسخة من الـ Operator تمثل خطوة واحدة في الـ DAG الخاص بك.
  • Task Instance: هو تشغيل محدد لمهمة (Task) في وقت محدد.
  • Web UI: واجهة مستخدم رسومية رائعة تمنحك رؤية كاملة لكل ما يحدث. يمكنك رؤية الـ DAGs، حالة المهام (نجاح، فشل، قيد التشغيل)، إعادة تشغيل المهام الفاشلة، عرض السجلات (logs)، وأكثر من ذلك بكثير. هذه الواجهة وحدها كانت كفيلة بحل 90% من مشاكل انعدام الرؤية لدينا.

من الفوضى إلى النظام: بناء أول خط بيانات (DAG) لنا

طيب، حكينا كثير تنظير. خلينا نشوف مثال عملي بالزبط. تخيل أننا نريد بناء خط بيانات بسيط يقوم بالآتي:

  1. سحب بيانات المستخدمين من واجهة برمجية (API).
  2. معالجة هذه البيانات (مثلاً، إزالة المستخدمين غير النشطين).
  3. تخزين البيانات النظيفة في قاعدة بيانات.

في عالم ما قبل Airflow، كان هذا يعني 3 سكريبتات منفصلة، و3 cron jobs، والكثير من الدعاء. مع Airflow، كل هذا يوصف في ملف بايثون واحد.

كود بايثون بسيط: مثال عملي

هذا مثال مبسط جداً لكيفية بناء DAG لهذه العملية:


from __future__ import annotations

import json
from datetime import datetime

from airflow import DAG
from airflow.operators.python import PythonOperator

# === Python Functions for our Tasks ===

def _fetch_user_data():
    # In a real scenario, this would make an API call
    print("Fetching user data...")
    users = [
        {'name': 'Abu Omar', 'active': True},
        {'name': 'Sami', 'active': False},
        {'name': 'Layla', 'active': True}
    ]
    with open('/tmp/users.json', 'w') as f:
        json.dump(users, f)
    print("User data fetched and saved to /tmp/users.json")

def _process_user_data():
    print("Processing user data...")
    with open('/tmp/users.json', 'r') as f:
        users = json.load(f)
    
    active_users = [user for user in users if user['active']]
    
    with open('/tmp/active_users.json', 'w') as f:
        json.dump(active_users, f)
    print("Active users processed and saved to /tmp/active_users.json")

def _store_user_data():
    # In a real scenario, this would connect to a database
    print("Storing data...")
    with open('/tmp/active_users.json', 'r') as f:
        active_users = json.load(f)
    
    print("--- Stored Users ---")
    for user in active_users:
        print(f"Stored: {user['name']}")
    print("Data stored successfully.")


# === DAG Definition ===

with DAG(
    dag_id='our_first_data_pipeline',
    start_date=datetime(2023, 1, 1),
    schedule_interval='@daily', # Run once a day
    catchup=False,
    tags=['tutorial'],
) as dag:
    
    fetch_data = PythonOperator(
        task_id='fetch_user_data',
        python_callable=_fetch_user_data,
    )

    process_data = PythonOperator(
        task_id='process_user_data',
        python_callable=_process_user_data,
    )

    store_data = PythonOperator(
        task_id='store_user_data',
        python_callable=_store_user_data,
    )

    # === Defining Dependencies ===
    # This is the magic part!
    fetch_data >> process_data >> store_data

لاحظ جمال وبساطة الجزء الأخير: fetch_data >> process_data >> store_data. بهذه الأسطر البسيطة، أخبرنا Airflow بالترتيب الدقيق الذي يجب أن تنفذ به المهام. إذا فشلت مهمة fetch_data، فإن process_data لن تبدأ أبداً. Airflow سيدير كل هذا التعقيد بالنيابة عنك.

نصائح من خبرتي (إشي من الآخر)

بعد سنوات من العمل مع Airflow، تعلمت بعض الدروس بالطريقة الصعبة. إليكم بعض النصائح العملية لتجنب أخطائي:

  1. اجعل مهامك قابلة للتكرار بأمان (Idempotent): هذه أهم نصيحة. يجب أن تكون المهمة مصممة بحيث لو قمت بتشغيلها 10 مرات بنفس المدخلات، فإن النتيجة النهائية تكون نفسها كما لو قمت بتشغيلها مرة واحدة. هذا يسمح لك بإعادة تشغيل المهام الفاشلة بثقة دون القلق من تكرار البيانات أو إفسادها.
  2. خلّي كل مهمة تعمل إشي واحد وبس (Atomic Tasks): لا تضع كل المنطق في مهمة واحدة ضخمة. قسّم عملك إلى مهام صغيرة ومركزة. هذا يجعل تصحيح الأخطاء (debugging) أسهل بكثير، ويسمح بإعادة استخدام المهام في DAGs أخرى.
  3. لا تكتب كلمات المرور في الكود يا حبيب! (Use Connections & Variables): Airflow يوفر واجهة لإدارة الاتصالات (مثل تفاصيل قاعدة البيانات) والمتغيرات بشكل آمن ومشفر. استخدمها دائماً ولا تقم أبداً بكتابة معلومات حساسة مباشرة في كود الـ DAG.
  4. استخدم الـ Versioning مع Git: بما أن الـ DAGs هي كود، عاملها ككود. ضعها في مستودع Git. هذا يمنحك تاريخاً كاملاً للتغييرات، القدرة على العودة لإصدار قديم، والعمل ضمن فريق بشكل منظم.
  5. راقب وضع التنبيهات (Monitoring & Alerting): Airflow رائع في إظهار الأخطاء، لكنك لن تجلس أمام الشاشة 24/7. قم بإعداد تنبيهات عبر البريد الإلكتروني أو Slack أو أي أداة أخرى لإعلامك فوراً عند فشل أي مهمة مهمة.

الخلاصة: من الدعاء إلى الأتمتة بثقة

التحول إلى Apache Airflow لم يكن مجرد تغيير تقني، بل كان تغييراً في ثقافة العمل. انتقلنا من حالة القلق الدائم والتدخلات اليدوية الطارئة، إلى نظام يمكننا الوثوق به. أصبح لدينا رؤية واضحة، وقدرة على تتبع الأخطاء بسهولة، والأهم من ذلك كله، استعدنا ليالي نومنا الهادئة.

إذا كنت لا تزال تعيش في جحيم “شغّل هذا السكريبت يدوياً”، فأتمنى أن تكون هذه المقالة قد أعطتك الدافع والخطوات الأولى نحو التغيير. قد يبدو الأمر صعباً في البداية، لكن الاستثمار في تعلم وتطبيق أداة مثل Airflow سيوفر عليك وقتاً وجهداً لا يقدران بثمن على المدى الطويل.

توقف عن الاعتماد على الدعاء لتشغيل خطوط بياناتك، وابدأ في بناء أنظمة مؤتمتة وموثوقة. وقتك وراحة بالك أغلى بكثير. بالتوفيق يا جماعة! 🚀

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

​معمارية البرمجيات

كانت قراراتنا أشباحاً تطاردنا: كيف أنقذتنا ‘سجلات القرارات المعمارية’ (ADRs) من جحيم “لماذا فعلنا ذلك؟”

قصص من قلب الميدان عن مشاريع كادت أن تنهار بسبب قرارات معمارية غامضة، وكيف كانت 'سجلات القرارات المعمارية' (ADRs) طوق النجاة الذي علّمنا أهمية توثيق...

26 مايو، 2026 قراءة المزيد
تسويق رقمي

كانت حملاتنا تحرق الأموال: كيف أنقذتنا نماذج الإحالة بالبيانات (DDA) من جحيم تخمين العائد على الاستثمار؟

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

25 مايو، 2026 قراءة المزيد
تجربة المستخدم والابداع البصري

من فوضى المكونات إلى لغة بصرية موحدة: كيف يبني ‘نظام التصميم’ (Design System) جسراً بين المطورين والمصممين؟

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

25 مايو، 2026 قراءة المزيد
برمجة وقواعد بيانات

كان كودنا غارقاً في بحر SQL: كيف أنقذنا ‘الربط الكائني العلائقي’ (ORM) من جحيم الاستعلامات المتكررة؟

أشارككم قصة حقيقية من مسيرتي كمبرمج، عن مشروع كاد أن يغرق في فوضى استعلامات SQL المتكررة. سنكتشف معًا كيف كانت تقنية الربط الكائني العلائقي (ORM)...

25 مايو، 2026 قراءة المزيد
الشبكات والـ APIs

كان كل مايكروسيرفس قلعة منعزلة: كيف أنقذتنا ‘بوابة الواجهات البرمجية’ (API Gateway) من جحيم الفوضى؟

في عالم الخدمات المصغرة (Microservices)، يمكن أن تتحول المرونة إلى فوضى عارمة. هذه قصة من تجربتي كـ "أبو عمر"، مبرمج فلسطيني، وكيف كانت بوابة الواجهات...

25 مايو، 2026 قراءة المزيد
البودكاست