refactor(dotnet): move collection schema init to service
This commit is contained in:
@@ -63,6 +63,11 @@ public interface ICollectionReadRepository
|
|||||||
Task<List<PriceHistorySummaryRecord>> GetPriceHistorySummaryAsync();
|
Task<List<PriceHistorySummaryRecord>> GetPriceHistorySummaryAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ICollectionSchemaInitializer
|
||||||
|
{
|
||||||
|
Task InitializeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Collection run record (maps Python CollectionRun).
|
/// Collection run record (maps Python CollectionRun).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ namespace QuantEngine.Infrastructure.Repositories
|
|||||||
|
|
||||||
public async Task SaveRunAsync(CollectionRunRecord run)
|
public async Task SaveRunAsync(CollectionRunRecord run)
|
||||||
{
|
{
|
||||||
await EnsureTablesAsync();
|
|
||||||
await ExecuteAsync(@"
|
await ExecuteAsync(@"
|
||||||
INSERT INTO quantengine.kis_collection_runs (run_id, status, started_at, finished_at, total_snapshots, total_errors, updated_at)
|
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)
|
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);
|
||||||
|
");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -111,6 +111,7 @@ try
|
|||||||
builder.Services.AddScoped<ICollectionRepository>(sp => sp.GetRequiredService<CollectionRepository>());
|
builder.Services.AddScoped<ICollectionRepository>(sp => sp.GetRequiredService<CollectionRepository>());
|
||||||
builder.Services.AddScoped<ICollectionReadRepository>(sp => sp.GetRequiredService<CollectionRepository>());
|
builder.Services.AddScoped<ICollectionReadRepository>(sp => sp.GetRequiredService<CollectionRepository>());
|
||||||
builder.Services.AddScoped<ICollectionWriteRepository>(sp => sp.GetRequiredService<CollectionRepository>());
|
builder.Services.AddScoped<ICollectionWriteRepository>(sp => sp.GetRequiredService<CollectionRepository>());
|
||||||
|
builder.Services.AddSingleton<ICollectionSchemaInitializer, CollectionSchemaInitializer>();
|
||||||
builder.Services.AddScoped<ICollectionReadModelService, CollectionReadModelService>();
|
builder.Services.AddScoped<ICollectionReadModelService, CollectionReadModelService>();
|
||||||
builder.Services.AddSingleton<IRuntimeAuditTrailService, RuntimeAuditTrailService>();
|
builder.Services.AddSingleton<IRuntimeAuditTrailService, RuntimeAuditTrailService>();
|
||||||
builder.Services.AddScoped<ITokenCache, PostgresTokenCache>();
|
builder.Services.AddScoped<ITokenCache, PostgresTokenCache>();
|
||||||
@@ -151,10 +152,12 @@ try
|
|||||||
var migrator = scope.ServiceProvider.GetRequiredService<DbMigrator>();
|
var migrator = scope.ServiceProvider.GetRequiredService<DbMigrator>();
|
||||||
var workspaceRepo = scope.ServiceProvider.GetRequiredService<IWorkspaceRepository>();
|
var workspaceRepo = scope.ServiceProvider.GetRequiredService<IWorkspaceRepository>();
|
||||||
var collectionRepo = scope.ServiceProvider.GetRequiredService<ICollectionRepository>();
|
var collectionRepo = scope.ServiceProvider.GetRequiredService<ICollectionRepository>();
|
||||||
|
var collectionSchemaInitializer = scope.ServiceProvider.GetRequiredService<ICollectionSchemaInitializer>();
|
||||||
var tokenCache = scope.ServiceProvider.GetRequiredService<ITokenCache>();
|
var tokenCache = scope.ServiceProvider.GetRequiredService<ITokenCache>();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
await collectionSchemaInitializer.InitializeAsync();
|
||||||
migrator.Migrate();
|
migrator.Migrate();
|
||||||
await workspaceRepo.GetAccountsAsync();
|
await workspaceRepo.GetAccountsAsync();
|
||||||
await collectionRepo.GetDashboardStateAsync();
|
await collectionRepo.GetDashboardStateAsync();
|
||||||
|
|||||||
Reference in New Issue
Block a user