انتقل إلى المحتوى
use-cases / crontab-per-branch / hero
CRON · GIT · جداول لكل فرع

ملف crontab لكل فرع، يُنشر مع الكود

أضف `.hoody/crontab` إلى المستودع بجانب مهامك. عندما يُشغّل سكربت النشر حاوية لـ `main` أو `feature/billing-v2` أو أي فرع معاينة، فإنه يرسل PUT لذلك الملف إلى Cron API الخاص بالحاوية الجديدة. الجدول يُشحن مع الفرع — ويختفي معه عند حذفه.

اقرأ Cron API
use-cases / crontab-per-branch / mechanism

كيف يصبح `.hoody/crontab` جدولاً حقيقياً

كل حاوية فرع تُشغّل Hoody Cron. سكربت النشر يقرأ ملف crontab المُودَع ويرسله بـ PUT إلى نقطة نهاية raw-crontab الخاصة بالحاوية الجديدة. الحاوية تُشغّل الجدول الذي يصفه الملف — لا أكثر ولا أقل.

deploy.sh · يدفعه CI
shell · client
#!/bin/sh
# زوّد حاوية جديدة لهذا الفرع.
BRANCH=$(git branch --show-current)
CTR=$(hoody containers create --from main-snapshot)

# استبدل crontab الحاوية بنسخة المستودع.
curl -X PUT --data-binary @.hoody/crontab \
  -H "Content-Type: text/plain" \
  https://$CTR-cron-1.hoody.com/users/root/crontab

# تم. جدول الفرع يعيش في حاويته.
echo "deployed $BRANCH → $CTR"
PUT /users/root/crontab
cron · server
# نقطة نهاية raw-crontab لـ Hoody Cron — تستبدل الملف بأكمله بشكل ذرّي.
PUT /users/root/crontab HTTP/1.1
Host: ctr_4d72b9-cron-1.hoody.com
Content-Type: text/plain

0 2 * * * /srv/jobs/billing-rollup-v2.sh
*/15 * * * * /srv/jobs/sync-stripe.py
@hourly curl -fsS http://localhost/healthz
*/5 * * * * /srv/jobs/diff-v1-v2.sh

HTTP/1.1 200 OK
# 200 OK: cron daemon يُعاد تحميله، الجدول نشط في أقل من ثانية.

ملف crontab هو بيانات يشحنها الفرع، لا حالة يتذكرها خادم cron. احذف الحاوية، ولن يبقى أي إدخال للتنظيف — الملف ذهب مع القرص.

use-cases / crontab-per-branch / powers

ثلاثة أشياء تتوقف عن فعلها

بمجرد أن يصبح الجدول ملفاً في المستودع، تختفي ثلاث فئات من العمل.

إصدارات

الجداول تركب على نفس diff الكود

عندما تُغيّر `billing-rollup.sh` إلى الإصدار 2، يصل الجدول الجديد في نفس pull request. المراجع يرى سطر cron إلى جانب السكربت مباشرة. تراجع عن commit واحد ويتراجع الجدول معه.

هدم

احذف الفرع، يذهب cron معه

حاويات الفروع عابرة. عندما تدمج الفرع أو تغلقه، تهدم الحاوية. ملف crontab كان يعيش داخلها، فيختفي الجدول دون حارس — لا يوجد خادم cron مشترك يحتفظ بإدخالات قديمة.

عزل

التجربة لا يمكن أن تنطلق في staging

مهمة تجريبية كل ساعة على `experiment/llm-rollups` تعمل في حاويتها الخاصة بنظام ملفاتها الخاص. cron daemon في staging لا يراها أبداً؛ cron daemon في production لا يراها أبداً. لا حاجة لحراسات `if BRANCH_ENV` داخل المهام نفسها.

use-cases / crontab-per-branch / compare

crontab مشترك مقابل crontab الفرع

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

