refactor(dotnet): move collection schema init to service
Validators (Pushes and Pull Requests) / validate-ui-and-storage (push) Successful in 18s
Validators (Pushes and Pull Requests) / validate-core (push) Failing after 1m49s

This commit is contained in:
2026-07-13 01:06:02 +09:00
parent c2cd643729
commit ae32f86685
4 changed files with 65 additions and 41 deletions
@@ -63,6 +63,11 @@ public interface ICollectionReadRepository
Task<List<PriceHistorySummaryRecord>> GetPriceHistorySummaryAsync();
}
public interface ICollectionSchemaInitializer
{
Task InitializeAsync();
}
/// <summary>
/// Collection run record (maps Python CollectionRun).
/// </summary>
@@ -37,7 +37,6 @@ namespace QuantEngine.Infrastructure.Repositories
public async Task SaveRunAsync(CollectionRunRecord run)
{
await EnsureTablesAsync();
await ExecuteAsync(@"
INSERT INTO quantengine.kis_collection_runs (run_id, status, started_at, finished_at, total_snapshots, total_errors, updated_at)
VALUES (@RunId, @Status, @StartedAt, @FinishedAt, @TotalSnapshots, @TotalErrors, @UpdatedAt)
@@ -198,45 +197,5 @@ namespace QuantEngine.Infrastructure.Repositories
);
}
private async Task EnsureTablesAsync()
{
await ExecuteAsync(@"
CREATE TABLE IF NOT EXISTS quantengine.kis_collection_runs (
run_id TEXT PRIMARY KEY,
status TEXT NOT NULL,
started_at TEXT NOT NULL,
finished_at TEXT,
total_snapshots INTEGER,
total_errors INTEGER,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS quantengine.kis_collection_snapshots (
run_id TEXT NOT NULL,
dataset_name TEXT,
ticker TEXT NOT NULL,
source_name TEXT NOT NULL,
payload_json TEXT NOT NULL,
captured_at TEXT NOT NULL,
created_at TEXT NOT NULL,
PRIMARY KEY (run_id, ticker, source_name)
);
CREATE TABLE IF NOT EXISTS quantengine.kis_collection_errors (
id SERIAL PRIMARY KEY,
run_id TEXT NOT NULL,
source_name TEXT NOT NULL,
error_kind TEXT NOT NULL,
error_message TEXT,
ticker TEXT,
created_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_kis_runs_started_at ON quantengine.kis_collection_runs(started_at DESC);
CREATE INDEX IF NOT EXISTS idx_kis_snapshots_ticker ON quantengine.kis_collection_snapshots(ticker);
CREATE INDEX IF NOT EXISTS idx_kis_snapshots_captured_at ON quantengine.kis_collection_snapshots(captured_at DESC);
CREATE INDEX IF NOT EXISTS idx_kis_errors_run_id ON quantengine.kis_collection_errors(run_id);
");
}
}
}
@@ -0,0 +1,57 @@
using Dapper;
using QuantEngine.Core.Interfaces;
using QuantEngine.Infrastructure.Data;
namespace QuantEngine.Infrastructure.Repositories;
public sealed class CollectionSchemaInitializer : ICollectionSchemaInitializer
{
private readonly IDbConnectionFactory _connectionFactory;
public CollectionSchemaInitializer(IDbConnectionFactory connectionFactory)
{
_connectionFactory = connectionFactory;
}
public async Task InitializeAsync()
{
using var conn = _connectionFactory.CreateConnection();
await conn.ExecuteAsync(@"
CREATE TABLE IF NOT EXISTS quantengine.kis_collection_runs (
run_id TEXT PRIMARY KEY,
status TEXT NOT NULL,
started_at TEXT NOT NULL,
finished_at TEXT,
total_snapshots INTEGER,
total_errors INTEGER,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS quantengine.kis_collection_snapshots (
run_id TEXT NOT NULL,
dataset_name TEXT,
ticker TEXT NOT NULL,
source_name TEXT NOT NULL,
payload_json TEXT NOT NULL,
captured_at TEXT NOT NULL,
created_at TEXT NOT NULL,
PRIMARY KEY (run_id, ticker, source_name)
);
CREATE TABLE IF NOT EXISTS quantengine.kis_collection_errors (
id SERIAL PRIMARY KEY,
run_id TEXT NOT NULL,
source_name TEXT NOT NULL,
error_kind TEXT NOT NULL,
error_message TEXT,
ticker TEXT,
created_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_kis_runs_started_at ON quantengine.kis_collection_runs(started_at DESC);
CREATE INDEX IF NOT EXISTS idx_kis_snapshots_ticker ON quantengine.kis_collection_snapshots(ticker);
CREATE INDEX IF NOT EXISTS idx_kis_snapshots_captured_at ON quantengine.kis_collection_snapshots(captured_at DESC);
CREATE INDEX IF NOT EXISTS idx_kis_errors_run_id ON quantengine.kis_collection_errors(run_id);
");
}
}
+3
View File
@@ -111,6 +111,7 @@ try
builder.Services.AddScoped<ICollectionRepository>(sp => sp.GetRequiredService<CollectionRepository>());
builder.Services.AddScoped<ICollectionReadRepository>(sp => sp.GetRequiredService<CollectionRepository>());
builder.Services.AddScoped<ICollectionWriteRepository>(sp => sp.GetRequiredService<CollectionRepository>());
builder.Services.AddSingleton<ICollectionSchemaInitializer, CollectionSchemaInitializer>();
builder.Services.AddScoped<ICollectionReadModelService, CollectionReadModelService>();
builder.Services.AddSingleton<IRuntimeAuditTrailService, RuntimeAuditTrailService>();
builder.Services.AddScoped<ITokenCache, PostgresTokenCache>();
@@ -151,10 +152,12 @@ try
var migrator = scope.ServiceProvider.GetRequiredService<DbMigrator>();
var workspaceRepo = scope.ServiceProvider.GetRequiredService<IWorkspaceRepository>();
var collectionRepo = scope.ServiceProvider.GetRequiredService<ICollectionRepository>();
var collectionSchemaInitializer = scope.ServiceProvider.GetRequiredService<ICollectionSchemaInitializer>();
var tokenCache = scope.ServiceProvider.GetRequiredService<ITokenCache>();
try
{
await collectionSchemaInitializer.InitializeAsync();
migrator.Migrate();
await workspaceRepo.GetAccountsAsync();
await collectionRepo.GetDashboardStateAsync();