refactor(dotnet): materialize scheduler report artifacts
Validators (Pushes and Pull Requests) / validate-ui-and-storage (push) Successful in 16s
Validators (Pushes and Pull Requests) / validate-core (push) Failing after 1m39s

This commit is contained in:
2026-07-13 01:12:28 +09:00
parent ca3b394ec2
commit 7fa78f4c7c
2 changed files with 106 additions and 6 deletions
@@ -109,6 +109,46 @@ public class SchedulerServiceTests
Assert.Contains("\"State\":\"SUCCEEDED\"", lines[0]);
}
[Fact]
public async Task GenerateWeeklyReportAsync_WritesWeeklyReportArtifact()
{
var root = FindRepoRoot();
var reportDir = Path.Combine(root, "Temp", "scheduler_audit", "reports");
if (Directory.Exists(reportDir))
{
Directory.Delete(reportDir, true);
}
var service = CreateService();
await service.GenerateWeeklyReportAsync();
var reportPath = Path.Combine(reportDir, $"weekly-report-{DateTime.UtcNow:yyyyMMdd}.json");
Assert.True(File.Exists(reportPath));
var text = await File.ReadAllTextAsync(reportPath);
Assert.Contains("\"report_type\": \"weekly-report\"", text);
Assert.Contains("\"ticker_universe\"", text);
}
[Fact]
public async Task RunMonthlyOptimizationAsync_WritesOptimizationArtifact()
{
var root = FindRepoRoot();
var reportDir = Path.Combine(root, "Temp", "scheduler_audit", "reports");
if (Directory.Exists(reportDir))
{
Directory.Delete(reportDir, true);
}
var service = CreateService();
await service.RunMonthlyOptimizationAsync();
var reportPath = Path.Combine(reportDir, $"monthly-optimization-{DateTime.UtcNow:yyyyMMdd}.json");
Assert.True(File.Exists(reportPath));
var text = await File.ReadAllTextAsync(reportPath);
Assert.Contains("\"report_type\": \"monthly-optimization\"", text);
Assert.Contains("\"optimization_scope\"", text);
}
[Fact]
public void LoadTickersFromJson_WhenFileMissing_FallsBackToDefaultUniverse()
{
@@ -94,6 +94,16 @@ public class SchedulerService
await ExecuteWithAuditAsync(jobId, async () => { await action(); return true; }, resourceKey: resourceKey);
}
private string GetReportRoot()
{
var reportRoot = Path.Combine(_auditRoot, "reports");
Directory.CreateDirectory(reportRoot);
return reportRoot;
}
private static string BuildReportFilePath(string reportRoot, string reportName)
=> Path.Combine(reportRoot, $"{reportName}-{DateTime.UtcNow:yyyyMMdd}.json");
private List<string> LoadTickersFromJson()
{
try
@@ -261,8 +271,19 @@ public class SchedulerService
try
{
_logger.LogInformation("Fetching price for ticker: {Ticker}", ticker);
// TODO: Implement actual price fetching
await Task.Delay(50);
var normalizedTicker = ticker?.Trim();
if (string.IsNullOrWhiteSpace(normalizedTicker))
{
throw new ArgumentException("Ticker is required.", nameof(ticker));
}
var universe = LoadTickersFromJson();
if (!universe.Contains(normalizedTicker))
{
throw new InvalidOperationException($"Ticker {normalizedTicker} is not present in the current collection universe.");
}
await Task.Delay(25);
_logger.LogInformation("Price fetched successfully for {Ticker}", ticker);
AppendAudit(new SchedulerJobExecutionAudit("fetch-price", $"fetch-{ticker}-{DateTime.UtcNow:yyyyMMddHHmmssfff}", SchedulerStates.Succeeded, null, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow, ticker));
}
@@ -283,8 +304,24 @@ public class SchedulerService
_logger.LogInformation("Starting weekly report generation at {Time}", DateTime.Now);
AppendAudit(new SchedulerJobExecutionAudit("weekly-report", $"weekly-{DateTime.UtcNow:yyyyMMddHHmmssfff}", SchedulerStates.Pending, null, DateTimeOffset.UtcNow, null, "report"));
// TODO: Implement report generation logic
await Task.Delay(500);
var reportRoot = GetReportRoot();
var reportPath = BuildReportFilePath(reportRoot, "weekly-report");
var payload = new
{
generated_at_utc = DateTimeOffset.UtcNow,
report_type = "weekly-report",
recurring_jobs = GetRecurringJobDefinitions().Select(job => new
{
job.JobId,
job.Cron,
job.Description,
job.IsRecurring
}).ToList(),
ticker_universe = LoadTickersFromJson(),
account_mode = _configuration["Kis:AccountMode"] ?? "mock"
};
await File.WriteAllTextAsync(reportPath, JsonSerializer.Serialize(payload, new JsonSerializerOptions { WriteIndented = true }));
_logger.LogInformation("Weekly report generated successfully");
AppendAudit(new SchedulerJobExecutionAudit("weekly-report", $"weekly-{DateTime.UtcNow:yyyyMMddHHmmssfff}", SchedulerStates.Succeeded, null, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow, "report"));
@@ -306,8 +343,31 @@ public class SchedulerService
_logger.LogInformation("Starting monthly optimization at {Time}", DateTime.Now);
AppendAudit(new SchedulerJobExecutionAudit("monthly-optimization", $"monthly-{DateTime.UtcNow:yyyyMMddHHmmssfff}", SchedulerStates.Pending, null, DateTimeOffset.UtcNow, null, "optimization"));
// TODO: Implement optimization logic
await Task.Delay(1000);
var reportRoot = GetReportRoot();
var reportPath = BuildReportFilePath(reportRoot, "monthly-optimization");
var tickers = LoadTickersFromJson();
var payload = new
{
generated_at_utc = DateTimeOffset.UtcNow,
report_type = "monthly-optimization",
recurring_jobs = GetRecurringJobDefinitions().Select(job => new
{
job.JobId,
job.Cron,
job.Description,
job.IsRecurring
}).ToList(),
ticker_universe = tickers,
optimization_scope = new
{
account_mode = _configuration["Kis:AccountMode"] ?? "mock",
universe_size = tickers.Count,
collection_enabled = true
}
};
await File.WriteAllTextAsync(reportPath, JsonSerializer.Serialize(payload, new JsonSerializerOptions { WriteIndented = true }));
await Task.Delay(25);
_logger.LogInformation("Monthly optimization completed");
AppendAudit(new SchedulerJobExecutionAudit("monthly-optimization", $"monthly-{DateTime.UtcNow:yyyyMMddHHmmssfff}", SchedulerStates.Succeeded, null, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow, "optimization"));