-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDailyProjectionArticleBackgroundService.cs
More file actions
69 lines (59 loc) · 2.63 KB
/
Copy pathDailyProjectionArticleBackgroundService.cs
File metadata and controls
69 lines (59 loc) · 2.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
using FantasyBasket.API.Models;
namespace FantasyBasket.API.Services;
/// <summary>
/// Regenerates the daily projections article for NBA and WNBA on a short interval.
/// The frequent cadence is intentional: it picks up last-minute injury changes
/// (OfficialInjuryService updates Player.InjuryStatus from ESPN) and re-projects
/// affected players. Generation upserts on (league, slate date), so re-running is
/// idempotent and only refreshes content.
/// </summary>
public class DailyProjectionArticleBackgroundService : BackgroundService
{
// Short enough that a late scratch shows up within ~half an hour; the HTTP
// ResponseCache (300s) already smooths read load, so this is purely write cadence.
private static readonly TimeSpan Interval = TimeSpan.FromMinutes(30);
private readonly IServiceScopeFactory _scopeFactory;
private readonly ILogger<DailyProjectionArticleBackgroundService> _logger;
public DailyProjectionArticleBackgroundService(
IServiceScopeFactory scopeFactory,
ILogger<DailyProjectionArticleBackgroundService> logger)
{
_scopeFactory = scopeFactory;
_logger = logger;
}
private static TimeZoneInfo EasternZone()
{
try { return TimeZoneInfo.FindSystemTimeZoneById("America/New_York"); }
catch (TimeZoneNotFoundException) { return TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"); }
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Daily Projection Article service is starting.");
var et = EasternZone();
while (!stoppingToken.IsCancellationRequested)
{
try
{
var slateDate = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, et).Date;
using var scope = _scopeFactory.CreateScope();
var service = scope.ServiceProvider.GetRequiredService<DailyProjectionArticleService>();
foreach (var league in new[] { ProLeagueType.NBA, ProLeagueType.WNBA })
{
try
{
await service.GenerateAndStoreAsync(league, slateDate, stoppingToken);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to generate projection article for {League}.", league);
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in Daily Projection Article service loop.");
}
await Task.Delay(Interval, stoppingToken);
}
}
}