refactor(dotnet): standardize scheduler state and definitions
Validators (Pushes and Pull Requests) / validate-ui-and-storage (push) Successful in 23s
Validators (Pushes and Pull Requests) / validate-core (push) Successful in 2m9s

This commit is contained in:
2026-07-13 00:08:28 +09:00
parent eb3a33f124
commit d7c106f292
3 changed files with 56 additions and 13 deletions
@@ -0,0 +1,26 @@
namespace QuantEngine.Web.Services;
public sealed record SchedulerJobDefinition(
string JobId,
string Cron,
string Description,
bool IsRecurring);
public sealed record SchedulerJobExecutionAudit(
string JobId,
string RunId,
string State,
string? Reason,
DateTimeOffset StartedAt,
DateTimeOffset? FinishedAt,
string? ResourceKey);
public static class SchedulerStates
{
public const string Pending = "PENDING";
public const string Running = "RUNNING";
public const string Succeeded = "SUCCEEDED";
public const string Failed = "FAILED";
public const string Retrying = "RETRYING";
public const string Blocked = "BLOCKED";
}
@@ -16,12 +16,6 @@ namespace QuantEngine.Web.Services;
/// </summary>
public class SchedulerService
{
private sealed record RecurringJobDefinition(
string JobId,
Expression<Func<Task>> Job,
string Cron,
string Description);
private readonly ILogger<SchedulerService> _logger;
private readonly IBackgroundJobClient _jobClient;
private readonly IRecurringJobManager _recurringJobManager;
@@ -82,12 +76,12 @@ public class SchedulerService
}
}
private IReadOnlyList<RecurringJobDefinition> BuildRecurringJobs() => new[]
public IReadOnlyList<SchedulerJobDefinition> GetRecurringJobDefinitions() => new[]
{
new RecurringJobDefinition("daily-collection", () => RunDailyCollectionAsync(), "0 9 * * *", "Daily data collection"),
new RecurringJobDefinition("hourly-price-update", () => UpdatePricesAsync(), "0 9,11,13,15 * * 1-5", "Hourly price update"),
new RecurringJobDefinition("weekly-report", () => GenerateWeeklyReportAsync(), "0 17 * * 5", "Weekly report generation"),
new RecurringJobDefinition("monthly-optimization", () => RunMonthlyOptimizationAsync(), "0 2 1 * *", "Monthly optimization"),
new SchedulerJobDefinition("daily-collection", "0 9 * * *", "Daily data collection", true),
new SchedulerJobDefinition("hourly-price-update", "0 9,11,13,15 * * 1-5", "Hourly price update", true),
new SchedulerJobDefinition("weekly-report", "0 17 * * 5", "Weekly report generation", true),
new SchedulerJobDefinition("monthly-optimization", "0 2 1 * *", "Monthly optimization", true),
};
private static string? FindGatherTradingDataJson()
@@ -118,11 +112,11 @@ public class SchedulerService
{
_logger.LogInformation("Initializing Hangfire schedules...");
foreach (var job in BuildRecurringJobs())
foreach (var job in GetRecurringJobDefinitions())
{
_recurringJobManager.AddOrUpdate(
job.JobId,
job.Job,
ResolveRecurringJob(job.JobId),
job.Cron,
new RecurringJobOptions { TimeZone = TimeZoneInfo.Local }
);
@@ -279,6 +273,15 @@ public class SchedulerService
return JobStorage.Current.GetConnection().GetJobData(jobId)?.State;
}
private Expression<Func<Task>> ResolveRecurringJob(string jobId) => jobId switch
{
"daily-collection" => () => RunDailyCollectionAsync(),
"hourly-price-update" => () => UpdatePricesAsync(),
"weekly-report" => () => GenerateWeeklyReportAsync(),
"monthly-optimization" => () => RunMonthlyOptimizationAsync(),
_ => throw new InvalidOperationException($"Unknown recurring job id: {jobId}")
};
/// <summary>
/// Cancel scheduled job
/// </summary>