save progress

This commit is contained in:
StellaOps Bot
2026-01-03 00:47:24 +02:00
parent 3f197814c5
commit ca578801fd
319 changed files with 32478 additions and 2202 deletions

View File

@@ -61,6 +61,37 @@ public sealed class PostgresBundleVersionStore : RepositoryBase<AirGapDataSource
await using var connection = await DataSource.OpenConnectionAsync(tenantKey, "writer", ct).ConfigureAwait(false);
await using var tx = await connection.BeginTransactionAsync(ct).ConfigureAwait(false);
var current = await GetCurrentForUpdateAsync(
connection,
tx,
versionTable,
tenantKey,
bundleTypeKey,
ct)
.ConfigureAwait(false);
if (current is not null && !record.WasForceActivated)
{
var incomingVersion = new BundleVersion(
record.Major,
record.Minor,
record.Patch,
record.BundleCreatedAt,
record.Prerelease);
var currentVersion = new BundleVersion(
current.Major,
current.Minor,
current.Patch,
current.BundleCreatedAt,
current.Prerelease);
if (!incomingVersion.IsNewerThan(currentVersion))
{
throw new InvalidOperationException(
$"Incoming version '{incomingVersion.SemVer}' is not monotonic vs current '{currentVersion.SemVer}'.");
}
}
var closeHistorySql = $$"""
UPDATE {{historyTable}}
SET deactivated_at = @activated_at
@@ -224,6 +255,31 @@ public sealed class PostgresBundleVersionStore : RepositoryBase<AirGapDataSource
ForceActivateReason: forceActivateReason);
}
private async Task<BundleVersionRecord?> GetCurrentForUpdateAsync(
NpgsqlConnection connection,
NpgsqlTransaction transaction,
string versionTable,
string tenantKey,
string bundleTypeKey,
CancellationToken ct)
{
var sql = $$"""
SELECT tenant_id, bundle_type, version_string, major, minor, patch, prerelease,
bundle_created_at, bundle_digest, activated_at, was_force_activated, force_activate_reason
FROM {{versionTable}}
WHERE tenant_id = @tenant_id AND bundle_type = @bundle_type
FOR UPDATE;
""";
await using var command = CreateCommand(sql, connection);
command.Transaction = transaction;
AddParameter(command, "tenant_id", tenantKey);
AddParameter(command, "bundle_type", bundleTypeKey);
await using var reader = await command.ExecuteReaderAsync(ct).ConfigureAwait(false);
return await reader.ReadAsync(ct).ConfigureAwait(false) ? Map(reader) : null;
}
private async ValueTask EnsureTablesAsync(CancellationToken ct)
{
if (_initialized)