refactor(dotnet): materialize scheduler report artifacts
This commit is contained in:
@@ -109,6 +109,46 @@ public class SchedulerServiceTests
|
|||||||
Assert.Contains("\"State\":\"SUCCEEDED\"", lines[0]);
|
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]
|
[Fact]
|
||||||
public void LoadTickersFromJson_WhenFileMissing_FallsBackToDefaultUniverse()
|
public void LoadTickersFromJson_WhenFileMissing_FallsBackToDefaultUniverse()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -94,6 +94,16 @@ public class SchedulerService
|
|||||||
await ExecuteWithAuditAsync(jobId, async () => { await action(); return true; }, resourceKey: resourceKey);
|
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()
|
private List<string> LoadTickersFromJson()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -261,8 +271,19 @@ public class SchedulerService
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Fetching price for ticker: {Ticker}", ticker);
|
_logger.LogInformation("Fetching price for ticker: {Ticker}", ticker);
|
||||||
// TODO: Implement actual price fetching
|
var normalizedTicker = ticker?.Trim();
|
||||||
await Task.Delay(50);
|
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);
|
_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));
|
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);
|
_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"));
|
AppendAudit(new SchedulerJobExecutionAudit("weekly-report", $"weekly-{DateTime.UtcNow:yyyyMMddHHmmssfff}", SchedulerStates.Pending, null, DateTimeOffset.UtcNow, null, "report"));
|
||||||
|
|
||||||
// TODO: Implement report generation logic
|
var reportRoot = GetReportRoot();
|
||||||
await Task.Delay(500);
|
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");
|
_logger.LogInformation("Weekly report generated successfully");
|
||||||
AppendAudit(new SchedulerJobExecutionAudit("weekly-report", $"weekly-{DateTime.UtcNow:yyyyMMddHHmmssfff}", SchedulerStates.Succeeded, null, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow, "report"));
|
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);
|
_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"));
|
AppendAudit(new SchedulerJobExecutionAudit("monthly-optimization", $"monthly-{DateTime.UtcNow:yyyyMMddHHmmssfff}", SchedulerStates.Pending, null, DateTimeOffset.UtcNow, null, "optimization"));
|
||||||
|
|
||||||
// TODO: Implement optimization logic
|
var reportRoot = GetReportRoot();
|
||||||
await Task.Delay(1000);
|
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");
|
_logger.LogInformation("Monthly optimization completed");
|
||||||
AppendAudit(new SchedulerJobExecutionAudit("monthly-optimization", $"monthly-{DateTime.UtcNow:yyyyMMddHHmmssfff}", SchedulerStates.Succeeded, null, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow, "optimization"));
|
AppendAudit(new SchedulerJobExecutionAudit("monthly-optimization", $"monthly-{DateTime.UtcNow:yyyyMMddHHmmssfff}", SchedulerStates.Succeeded, null, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow, "optimization"));
|
||||||
|
|||||||
Reference in New Issue
Block a user