قبل از اینکه برویم سراغ استفاده از Hangfire بیاید تعریفی از background job ها داشته باشیم، این نوع Job
ها برای در صف قرار دادن برخی فرایندها مورد استفاده قرار میگیرند که در پس زمینه اجرا می شوند.
به عنوان مثال اجرای task های طولانی مدت بدون اینکه کاربر نهایی منتظر اتمام آن باشد، یا دریافت یک گزارش از برنامه که برای تولید این گزارش زمان زیادی نیاز داشته باشیم.
یکی از پکیج های open-source که میتوان استفاده کرد Hangfire میباشد. این پکیچ بهصورت چند نخی (multi-thread) است و به سادگی قابل ارتقا می باشد، همچنین به دلیل ساختار خوبی که دارد به شما عملکرد بسیار قدرتمندی ارائه می دهد.
بهصورت کلی برای انجام task های پس زمینه مانند ارسال ایمیل، import کردن فایل ها، ویدیوها، نگهداری پایگاه داده و ... را در اختیار شما قرار می دهد.
از طریق داشبورد Hangfire میتوانیم تمامی job های در حال اجرا یا زمانبندی شده را که توسط hangfire client ایجاد شده است را مشاهده کنیم، همچنین این در داشبورد میتوانید تمامی خطاها، job هایی که باید دوباره اجرا شوند، و آنهایی که در صف اجرا هستند را مشاهده کرد.
یکی دیگر از مزایای استفاده از این داشبورد اجرای دستی job ها هستند.
در حال حاضر 6 نوع تایپ برای اجرای Job ها در hangfire وجود دارند:
این نوع job ها فقط یکبار بعد از ایجاد اجرا میشوند و سپس از چرخه ی اجرا برای همیشه خارج میشوند.
این نوع job ها تنها یکبار اجرا می شوند، اما نه بعد از ایجاد آن، بلکه در یک دوره زمانی مشخص.
این نوع job چندین بار در طول زمانی متفاوت اجرا می شوند، به عنوان مثال روزی یکبار، یا هر ساعت و...
این نوع job زمانی اجرا میشوند که جاب پدر (parent job) به اتمام رسیده باشد.
همچنین دو نوع دیگر job ها وجود دارند اما در نسخه open-source ارائه نمی شوند و نیاز به تهیه لایسنس مربوط به آن هستین، این دو نوع Batches و Batch Continuations هستند.
این نوع جاب همانطور که از نام آن پیداست، گروهی از جاب ها را شامل میشوند که به بهصورت خودکار قابل اجرا هستند.
این نوع جاب زمانی اجرا میشوند که جاب پدر (parent job) به اتمام رسیده باشد.
قدم 1
بعد از تعاریف Hangfire نوبت آن است که آن را پیادهسازی کنیم، برای این منظور نیاز به ایجاد یک پروژه ASP.NET Core Web API داریم.
بدین منظور در Visual Studio 2022 یک پروژه ایجاد میکنیم.
قدم 2
نام پروژه را به همراه مقصد آن مشخص میکنیم.
قدم 3
فریم ورک و همچنین نوع اجرا شدن آن را مشخص میکنیم، در اینجا فریم ورک را NET 7. انتخاب میکنیم.
قدم 4
بعد از ایجاد پروژه اقدام به نصب پکیج های مربوط به Hangfire میکنیم.
Hangfire.AspNetCore Hangfire.SqlServer Microsoft.Data.SqlClient
قدم 5
حال نیاز داریم که تایپهای مختلفی که در بالا اشاره کردم را در یک کنترلر پیادهسازی کنیم.
using Microsoft.AspNetCore.Mvc; namespace HangfireDemo.Controllers; [ApiController] public class HomeController : Controller { }
[HttpGet] [Route("FireAndForgetJob")] public string FireAndForgetJob() { var jobId = BackgroundJob.Enqueue(() => Console.WriteLine("Hello world - Fire and Forget Job")); return $"Job ID: {jobId}, Hello world - Fire and Forget Job" }
برای تعریف FireAndForgetJob باید از متد Enqueue استفاده کنیم سپس بعد از ایجاد جاب، بلافاصله اجرا خواهد شد.
[HttpGet] [Route("DelayedJob")] public string DelayedJob() { var jobId = BackgroundJob.Schedule(() => Console.WriteLine("Hello world - Delayed Job"), TimeSpan.FromSeconds(30)); return $"Job ID: {jobId}, Hello world - Delayed Job" }
برای تعریف DelayedJobباید از متد Schedule استفاده کنیم سپس بعد از ایجاد جاب،در بازه زمانی مشخص اجرا خواهد شد، در این مثال 30 ثانیه پس از ایجاد Job آن اجرا خواهد شد.
[HttpGet] [Route("ContinuousJob")] public string ContinuousJob() { var parentJobId = BackgroundJob.Enqueue(() => Console.WriteLine("Hello world - Fire and Forget Job")); BackgroundJob .ContinueJobWith(parentJobId, () => Console.WriteLine("Hello world - continuous Job")); return "Welcome user in continuous Job Demo!" }
در این نوع جاب ابتدا از طریق متد Enqueue یک جاب را ایجاد کردیم، سپس پس از اجرا شدن آن از طریق متد ContinueJobWith، با شناسه مربوط به جاب پدر جاب فرزند را اجرا میکنیم.
[HttpGet] [Route("RecurringJob")] public string RecurringJobs() { RecurringJob .AddOrUpdate(() => Console.WriteLine("Hello world - Recurring Job"), Cron.Weekly); return "Hello world - Recurring Job " }
این جاب بهصورت دوره ای اجرا خواهد شد، بدین منظور از متد AddOrUpdate استفاده میکنیم، به عنوان مثال این جاب بهصورت هفتگی اجرا خواهد شد.
قدم 6
در این قدم تنظیمات مربوط به پایگاه داده را در appsettings.json پیکربندی میکنیم.
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { "HangfireConnection": "Server=localhost;Database=dashboard;Integrated Security=true;MultipleActiveResultSets=true;TrustServerCertificate=Yes;" } }
قدم 7
حال نوبت به آن رسیده که پیکربندی Hangfire را در pipeline و middleware خود انجام دهیم، بدین منظور باید پیکربندی مربوط به پایگاه داده، ثبت کردن سرویس hangfire و همچنین پیکربندی UI را انجام دهیم.
builder.Services.AddHangfire(x => { x.UseSqlServerStorage(builder.Configuration["ConnectionStrings:HangfireConnection"]); x.UseSimpleAssemblyNameTypeSerializer(); x.UseRecommendedSerializerSettings(); });
در کد بالا تنظیمات مربوط به پایگاه داده را پیکربندی کردیم.
builder.Services.AddHangfireServer();
حال سرویس مربوط به سرور hangfire را ثبت میکنیم، این سرویس به صورت Transient ثبت خواهد شد.
و در نهایت برای دسترسی به داشبورد و فراهم کردن UI از کد زیر استفاده میکنیم.
app.UseHangfireDashboard("/dashboard");
فایل program.cs در نهایت شبیه به زیر خواهد بود.
using Hangfire; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddHangfire(x => { x.UseSqlServerStorage(builder.Configuration["ConnectionStrings:HangfireConnection"]); x.UseSimpleAssemblyNameTypeSerializer(); x.UseRecommendedSerializerSettings(); }); builder.Services.AddHangfireServer(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.UseHangfireDashboard("/dashboard"); app.Run();
قدم 8
قبل از اجرای برنامه اجازه دهید تا فایل launchSetting.json را به صورا زید بروز رسانی کنیم تا برنامه ما در پورت 5001 اجرا شود.
"https": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "swagger", "applicationUrl": "https://localhost:5001;http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } },
قدم 9
زمان آن فرارسیده است تا برنامه خود را اجرا کنیم.
بعد از اجرای برنامه، پنجره swagger باز خواهد شد و شما تمامی endpoint های API خود را در آن مشاهد خواهید کرد.
همچنین جداول پایگاه داده ایجاد شده نیز به شکل زیر خواهند بود.
قدم 10
حال زمان آن رسیده است تا endpoint های API خود را اجرا کنیم، برای این منظور در صفحه Swagger تمامی endpoint ها را یک به یک اجرا میکنیم و سپس به داشبورد hangfire مراجعه میکنیم.
داشبورد تمامی جاب های در حال اجرا یا زمانبندی شده را نمایش می دهد، همنچنین می توانیم اجرای جاب ها، خطاهای موجود در جاب ها و همچنین جابهای زمانبندی شده را نیز در این داشبورد مشاهده کنیم.
در این مقاله نگاهی کردیم به پیادهسازی Hangfire در NET 7. و همچنین نحوه ایجاد background job ها.