انتقل إلى المحتوى
use-cases / cleanup-jobs-self-retire / hero
CRON · FILES · SELF-RETIRING

مهام تنظيف تجدول تقاعدها بنفسها

وفّر مُدخل cron مُداراً يوم بدء التنظيف. اضبط expires_at على بضعة أيام بعد آخر تشغيل متوقّع. السكربت يقطع العمل ليلاً، ثم يُرسل DELETE لنفسه حين لا يبقى شيء. لا تذكير في التقويم، لا crontab زومبي، ولا مراجعة سنوية لتنظيف-المُنظِّفات.

توثيق cron
cleanup-stale-uploads.sh
# tail of cleanup-stale-uploads.sh
removed=$(find /uploads -mtime +90 -delete -print | wc -l)
echo "$removed files removed"

# self-aware tail: nothing left → retire
if [ -z "$(ls /uploads)" ]; then
  curl -fsS -X DELETE \
    "$CRON_URL/entries/$ENTRY_ID"
fi

الذيل الواعي لذاته. مُدخل cron هو السطر الأخير من سكربته الخاص.

use-cases / cleanup-jobs-self-retire / lifecycle

تنظيف بعمر مُنتهٍ، بالبناء

ثلاث مراحل منفصلة. كل انتقال آلي، ولا واحد منها يحتاج إنساناً ليتذكّر. المُدخل يعرف متى ينتهي عمله ومتى تنقضي خانته في التقويم.

LIFECYCLE · SCHEDULE → SLICE → SELF-DELETEمُدخل واحد، حياة مُنتهية
1 · SCHEDULE

أرسل POST لمُدخل واحد يوم بدء التنظيف

الجدول @daily، الأمر يُشير إلى سكربت تقطيع، expires_at مضبوط على ما بعد آخر تشغيل متوقّع بقليل. الموعد النهائي في المُدخل — لا في وثيقة Notion، ولا في خيط Slack.

2 · SLICE

السكربت يقتطع كل ليلة، بلطف

كل تشغيل يحذف شريحة من البيانات القديمة كي لا تُرهَق قاعدة البيانات. اليوم الأول قد يمسح 247 ملفاً؛ اليوم السادس فقط 1. الإيقاع محدود بما تبقّى فعلاً.

3 · SELF-DELETE

حين ينتهي العمل، يتقاعد المُدخل

آخر كتلة في السكربت تتفقّد ما إذا كان الهدف فارغاً. إن نعم، تُطلق DELETE /entries/[self]. وإن لم تفعل لسبب ما، تُطلق expires_at شبكة الأمان بعد بضعة أيام.

محرّكان مستقلّان — تحقّق السكربت الذاتي وexpires_at على مستوى API — يتلاقيان في النتيجة نفسها: سطر في crontab لا يعيش أطول من غرضه.

use-cases / cleanup-jobs-self-retire / mechanism

استدعاءا HTTP، تنظيف واحد مُنتهٍ

Hoody Cron غلاف JSON-CRUD حول crontab النظام. POST يُنشئ المُدخل؛ DELETE يُزيله؛ expires_at هو شبكة الأمان. السكربت الذي يعمل ليلاً هو من يعرف متى انتهى — لذا هو من يستدعي DELETE.

create-entry.sh
DAY 0 · POST
# day 0 — provision the cleanup
curl -X POST \
  https://cron.containers.hoody.com/users/me/entries \
  -H "Content-Type: application/json" \
  -d '["schedule":"@daily","command":"/srv/jobs/cleanup-stale-uploads.sh","expires_at":"2026-05-05T00:00:00Z"]'

# response
HTTP/1.1 201 Created
{ "id":"f3a1", "expires_at":"2026-05-05T00:00:00Z", "enabled":true }
cleanup-stale-uploads.sh
DAY 7 · DELETE
# inside the cron command itself
if [ -z "$(ls /uploads)" ]; then
  curl -X DELETE \
    "$CRON_URL/entries/$ENTRY_ID"
fi

# response
HTTP/1.1 204 No Content
# entry f3a1 was here. f3a1 deleted itself.

$ENTRY_ID هو UUID الذي أعاده POST — يستطيع السكربت قراءته من ملف مرّره سطر أمر المُدخل، أو من $HOODY_ENTRY_ID وقت التشغيل. على أي حال، مُدخل cron يحذف مُدخل cron.

use-cases / cleanup-jobs-self-retire / powers

ما الذي يفتحه التنظيف ذاتي التقاعد

