Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bd07876a41 |
@@ -977,105 +977,61 @@ public static class StartupInitializationExtensions
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
if (!MySqlIndexExists(conn, "Companies", "IX_Companies_OwnerUserId"))
|
||||
// Schema reconciliation must never crash app startup: an index that fails
|
||||
// (e.g. combined key exceeds MySQL's 3072-byte limit because an older
|
||||
// migration made OwnerUserId wider than the varchar(255) this reconciler
|
||||
// assumes) is logged and skipped rather than taking prod down. OwnerUserId
|
||||
// is prefix-indexed at 191 chars (safe under utf8mb4's 767-byte legacy
|
||||
// per-column key limit, and far longer than the GUID-like Identity ids
|
||||
// actually stored there) so composite indexes stay well under the cap
|
||||
// regardless of the column's declared width.
|
||||
void TryCreateIndex(string table, string indexName, string columnsSql)
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "CREATE INDEX `IX_Companies_OwnerUserId` ON `Companies` (`OwnerUserId`);";
|
||||
cmd.ExecuteNonQuery();
|
||||
if (MySqlIndexExists(conn, table, indexName)) return;
|
||||
try
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = $"CREATE INDEX `{indexName}` ON `{table}` ({columnsSql});";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
app.Logger.LogWarning(ex, "Skipping index {Index} on {Table} during startup reconciliation.", indexName, table);
|
||||
}
|
||||
}
|
||||
|
||||
if (!MySqlIndexExists(conn, "JobApplications", "IX_JobApplications_OwnerUserId"))
|
||||
void TryCreateUniqueIndex(string table, string indexName, string columnsSql)
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "CREATE INDEX `IX_JobApplications_OwnerUserId` ON `JobApplications` (`OwnerUserId`);";
|
||||
cmd.ExecuteNonQuery();
|
||||
if (MySqlIndexExists(conn, table, indexName)) return;
|
||||
try
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = $"CREATE UNIQUE INDEX `{indexName}` ON `{table}` ({columnsSql});";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
app.Logger.LogWarning(ex, "Skipping unique index {Index} on {Table} during startup reconciliation.", indexName, table);
|
||||
}
|
||||
}
|
||||
|
||||
TryCreateIndex("Companies", "IX_Companies_OwnerUserId", "`OwnerUserId`(191)");
|
||||
TryCreateIndex("JobApplications", "IX_JobApplications_OwnerUserId", "`OwnerUserId`(191)");
|
||||
|
||||
// Hot-path composite indexes for tenant-scoped list/board/stats/analytics
|
||||
// (OwnerUserId + IsDeleted) and reminders (OwnerUserId + FollowUpAt).
|
||||
if (!MySqlIndexExists(conn, "JobApplications", "IX_JobApplications_OwnerUserId_IsDeleted"))
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "CREATE INDEX `IX_JobApplications_OwnerUserId_IsDeleted` ON `JobApplications` (`OwnerUserId`, `IsDeleted`);";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
if (!MySqlIndexExists(conn, "JobApplications", "IX_JobApplications_OwnerUserId_FollowUpAt"))
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "CREATE INDEX `IX_JobApplications_OwnerUserId_FollowUpAt` ON `JobApplications` (`OwnerUserId`, `FollowUpAt`);";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
if (!MySqlIndexExists(conn, "CvUploadArtifacts", "IX_CvUploadArtifacts_OwnerUserId_UploadedAtUtc"))
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "CREATE INDEX `IX_CvUploadArtifacts_OwnerUserId_UploadedAtUtc` ON `CvUploadArtifacts` (`OwnerUserId`, `UploadedAtUtc`);";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
if (!MySqlIndexExists(conn, "CvExtractionRuns", "IX_CvExtractionRuns_OwnerUserId_StartedAtUtc"))
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "CREATE INDEX `IX_CvExtractionRuns_OwnerUserId_StartedAtUtc` ON `CvExtractionRuns` (`OwnerUserId`, `StartedAtUtc`);";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
if (!MySqlIndexExists(conn, "CvExtractionRuns", "IX_CvExtractionRuns_ArtifactId"))
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "CREATE INDEX `IX_CvExtractionRuns_ArtifactId` ON `CvExtractionRuns` (`ArtifactId`);";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
if (!MySqlIndexExists(conn, "GmailConnections", "IX_GmailConnections_OwnerUserId"))
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "CREATE INDEX `IX_GmailConnections_OwnerUserId` ON `GmailConnections` (`OwnerUserId`);";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
if (!MySqlIndexExists(conn, "GmailConnections", "IX_GmailConnections_OwnerUserId_GmailAddress"))
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "CREATE UNIQUE INDEX `IX_GmailConnections_OwnerUserId_GmailAddress` ON `GmailConnections` (`OwnerUserId`, `GmailAddress`);";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
if (!MySqlIndexExists(conn, "MicrosoftGraphConnections", "IX_MicrosoftGraphConnections_OwnerUserId"))
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "CREATE INDEX `IX_MicrosoftGraphConnections_OwnerUserId` ON `MicrosoftGraphConnections` (`OwnerUserId`);";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
if (!MySqlIndexExists(conn, "MicrosoftGraphConnections", "IX_MicrosoftGraphConnections_OwnerUserId_MailAddress"))
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "CREATE UNIQUE INDEX `IX_MicrosoftGraphConnections_OwnerUserId_MailAddress` ON `MicrosoftGraphConnections` (`OwnerUserId`, `MailAddress`);";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
if (!MySqlIndexExists(conn, "ImapConnections", "IX_ImapConnections_OwnerUserId"))
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "CREATE UNIQUE INDEX `IX_ImapConnections_OwnerUserId` ON `ImapConnections` (`OwnerUserId`);";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
if (!MySqlIndexExists(conn, "TailoredCvDrafts", "IX_TailoredCvDrafts_OwnerUserId_JobApplicationId"))
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "CREATE UNIQUE INDEX `IX_TailoredCvDrafts_OwnerUserId_JobApplicationId` ON `TailoredCvDrafts` (`OwnerUserId`, `JobApplicationId`);";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
if (!MySqlIndexExists(conn, "TailoredCvDrafts", "IX_TailoredCvDrafts_JobApplicationId"))
|
||||
{
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "CREATE INDEX `IX_TailoredCvDrafts_JobApplicationId` ON `TailoredCvDrafts` (`JobApplicationId`);";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
TryCreateIndex("JobApplications", "IX_JobApplications_OwnerUserId_IsDeleted", "`OwnerUserId`(191), `IsDeleted`");
|
||||
TryCreateIndex("JobApplications", "IX_JobApplications_OwnerUserId_FollowUpAt", "`OwnerUserId`(191), `FollowUpAt`");
|
||||
TryCreateIndex("CvUploadArtifacts", "IX_CvUploadArtifacts_OwnerUserId_UploadedAtUtc", "`OwnerUserId`(191), `UploadedAtUtc`");
|
||||
TryCreateIndex("CvExtractionRuns", "IX_CvExtractionRuns_OwnerUserId_StartedAtUtc", "`OwnerUserId`(191), `StartedAtUtc`");
|
||||
TryCreateIndex("CvExtractionRuns", "IX_CvExtractionRuns_ArtifactId", "`ArtifactId`");
|
||||
TryCreateIndex("GmailConnections", "IX_GmailConnections_OwnerUserId", "`OwnerUserId`(191)");
|
||||
TryCreateUniqueIndex("GmailConnections", "IX_GmailConnections_OwnerUserId_GmailAddress", "`OwnerUserId`(191), `GmailAddress`(191)");
|
||||
TryCreateIndex("MicrosoftGraphConnections", "IX_MicrosoftGraphConnections_OwnerUserId", "`OwnerUserId`(191)");
|
||||
TryCreateUniqueIndex("MicrosoftGraphConnections", "IX_MicrosoftGraphConnections_OwnerUserId_MailAddress", "`OwnerUserId`(191), `MailAddress`(191)");
|
||||
TryCreateUniqueIndex("ImapConnections", "IX_ImapConnections_OwnerUserId", "`OwnerUserId`(191)");
|
||||
TryCreateUniqueIndex("TailoredCvDrafts", "IX_TailoredCvDrafts_OwnerUserId_JobApplicationId", "`OwnerUserId`(191), `JobApplicationId`");
|
||||
TryCreateIndex("TailoredCvDrafts", "IX_TailoredCvDrafts_JobApplicationId", "`JobApplicationId`");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user