المحورCRONTAB مشتركCRONTAB الفرع
مصدر الحقيقة
ويكي العمليات + دور ansibleالجدول يعيش في مستودع غير الذي يحتوي السكربت
.hoody/crontab في المستودعبجانب السكربت الذي يستدعيه سطر cron
إضافة مهمة
ادمج الكود → اطلب من العمليات → SSH إلى مضيف cronنظامان يجب أن يتوافقا، يدوياً
حرّر الملف، ادفع، انشرdiff واحد، دمج واحد، نشر واحد
عزل الفرع
if [ "$ENV" = staging ]; then …كل مهمة تعرف عن كل بيئة
حاوية لكل فرعلا علم بيئة داخل السكربت
التنظيف
تذكّر أن تحذف السطرالإدخالات القديمة تتراكم لسنوات
حذف الفرع = حذف cronنظام الملفات اختفى، الجدول اختفى
التجارب
crontab production هو الوحيدأي اختبار يخاطر بالانطلاق في prod
فرع تجريبي = crontab تجريبيينطلق فقط في حاويته

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

use-cases / crontab-per-branch / capacity

ما يمنحك إياه Hoody Cron فعلاً

Cron لكل حاوية هو سطح REST حقيقي — ثلاث عائلات من نقاط النهاية، صياغة cron قياسية، عزل كامل لكل مستخدم. الأرقام من مواصفات Cron API، لا معايير مُختلَقة.

  1. CRONTAB لكل حاوية1

    لكل حاوية فرع ملف crontab خاص بها لكل مستخدم. أرسل PUT للملف بأكمله، استرجعه بـ GET، استبدله بشكل ذرّي. لا جدول مواعيد مشترك خلف الكواليس.

  2. عائلات نقاط النهاية3

    crontab الخام (GET/PUT)، الإدخالات المُدارة (POST/PATCH/DELETE مع UUIDs و `expires_at`)، والقوائم لكل مستخدم. اختر ما يحتاجه سكربت النشر لديك.

  3. حقول لتعابير CRON5

    صياغة `min hour day month dow` القياسية بالإضافة إلى الماكروهات: `@hourly`, `@daily`, `@weekly`, `@monthly`, `@yearly`. نفس الصياغة التي يستخدمها `.hoody/crontab` لديك بالفعل.

وفقاً لـ Hoody Cron API: GET/PUT /users/[user]/crontab و POST/PATCH/DELETE /users/[user]/entries على عنوان URL خدمة cron الخاصة بكل حاوية.

use-cases / crontab-per-branch / punchline

الجدول يعيش بجانب الكود الذي يعمل عليه، في الحاوية نفسها، على الفرع نفسه.

قبل · نظامان لتذكّرهمابعد · ملف واحد في المستودع
ما كان لديك سابقاًالجدول في ops/ansible · الكود في app/ · لم يتفقا أبداًادمج الـ PR، ثم افتح تذكرة لتحديث مضيف cron
ما لديك الآنPUT @.hoody/crontab → cron-1.[branch].hoody.comPUT واحد، حاوية واحدة، جدول واحد، فرع واحد
اقرأ Cron API
use-cases / crontab-per-branch / replaces

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

ستة أماكن كان جدول cron يعيش فيها، لا واحد منها بجانب الكود. crontab المرتبط بالفرع يجعلها كلها زائدة عن الحاجة.

  • crontab production مشتركملف واحد على مضيف cron كان على كل فريق التنسيق حوله
  • مزامنة إعدادات cron يدويةدور Ansible / بيان Puppet مُطبَّق خارج نطاق دمج كودك
  • جداول GitHub Actions مثبَّتة على mainجداول مرتبطة بالفرع الافتراضي، غير مرئية لعمل الميزات والمعاينات
  • "تذكّر تحديث cron عند الدمج"بند قائمة تحقق بشري — الشيء الوحيد الذي يقف بينك وبين إدخال قديم
  • مستودع إعدادات cron منفصلمستودع ثانٍ مهمته الوحيدة التأخر عن المستودع الذي يحتوي الكود الفعلي
  • هجرات Atlas/Liquibase المجدولةأدوات هجرة تقوم بمهام جدولة لأنه لم يكن هناك مكان أفضل لتعيش فيه
use-cases / crontab-per-branch / cta

توقّف عن مزامنة الجداول عبر الأنظمة. أودِع crontab. دع الفرع يحمله.

اقرأ مستندات Cron
use-cases / crontab-per-branch / related

اقرأ الآخرين