ليس الحذف هو ما يهمّ. بل أنه لا أحد يحتاج أن يتذكّر وجود أيّ من هذا بعد ثلاثة أشهر من الآن.

PRESSURE-FREE PACING

شريحة بعد شريحة، لا دفعة واحدة

@daily يعمل كل 24 ساعة. السكربت يحذف شريحة من البيانات القديمة — بضعة آلاف من الملفات، بضعة آلاف من الصفوف — ويخرج. قاعدة البيانات تبقى هادئة؛ منحنى الحمل يبدو وكأن شيئاً لم يحدث.

بلا CRONTAB ZOMBIE

السطر لا يعيش أطول من المهندس

expires_at في المُدخل بصيغة JSON. حين يُطلق، يُحذف السطر من crontab النظام. ثلاثة مهندسين من الآن، لا أحد يتصفّح 200 سطر متسائلاً ماذا يفعل cleanup-stale-uploads-v3 بعد.

زناد اثنين، نتيجة واحدة

Self-DELETE مع شبكة أمان expires_at

السكربت يُرسل DELETE لنفسه ليلة انتهاء العمل. إن تخطّى خلل ذلك المسار، expires_at يُقاعد المُدخل بعد بضعة أيام. آليتان مستقلّتان؛ واحدة منهما ستُطلق.

use-cases / cleanup-jobs-self-retire / capacity

كيف يتسع هذا

كل مُدخل مُدار هو صفّ JSON يحقنه API في crontab النظام. التوسّع محدود بما يستطيع cron نفسه أن يحمله، لا بـ Hoody.

  1. إيقاع التشغيل1 / يوم

    @daily هو الإيقاع المعتاد للتنظيف. إن احتجت تمريرات أكثر تواتراً تستطيع استخدام تعابير الخمسة حقول وصولاً إلى * * * * * — دقّة الدقيقة.

  2. عمر المُدخلexpires_at

    طابع زمني ISO-8601 على المُدخل. حين يمضي، يُزيل API السطر في الكنس التالي. التنظيف لا يتمدّد قطّ بعد موعده النهائي.

  3. تفكيك HTTPDELETE · 204

    DELETE /users/[user]/entries/[id] من داخل الأمر قيد التشغيل يعمل لأن عفريت cron لا يقفل crontab الخاص به — API يكنس التغيير بأمان.

تعابير cron قياسية من خمسة حقول مع الماكروات (@hourly, @daily, @weekly, @monthly, @yearly). عزل لكل مستخدم؛ كل مستخدم نظام يحصل على crontab خاص به. صفحة Cron في Hoody Kit توثّق كلّاً من المُدخلات المُدارة وaccess crontab الخام إن احتجت الشكل الأقدم.

use-cases / cleanup-jobs-self-retire / punchline

التنظيف يعمل ليلاً حتى يختفي الشيء الذي يجري تنظيفه.

BEFORE · CALENDAR REMINDERS, ZOMBIE CRON LINESبعد · إدخال CRON يعرف متى انتهى
BEFORE// TODO: حذف هذا حين /uploads فارغ (2026؟)تعليق سيقرؤه نفسك المستقبلي مرة واحدة ثم لا يقرؤه أبداً.
NOWDELETE /entries/$ENTRY_ID · expires_at: 2026-05-05تفكيك يُطلَق من السكربت وموعد نهائي مُدرَج في المُدخل ذاته.
مرجع Cron API
use-cases / cleanup-jobs-self-retire / replaces

ما الذي يحلّ هذا محلّه

في أيّ مكان يُفترض فيه بمهمة تنظيف أن تختفي من تلقاء نفسها — هذه هي الأنماط التي يحلّ هذا محلّها:

  • مهام cron تنظيف زومبيأسطر من 2022 لا أحد يجرؤ على حذفها
  • // TODO: حذف هذا حين X فارغتعليق أصبح دائماً
  • سكربتات حارس يدويةزميل يُشغّلها فصلياً، حين يتذكّر
  • Kubernetes CronJobs لا تحذف نفسها أبداًttlSecondsAfterFinished على البود، لا على الجدول
  • مُدراء دورة حياة مخصّصون واعون لذاتهمخدمة محلّية تراقب خدماتك الأخرى
  • سياسات دورة حياة مُدارة بـ TerraformPlan، apply، بعد ستة أشهر لا تزال في tfstate
use-cases / cleanup-jobs-self-retire / cta

وفّر التنظيف. اضبط تاريخ تقاعده. وامشِ بعيداً.

اقرأ توثيق Cron
use-cases / cleanup-jobs-self-retire / related

اقرأ الآخرين