From 72baf49486f181f03f1b7fb211b7025f633eac7a Mon Sep 17 00:00:00 2001 From: Thomas Luizon Rodrigues Gregorio Date: Sun, 12 Jul 2026 13:11:02 -0300 Subject: [PATCH] fix(api): make AddUserHandleUniqueIndex idempotent to unblock prod deploy (#243) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The IX_Users_Handle_Lower unique functional index was ALREADY created by AddSocialFoundation (2026-06-27). #338's new migration re-issued a bare CREATE UNIQUE INDEX, so every prod deploy since crashed at startup with Npgsql 42P07 "relation IX_Users_Handle_Lower already exists" — EF kept re-running the never-recorded migration. CI missed it because the unit suite doesn't run raw-SQL migrations against real Postgres. Add IF NOT EXISTS so the migration is a safe no-op on the existing DB (and still correct on a fresh one), applies cleanly, records itself, and the deploy pipeline recovers. No behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../Migrations/20260712120428_AddUserHandleUniqueIndex.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Orbit.Infrastructure/Migrations/20260712120428_AddUserHandleUniqueIndex.cs b/src/Orbit.Infrastructure/Migrations/20260712120428_AddUserHandleUniqueIndex.cs index 39c3a9484..4cf865244 100644 --- a/src/Orbit.Infrastructure/Migrations/20260712120428_AddUserHandleUniqueIndex.cs +++ b/src/Orbit.Infrastructure/Migrations/20260712120428_AddUserHandleUniqueIndex.cs @@ -25,9 +25,9 @@ PARTITION BY LOWER(""Handle"") FROM ranked WHERE u.""Id"" = ranked.""Id"" AND ranked.rn > 1;"); - // Handles are compared case-insensitively app-wide (LOWER(Handle) == normalized), so a plain unique index would let 'Bob'/'bob' coexist and skip the lookup; Npgsql has no fluent functional-index API, so it lives in SQL. https://github.com/thomasluizon/orbit-ui-mobile/issues/243 + // Idempotent: an identical IX_Users_Handle_Lower was already created by AddSocialFoundation, so a bare CREATE crashes prod migration with 42P07 (relation already exists) while tests — which never run raw-SQL migrations against real Postgres — pass. IF NOT EXISTS makes this a safe no-op on existing DBs and still correct on a fresh one. https://github.com/thomasluizon/orbit-ui-mobile/issues/243 migrationBuilder.Sql(@" - CREATE UNIQUE INDEX ""IX_Users_Handle_Lower"" + CREATE UNIQUE INDEX IF NOT EXISTS ""IX_Users_Handle_Lower"" ON ""Users"" (LOWER(""Handle"")) WHERE ""Handle"" IS NOT NULL;"); }