تسکهای پس زمینه (Background Job) چیست؟
سؤال : HangFire چیست؟
مقایسه HangFire و Quartz
دیتابیس :
ساختار :
داشبورد :
استفاده از HangFire
1. نصب :
- برای نصب HangFire در یک پروژهی Asp.Net Core لازم است ابتدا پکیجهای مورد نیاز آن را نصب کنید؛ که شامل موارد زیر است:
Install-Package Hangfire.Core Install-Package Hangfire.SqlServer Install-Package Hangfire.AspNetCore
- پس از نصب پکیجها باید تنظیمات مورد نیاز برای پیاده سازی HangFire را در برنامه، اعمال کنیم. این تنظیمات شامل افزودن سرویسها و اینترفیسهای HangFire به برنامه است که اینکار را با افزودن HangFire به متد ConfigureService کلاس Startup انجام خواهیم داد:
public void ConfigureServices(IServiceCollection services) { // Add Hangfire services. services.AddHangfire(configuration => configuration .SetDataCompatibilityLevel(CompatibilityLevel.Version_170) .UseSimpleAssemblyNameTypeSerializer() .UseRecommendedSerializerSettings() .UseSqlServerStorage(Configuration.GetConnectionString("HangfireConnection"), new SqlServerStorageOptions { CommandBatchMaxTimeout = TimeSpan.FromMinutes(5), SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5), QueuePollInterval = TimeSpan.Zero, UseRecommendedIsolationLevel = true, DisableGlobalLocks = true })); // Add the processing server as IHostedService services.AddHangfireServer(); // Add framework services. services.AddMvc(); }
- پکیج HangFire برای مدیریت کار و زمان ، Table هایی دارد که پس از نصب، بر روی دیتابیس برنامهی شما قرار میگیرد. فقط باید دقت داشته باشید ConnectionString دیتابیس خود را در متد AddHangFire مقدار دهی کنید، تا از این طریق دیتابیس برنامه را شناخته و Tableهای مورد نظر را در Schema جدیدی با نام HangFire به آن اضافه کند.
- این پکیج یک داشبورد اختصاصی دارد که در آن لیستی از انواع تسکهای در صف انجام و گزارشی از انجام شدهها را در اختیار ما قرار میدهد. برای تنظیم این داشبورد باید Middleware مربوط به آن و endpoint جدیدی را برای شناسایی مسیر داشبورد HangFire در برنامه، در متد Configure کلاس Startup اضافه کنید :
public void Configure(IApplicationBuilder app, IBackgroundJobClient backgroundJobs, IHostingEnvironment env) { // HangFire Dashboard app.UseHangfireDashboard(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); // HangFire Dashboard endpoint endpoints.MapHangfireDashboard(); }); }
http://localhost:50255/hangfire
app.UseHangfireDashboard("/mydashboard");
http://localhost:50255/mydashboard
2. داشبورد :
3. امنیت داشبورد :
public class MyAuthorizationFilter : IDashboardAuthorizationFilter { public bool Authorize(DashboardContext context) { var httpContext = context.GetHttpContext(); // Allow all authenticated users to see the Dashboard (potentially dangerous). return httpContext.User.Identity.IsAuthenticated; } }
app.UseHangfireDashboard("/hangfire", new DashboardOptions { Authorization = new [] { new MyAuthorizationFilter() } });
app.UseHangfireDashboard("/hangfire", new DashboardOptions { IsReadOnlyFunc = (DashboardContext context) => true });
انواع تسکها در HangFire :
1. تسکهای Fire-And-Forget :
public class HomeController : Controller { private readonly IBackgroundJobClient _backgroundJobClient; public HomeController(IBackgroundJobClient backgroundJobClient) { _backgroundJobClient = backgroundJobClient; } [HttpPost] [Route("welcome")] public IActionResult Welcome(string userName) { var jobId = _backgroundJobClient.Enqueue(() => SendWelcomeMail(userName)); return Ok($"Job Id {jobId} Completed. Welcome Mail Sent!"); } public void SendWelcomeMail(string userName) { //Logic to Mail the user Console.WriteLine($"Welcome to our application, {userName}"); } }
2. تسکهای Delayed :
- دسته اول : اجرا پس از تاخیر در زمانی مشخص.
public class HomeController : Controller { private readonly IBackgroundJobClient _backgroundJobClient; public HomeController(IBackgroundJobClient backgroundJobClient) { _backgroundJobClient = backgroundJobClient; } [HttpPost] [Route("welcome")] public IActionResult Welcome(string userName) { var jobId = BackgroundJob.Schedule(() => SendWelcomeMail(userName),TimeSpan.FromMinutes(10)); return Ok($"Job Id {jobId} Completed. Welcome Mail Sent!"); } public void SendWelcomeMail(string userName) { //Logic to Mail the user Console.WriteLine($"Welcome to our application, {userName}"); } }
- دسته دوم : اجرا در زمانی مشخص.
public class HomeController : Controller { private readonly IBackgroundJobClient _backgroundJobClient; public HomeController(IBackgroundJobClient backgroundJobClient) { _backgroundJobClient = IBackgroundJobClient; } [HttpPost] [Route("welcome")] public IActionResult Welcome(string userName , DateTime dateAndTime) { var jobId = BackgroundJob.Schedule(() => SendWelcomeMail(userName),DateTimeOffset(dateAndTime)); return Ok($"Job Id {jobId} Completed. Welcome Mail Sent!"); } public void SendWelcomeMail(string userName) { //Logic to Mail the user Console.WriteLine($"Welcome to our application, {userName}"); } }
3. تسکهای Recurring :
public class HomeController : Controller { private readonly IRecurringJobManager _recurringJobManager; public HomeController(IRecurringJobManager recurringJobManager) { _recurringJobManager = recurringJobManager; } [HttpPost] [Route("BackUp")] public IActionResult BackUp(string userName) { _recurringJobManager.AddOrUpdate("test", () => BackUpDataBase(), Cron.Weekly); return Ok(); } public void BackUpDataBase() { // ... } }
- هر دقیقه (Cron.Minutely) :
_recurringJobManager.AddOrUpdate("test", () => job , Cron.Minutely);
- هر ساعت (Cron.Hourly) :
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Hourly);
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Hourly(10));
- هر روز (Cron.Daily) :
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Daily);
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Daily(3,10));
- هر هفته (Cron.Weekly) :
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Weekly);
_recurringJobManager.AddOrUpdate("test", () => Job,Cron.Weekly(DayOfWeek.Monday,3,10));
- هر ماه (Cron.Monthly) :
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Monthly);
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Monthly(10,3,10));
- هر سال (Cron.Yearly) :
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Yearly);
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Yearly(2,4,3,10));
4. تسکهای Continuations :
var stepOne = _backgroundJobClient.Schedule(() => SendAuthorizationEmail(), TimeSpan.FromMinute(10)); _backgroundJobClient.ContinueJobWith(stepOne, () => _backgroundJobClient.Schedule(() => ExpireAuthorizationEmail(), TimeSpan.FromHours(5)));
برخی از نکات و ترفندهای HangFire
1. استفاده از Cron Expression در Recurring Jobها :
* * * * * command to be executed - - - - - | | | | | | | | | ----- Day of week (0 - 7) (Sunday=0 or 7) | | | ------- Month (1 - 12) | | --------- Day of month (1 - 31) | ----------- Hour (0 - 23) ------------- Minute (0 - 59)
* * * * *
- فیلد اول (Minute) : در این فیلد باید دقیقهای مشخص از یک ساعت را وارد کنید؛ مانند دقیقه 10 (میتوانید محدودهای را هم تعیین کنید)
- فیلد دوم (Hour) : در این فیلد باید زمان معلومی را با فرمت ساعت وارد کنید؛ مانند ساعت 7 (میتوانید محدودهای را هم تعیین کنید، مانند ساعات 12-7)
- فیلد سوم (Day of Month) : در این فیلد باید یک روز از ماه را وارد کنید؛ مانند روز 15 ام از ماه (میتوانید محدودهای را هم تعیین کنید)
- فیلد چهارم (Month) : در این فیلد باید یک ماه از سال را وارد کنید؛ مثلا ماه 4 ام(آوریل) (میتوانید محدودهای را هم تعیین کنید)
- فیلد پنجم (Day of Week) : در این فیلد باید روزی از روزهای هفته یا محدودهای از آن روزها را تعیین کنید. مانند صفرم هفته که در کشورهای اروپایی و آمریکایی معادل روز یکشنبه است.
0 4 10-15 * *
_recurringJobManager.AddOrUpdate("test", () => job , "0 4 10-15 * *" );
2. متد Trigger :
RecurringJob.Trigger("some-id");
3. تعیین تاریخ انقضاء برای Recurring Jobها :
_recurringJobManager.AddOrUpdate("test", () => Console.WriteLine("Recurring Job"), Cron.Monthly); _backgroundJobClient.Schedule(() => _recurringJobManager.RemoveIfExists("test"), DateTimeOffset(dateAndTime));