I have built out a service to create an erxcel report which uploads to a cloud storage provider. I am creating a scheduled task to occur at midnight every night to run this service. My issue is I often am redeploying my application for updates and all and I am trying to figure out how to get this background task to run every time I redeploy. Can this be done automatically or do I need to create a controller action and manually remember to call it so the task starts?
My code is as follows:
public class ReviewSummaryBackgroundService : BackgroundService
{
protected IReviewSummaryService _reviewSummaryService;
public ReviewSummaryBackgroundService(IReviewSummaryService reviewSummaryService)
{
_reviewSummaryService = reviewSummaryService;
}
private static int SecondsUntilMidnight()
{
return (int)(DateTime.Today.AddDays(1.0) - DateTime.Now).TotalSeconds;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var countdown = SecondsUntilMidnight();
while (!stoppingToken.IsCancellationRequested)
{
if (countdown-- <= 0)
{
try
{
await OnTimerFiredAsync(stoppingToken);
}
catch(Exception ex)
{
// in future log exception
}
finally
{
countdown = SecondsUntilMidnight();
}
}
await Task.Delay(1000, stoppingToken);
}
}
private async Task OnTimerFiredAsync(CancellationToken stoppingToken)
{
await _reviewSummaryService.ExportExcelReportAsync();
}
}
Assuming you're registering the background service as follows, it will be started when your application starts:
builder.Services.AddHostedService<ReviewSummaryBackgroundService>();
If you want to ensure that the report doesn't get created on each local debugging attempt, but when deployed to your prod environment, you could take advantage of the ASPNETCORE_ENVIRONMENT
public ReviewSummaryBackgroundService(IWebHostEnvironment env, IReviewSummaryService reviewSummaryService)
{
_Env = env;
//...
}
private static TimeSpan TimeUntilMidnight()
{
return DateTime.Today.AddDays(1) - DateTime.Now;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var delay = _Env.IsProduction() ? TimeSpan.Zero : TimeUntilMidnight();
while (!stoppingToken.IsCancellationRequested)
{
await Task.Delay(delay, stoppingToken);
try
{
await OnTimerFiredAsync(stoppingToken);
}
catch (Exception ex)
{
// in future log exception
}
delay = TimeUntilMidnight();
}
}