using Microsoft.Extensions.Options; using Serilog; using System.Numerics; using System.Threading.Channels; using TriliumMind.Models; using TriliumMind.Services; namespace TriliumMind.Workers; public class JiraWorker : BackgroundService { private readonly Serilog.ILogger _log; private readonly AppConfigs _configs; private readonly IServiceScopeFactory _scopeFactory; // Singleton services cannot directly inject Scoped services. private readonly JiraService _jira; private readonly Channel _issueChannel; public JiraWorker(AppConfigs configs, IServiceScopeFactory serviceScopeFactory, JiraService jaraService, Channel issueChannel) { _log = Log.ForContext(); ; _configs = configs; _scopeFactory = serviceScopeFactory; _jira = jaraService; _issueChannel = issueChannel; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { _log.Debug("Worker running at: {time}", DateTimeOffset.Now); var configLastFetchTime = _configs.RuntimeConfigs.GetValueOrDefault(Consts.ConfigLastFetchTimeKey); if (string.IsNullOrEmpty(configLastFetchTime)) { using (var scope = _scopeFactory.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService(); var lastFetchTimeText = await db.GetConfigAsync(Consts.ConfigLastFetchTimeKey); configLastFetchTime = (lastFetchTimeText != null) ? lastFetchTimeText : DateTimeOffset.Now.AddDays(-1).ToString("yyyy-MM-ddTHH:mm:sszzz"); } } var lastFetchTime = DateTimeOffset.Parse(configLastFetchTime); var issueList = new List(); var currentFetchTime = DateTimeOffset.Now; foreach (var targetProject in _configs.AppSettings.Jira.TargetProjects) { int startAt = 0, total = 0; do { var response = await _jira.FetchJiraIssuesAsync(lastFetchTime, targetProject, startAt, stoppingToken); if (response != null) { total = response.total; startAt += response.maxResults; issueList.AddRange(response.issues); } } while(startAt < total); } foreach (var item in issueList) { await _issueChannel.Writer.WriteAsync(item, stoppingToken); } using (var scope = _scopeFactory.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService(); // Update last fetch time await db.SetConfigAsync(Consts.ConfigLastFetchTimeKey, currentFetchTime.ToString("yyyy-MM-ddTHH:mm:sszzz")); _configs.RuntimeConfigs[Consts.ConfigLastFetchTimeKey] = currentFetchTime.ToString("yyyy-MM-ddTHH:mm:sszzz"); } await Task.Delay(_configs.AppSettings.Jira.FetchInterval * 1000, stoppingToken); } } }