fix(storage): repair provider account creator type

This commit is contained in:
joshpatra committed 2026-08-20 13:17:08 -04:00
1 parent 073705ce72
commit 86ebf700bb
2 files changed
+135

No files matched your search

@@ -704,6 +704,85 @@ public sealed class PostgresStorageIntegrationTests
Assert.Equal(2, (await restarted.RecommendationCandidates.SingleAsync(item => item.Id == candidate)).Revision);
}
[Fact]
[Trait("Category", "Postgres")]
[Trait("Lane", "ReleaseCritical")]
public async Task ProviderAccountCreatorRepair_ConvertsLegacyTextColumnAndPreservesCreator()
{
const string previous = "20260804080000_BackfillV3CompatibilityState";
const string current = "20260820173000_RepairProviderAccountCreatorIdentity";
await using var database = await PostgresTestDatabase.CreateAsync(useTemplate: false);
await using var context = new AllstarrDbContext(database.Options);
var migrator = context.GetService<IMigrator>();
await migrator.MigrateAsync(previous);
var now = DateTimeOffset.UtcNow;
var tenantId = Guid.CreateVersion7();
var userId = Guid.CreateVersion7();
var accountId = Guid.CreateVersion7();
context.Tenants.Add(new TenantRecord
{
Id = tenantId,
Slug = "provider-creator-repair",
Name = "Provider creator repair",
CreatedAt = now
});
context.Users.Add(new PlatformUserRecord
{
Id = userId,
TenantId = tenantId,
DisplayName = "Creator",
Status = PlatformUserStatus.Active,
CreatedAt = now,
UpdatedAt = now
});
context.ProviderAccounts.Add(new ProviderAccountRecord
{
Id = accountId,
TenantId = tenantId,
OwnerUserId = userId,
CreatedByUserId = userId,
ProviderId = "audiomuse-ai",
DisplayName = "AudioMuse",
Scope = ProviderAccountScope.User,
Enabled = false,
CreatedAt = now,
UpdatedAt = now
});
await context.SaveChangesAsync();
await context.Database.ExecuteSqlRawAsync("""
ALTER TABLE provider_accounts DROP CONSTRAINT IF EXISTS "FK_provider_account_creator";
DROP INDEX IF EXISTS "IX_provider_accounts_CreatedByUserId";
ALTER TABLE provider_accounts
ALTER COLUMN "CreatedByUserId" TYPE text
USING "CreatedByUserId"::text;
""");
Assert.Equal("text", await ColumnType(context, "provider_accounts", "CreatedByUserId"));
await migrator.MigrateAsync(current);
context.ChangeTracker.Clear();
Assert.Equal("uuid", await ColumnType(context, "provider_accounts", "CreatedByUserId"));
Assert.Equal(userId, (await context.ProviderAccounts.AsNoTracking()
.SingleAsync(item => item.Id == accountId)).CreatedByUserId);
await using (var command = context.Database.GetDbConnection().CreateCommand())
{
command.CommandText = "SELECT count(*) FROM pg_constraint " +
"WHERE conrelid = 'provider_accounts'::regclass " +
"AND conname = 'FK_provider_account_creator'";
Assert.Equal(1L, Convert.ToInt64(await command.ExecuteScalarAsync()));
command.CommandText = "SELECT count(*) FROM pg_indexes " +
"WHERE schemaname = 'public' AND tablename = 'provider_accounts' " +
"AND indexname = 'IX_provider_accounts_CreatedByUserId'";
Assert.Equal(1L, Convert.ToInt64(await command.ExecuteScalarAsync()));
}
await migrator.MigrateAsync(previous);
await migrator.MigrateAsync(current);
Assert.Equal("uuid", await ColumnType(context, "provider_accounts", "CreatedByUserId"));
}
[Fact]
[Trait("Category", "Postgres")]
[Trait("Lane", "ReleaseCritical")]
@@ -0,0 +1,56 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace allstarr.Core.Storage.Migrations;
[DbContext(typeof(AllstarrDbContext))]
[Migration("20260820173000_RepairProviderAccountCreatorIdentity")]
public sealed class RepairProviderAccountCreatorIdentity : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("""
DO $repair$
BEGIN
IF EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'provider_accounts'
AND column_name = 'CreatedByUserId'
AND data_type = 'text') THEN
ALTER TABLE provider_accounts
ALTER COLUMN "CreatedByUserId" TYPE uuid
USING "CreatedByUserId"::uuid;
END IF;
END
$repair$;
CREATE INDEX IF NOT EXISTS "IX_provider_accounts_CreatedByUserId"
ON provider_accounts ("CreatedByUserId");
DO $repair$
BEGIN
IF NOT EXISTS (
SELECT 1
FROM pg_constraint
WHERE conrelid = 'provider_accounts'::regclass
AND conname = 'FK_provider_account_creator') THEN
ALTER TABLE provider_accounts
ADD CONSTRAINT "FK_provider_account_creator"
FOREIGN KEY ("CreatedByUserId") REFERENCES users ("Id")
ON DELETE SET NULL;
END IF;
END
$repair$;
""");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
// The repaired UUID shape is the model expected by every supported build. Keeping it
// also makes rollback and reapplication safe for databases that never had the drift.
}
}