صيغة كرون في Hangfire
يحلّل Hangfire الجداول بمكتبة Cronos، ويحدّد الصيغة من عدد الحقول: خمسة من الدقيقة إلى يوم الأسبوع، أو ستة بإضافة حقل الثواني في البداية.
| الحقل | القيم المسموحة | الرموز الخاصة |
|---|---|---|
| الثانية | 0–59 (اختياري، ويأتي أولًا) | , - * / |
| الدقيقة | 0–59 | , - * / |
| الساعة | 0–23 | , - * / |
| يوم الشهر | 1–31 | , - * ? / L W |
| الشهر | 1–12 أو JAN–DEC | , - * / |
| يوم الأسبوع | 0–7 أو SUN–SAT (0 و7 = الأحد) | , - * ? / L # |
الرموز الخاصة
| الرمز | المعنى |
|---|---|
L | الأخير. في حقل يوم الشهر يعني L آخر يوم في الشهر، وL-2 ما قبله بيومين. وفي حقل يوم الأسبوع يعني 5L أو FRIL آخر جمعة في الشهر، ولا يُقبل L وحده في هذا الحقل. |
W | أقرب يوم عمل (من الإثنين إلى الجمعة) إلى تاريخ معيّن دون الخروج من الشهر: 15W. وLW هو آخر يوم عمل في الشهر، وL-3W أقرب يوم عمل إلى ما قبل نهاية الشهر بثلاثة أيام. |
# | ترتيب اليوم في الشهر: 1#1 أول إثنين، وFRI#3 ثالث جمعة. |
? | مثل * تمامًا، وهو اختياري، لذا يُقبل تعبير من ستة حقول مكتوب بأسلوب Quartz مثل 0 0 12 ? * MON. |
- | النطاقات، ويمكن أن تلتف إلى البداية: 22-2 في حقل الساعة يعني من 22:00 إلى 02:59، وFRI-MON من الجمعة إلى الإثنين. |
@ | الاختصارات: @every_second و@every_minute و@hourly و@daily و@weekly و@monthly و@yearly. |
أمثلة على كرون Hangfire
اضغط على أي تعبير لتحميله في المولّد أعلاه.
| التعبير | الجدول الزمني |
|---|---|
| كل 5 دقائق. | |
| كل 30 ثانية. | |
| في تمام الساعة 8:00 ص، من الإثنين إلى الجمعة. | |
| كل 15 دقيقة، بين 10:00 م و2:59 ص. | |
| في تمام الساعة 12:00 ص، في آخر يوم من الشهر. | |
| في تمام الساعة 6:00 م، في آخر يوم عمل (من الإثنين إلى الجمعة) من الشهر. | |
| في تمام الساعة 9:00 ص، في أول إثنين من الشهر. | |
| في تمام الساعة 5:00 م، في آخر جمعة من الشهر. | |
| في تمام الساعة 12:00 ص، في اليوم 13 من الشهر، بشرط أن يوافق ذلك اليوم يوم الجمعة. | |
| في تمام الساعة 12:00 ص. |
الفرق بين كرون Hangfire وكرون لينكس
- إذا حدّدت حقلي اليوم معًا فيجب أن يتطابقا معًا. فالتعبير
0 0 13 * 5لا يعمل في Hangfire إلا يوم الجمعة الموافق 13، بينما يشغّله كرون لينكس في كل يوم 13 وفي كل جمعة. - الحقل السادس يعني الثواني، وليست هذه صيغة Quartz. فالتعبير
0 0 12 ? * 2مقبول، لكن2تعني هنا الثلاثاء وتعني في Quartz الإثنين، أما الحقل السابع (السنة في Quartz) فمرفوض. - تعمل الجداول بتوقيت UTC ما لم تضبط
RecurringJobOptions.TimeZone. ويتولى Hangfire التوقيت الصيفي عنك: فالمهمة المقررة الساعة 02:30 في الليلة التي تُقدَّم فيها الساعة تعمل الساعة 03:00 بدلًا من أن تُتخطى. - الجداول بالثواني تعمل، لكن المجدول يفحص المهام المتكررة المستحقة كل 15 ثانية افتراضيًا (
SchedulePollingInterval)، لذا لن يعمل*/5 * * * * *كل خمس ثوانٍ فعلًا.
الاستخدام في C#
سجّل المهمة مرة واحدة عند تشغيل التطبيق، ومرّر المنطقة الزمنية في RecurringJobOptions، وإلا فسيستخدم Hangfire توقيت UTC:
RecurringJob.AddOrUpdate<ReportService>(
"weekday-report",
service => service.SendDailyReport(),
"0 8 * * 1-5",
new RecurringJobOptions
{
TimeZone = TimeZoneInfo.FindSystemTimeZoneById("Asia/Riyadh")
});
وتعمل الصيغة نفسها دون Hangfire عبر حزمة Cronos:
using Cronos;
var expression = CronExpression.Parse("*/30 * * * * *", CronFormat.IncludeSeconds);
DateTime? next = expression.GetNextOccurrence(DateTime.UtcNow); // in UTC
يكتب الصنف المساعد Cron التعبيرات الشائعة نيابةً عنك: Cron.Daily(2, 30) يعيد 30 2 * * *، وCron.Weekly(DayOfWeek.Monday, 9) يعيد 0 9 * * 1، وCron.Never() يعيد 0 0 31 2 * الذي يُبقي المهمة مسجّلة دون أن تعمل أبدًا.
الأسئلة الشائعة
هل يدعم Hangfire الثواني في تعبيرات الكرون؟
نعم. يعتمد Hangfire على عدد الحقول: خمسة تعني من الدقيقة إلى يوم الأسبوع، وستة تضيف الثواني في البداية، فالتعبير */30 * * * * * يعمل كل 30 ثانية. لكن مجدول المهام المتكررة يفحص كل 15 ثانية افتراضيًا، لذا قلّل قيمة SchedulePollingInterval في BackgroundJobServerOptions إذا احتجت إلى فواصل أقصر من ذلك.
ما المنطقة الزمنية التي تستخدمها مهمة Hangfire المتكررة؟
توقيت UTC، ما لم تحدّد غيره: new RecurringJobOptions { TimeZone = TimeZoneInfo.FindSystemTimeZoneById("Asia/Dubai") }. وعندها يتبع Hangfire تلك المنطقة، بما في ذلك تغييرات التوقيت الصيفي إن كانت تطبّقه.
لماذا يعمل التعبير 0 0 13 * 5 في Hangfire أقل مما يعمل في كرون تاب؟
تشترط مكتبة Cronos، التي يعتمد عليها Hangfire، أن يتطابق حقلا اليوم معًا، فلا تعمل المهمة إلا يوم الجمعة الموافق 13. أما كرون لينكس فيشغّلها في كل يوم 13 وفي كل جمعة. وللحصول على سلوك كرون تاب سجّل مهمتين متكررتين: 0 0 13 * * و0 0 * * 5.
هل تعبير الكرون في Hangfire هو نفسه في Quartz.NET؟
لا. يبدأ تعبير Quartz.NET بالثواني، ويعدّ الأحد 1، ويتطلب ? في أحد حقلي اليوم، ويسمح بحقل للسنة. أما Hangfire فيقبل كرون القياسي بخمسة حقول مع ثوانٍ اختيارية. ولمشغّلات Quartz.NET استخدم مولد Quartz في الروابط أدناه.
هل يمكنني استخدام هذه الصيغة دون Hangfire؟
نعم. ثبّت حزمة Cronos من NuGet واستدعِ CronExpression.Parse("0 8 * * 1-5")، وأضف CronFormat.IncludeSeconds للتعبيرات ذات الستة حقول. وتعيد GetNextOccurrence(DateTime.UtcNow) موعد التشغيل التالي بتوقيت UTC.
مولدات كرون لمنصات أخرى
*/15 8-18 * * 1-5
مولد تعبيرات كرون Quartz
0 0 8 ? * MON-FRI
مولد تعبيرات كرون لـ Spring
0 0 8 * * MON-FRI
مولد تعبيرات كرون لـ AWS
0 8 ? * MON-FRI *
مولد تعبيرات كرون لـ Jenkins
H 2 * * 1-5
مولد تعبيرات كرون لـ Salesforce
0 0 8 ? * MON-FRI
مولد تعبيرات كرون لـ Airflow
0 6 * * 1-5
مولد تعبيرات node-cron
0 30 8 * * 1-5