Split the backend into API host, Domain, Application and Infrastructure projects. Add Swagger/OpenAPI per API version, Asp.Versioning (query/header), ProblemDetails with a global exception handler and SurrealQL migrations applied at startup (namespace/database ensured). Infrastructure owns the SurrealDB client, settings and DI.
64 lines
2.0 KiB
C#
64 lines
2.0 KiB
C#
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using SurrealDb.Net;
|
|
using TarninaHub.Application.Abstractions;
|
|
using TarninaHub.Infrastructure.Settings;
|
|
|
|
namespace TarninaHub.Infrastructure.Persistence;
|
|
|
|
public sealed class MigrationRunner : IMigrationRunner
|
|
{
|
|
private readonly ISurrealDbClient _client;
|
|
private readonly SurrealDbSettings _settings;
|
|
private readonly ILogger<MigrationRunner> _logger;
|
|
|
|
public MigrationRunner(
|
|
ISurrealDbClient client,
|
|
IOptions<SurrealDbSettings> settings,
|
|
ILogger<MigrationRunner> logger)
|
|
{
|
|
_client = client;
|
|
_settings = settings.Value;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task ApplyAsync(CancellationToken cancellationToken)
|
|
{
|
|
await EnsureNamespaceAsync(cancellationToken);
|
|
|
|
var migrationsPath = Path.Combine(AppContext.BaseDirectory, _settings.MigrationsDirectory);
|
|
|
|
if (!Directory.Exists(migrationsPath))
|
|
{
|
|
_logger.LogWarning(
|
|
"Migrations directory '{MigrationsPath}' was not found; skipping migrations.",
|
|
migrationsPath);
|
|
|
|
return;
|
|
}
|
|
|
|
var files = Directory.GetFiles(migrationsPath, "*.surql")
|
|
.OrderBy(file => file, StringComparer.Ordinal);
|
|
|
|
foreach (var file in files)
|
|
{
|
|
var sql = await File.ReadAllTextAsync(file, cancellationToken);
|
|
|
|
await _client.RawQuery(sql, cancellationToken: cancellationToken);
|
|
|
|
_logger.LogInformation("Applied migration {Migration}.", Path.GetFileName(file));
|
|
}
|
|
}
|
|
|
|
private async Task EnsureNamespaceAsync(CancellationToken cancellationToken)
|
|
{
|
|
var sql =
|
|
$"DEFINE NAMESPACE IF NOT EXISTS {_settings.Namespace}; " +
|
|
$"USE NS {_settings.Namespace}; " +
|
|
$"DEFINE DATABASE IF NOT EXISTS {_settings.Database}; " +
|
|
$"USE DB {_settings.Database};";
|
|
|
|
await _client.RawQuery(sql, cancellationToken: cancellationToken);
|
|
}
|
|
}
|