Add canonical CV artifact pipeline

This commit is contained in:
2026-03-28 23:32:54 +01:00
parent d8ab312f59
commit 107c181506
10 changed files with 619 additions and 82 deletions
+121
View File
@@ -351,6 +351,10 @@ CREATE TABLE IF NOT EXISTS `AspNetUsers` (
`LastName` longtext NULL,
`DisplayName` longtext NULL,
`ProfileCvText` longtext NULL,
`ProfileCvStructureJson` longtext NULL,
`CurrentCvUploadArtifactId` int NULL,
`CurrentCvExtractionRunId` int NULL,
`CurrentCvProfileVersion` int NULL,
`AvatarImageDataUrl` longtext NULL,
`GoogleSubject` longtext NULL,
`GoogleEmail` longtext NULL,
@@ -504,6 +508,10 @@ CREATE TABLE IF NOT EXISTS "AspNetUsers" (
"LastName" TEXT NULL,
"DisplayName" TEXT NULL,
"ProfileCvText" TEXT NULL,
"ProfileCvStructureJson" TEXT NULL,
"CurrentCvUploadArtifactId" INTEGER NULL,
"CurrentCvExtractionRunId" INTEGER NULL,
"CurrentCvProfileVersion" INTEGER NULL,
"AvatarImageDataUrl" TEXT NULL,
"GoogleSubject" TEXT NULL,
"GoogleEmail" TEXT NULL,
@@ -578,6 +586,9 @@ CREATE TABLE IF NOT EXISTS "AspNetUserTokens" (
EnsureColumn(conn, "AspNetUsers", "DisplayName", "ALTER TABLE AspNetUsers ADD COLUMN DisplayName TEXT NULL;");
EnsureColumn(conn, "AspNetUsers", "ProfileCvText", "ALTER TABLE AspNetUsers ADD COLUMN ProfileCvText TEXT NULL;");
EnsureColumn(conn, "AspNetUsers", "ProfileCvStructureJson", "ALTER TABLE AspNetUsers ADD COLUMN ProfileCvStructureJson TEXT NULL;");
EnsureColumn(conn, "AspNetUsers", "CurrentCvUploadArtifactId", "ALTER TABLE AspNetUsers ADD COLUMN CurrentCvUploadArtifactId INTEGER NULL;");
EnsureColumn(conn, "AspNetUsers", "CurrentCvExtractionRunId", "ALTER TABLE AspNetUsers ADD COLUMN CurrentCvExtractionRunId INTEGER NULL;");
EnsureColumn(conn, "AspNetUsers", "CurrentCvProfileVersion", "ALTER TABLE AspNetUsers ADD COLUMN CurrentCvProfileVersion INTEGER NULL;");
EnsureColumn(conn, "AspNetUsers", "AvatarImageDataUrl", "ALTER TABLE AspNetUsers ADD COLUMN AvatarImageDataUrl TEXT NULL;");
EnsureColumn(conn, "AspNetUsers", "GoogleSubject", "ALTER TABLE AspNetUsers ADD COLUMN GoogleSubject TEXT NULL;");
EnsureColumn(conn, "AspNetUsers", "GoogleEmail", "ALTER TABLE AspNetUsers ADD COLUMN GoogleEmail TEXT NULL;");
@@ -622,7 +633,50 @@ CREATE TABLE IF NOT EXISTS "GmailConnections" (
Exec(c, """CREATE UNIQUE INDEX IF NOT EXISTS "IX_GmailConnections_OwnerUserId_GmailAddress" ON "GmailConnections" ("OwnerUserId", "GmailAddress");""");
}
static void EnsureCvTables(DbConnection c)
{
Exec(c, """
CREATE TABLE IF NOT EXISTS "CvUploadArtifacts" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_CvUploadArtifacts" PRIMARY KEY AUTOINCREMENT,
"OwnerUserId" TEXT NOT NULL,
"OriginalFileName" TEXT NOT NULL,
"StoredFileName" TEXT NOT NULL,
"MimeType" TEXT NOT NULL,
"ByteSize" INTEGER NOT NULL,
"Sha256" TEXT NOT NULL,
"StoragePath" TEXT NOT NULL,
"UploadedAtUtc" TEXT NOT NULL
);
""");
Exec(c, """
CREATE TABLE IF NOT EXISTS "CvExtractionRuns" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_CvExtractionRuns" PRIMARY KEY AUTOINCREMENT,
"OwnerUserId" TEXT NOT NULL,
"ArtifactId" INTEGER NULL,
"Trigger" TEXT NOT NULL,
"ParserVersion" TEXT NOT NULL,
"NormalizerVersion" TEXT NOT NULL,
"LlmPromptVersion" TEXT NOT NULL,
"Status" TEXT NOT NULL,
"RawExtractedText" TEXT NULL,
"NormalizedText" TEXT NULL,
"StructuredProfileJson" TEXT NULL,
"ErrorMessage" TEXT NULL,
"StartedAtUtc" TEXT NOT NULL,
"CompletedAtUtc" TEXT NULL,
"AppliedAtUtc" TEXT NULL,
CONSTRAINT "FK_CvExtractionRuns_CvUploadArtifacts_ArtifactId" FOREIGN KEY ("ArtifactId") REFERENCES "CvUploadArtifacts" ("Id") ON DELETE SET NULL
);
""");
Exec(c, """CREATE INDEX IF NOT EXISTS "IX_CvUploadArtifacts_OwnerUserId_UploadedAtUtc" ON "CvUploadArtifacts" ("OwnerUserId", "UploadedAtUtc");""");
Exec(c, """CREATE INDEX IF NOT EXISTS "IX_CvExtractionRuns_OwnerUserId_StartedAtUtc" ON "CvExtractionRuns" ("OwnerUserId", "StartedAtUtc");""");
Exec(c, """CREATE INDEX IF NOT EXISTS "IX_CvExtractionRuns_ArtifactId" ON "CvExtractionRuns" ("ArtifactId");""");
}
EnsureGmailConnectionsTable(conn);
EnsureCvTables(conn);
// Legacy DB signature: migration history exists (AddCorrespondence applied), but 20260310195000 not recorded,
// and at least one of the new columns already exists.
@@ -787,6 +841,9 @@ CREATE TABLE IF NOT EXISTS "GmailConnections" (
EnsureMySqlColumn(conn, "Attachments", "UseForAi", "ALTER TABLE `Attachments` ADD COLUMN `UseForAi` tinyint(1) NOT NULL DEFAULT 1;");
EnsureMySqlColumn(conn, "AspNetUsers", "ProfileCvText", "ALTER TABLE `AspNetUsers` ADD COLUMN `ProfileCvText` longtext NULL;");
EnsureMySqlColumn(conn, "AspNetUsers", "ProfileCvStructureJson", "ALTER TABLE `AspNetUsers` ADD COLUMN `ProfileCvStructureJson` longtext NULL;");
EnsureMySqlColumn(conn, "AspNetUsers", "CurrentCvUploadArtifactId", "ALTER TABLE `AspNetUsers` ADD COLUMN `CurrentCvUploadArtifactId` int NULL;");
EnsureMySqlColumn(conn, "AspNetUsers", "CurrentCvExtractionRunId", "ALTER TABLE `AspNetUsers` ADD COLUMN `CurrentCvExtractionRunId` int NULL;");
EnsureMySqlColumn(conn, "AspNetUsers", "CurrentCvProfileVersion", "ALTER TABLE `AspNetUsers` ADD COLUMN `CurrentCvProfileVersion` int NULL;");
EnsureMySqlColumn(conn, "AspNetUsers", "AvatarImageDataUrl", "ALTER TABLE `AspNetUsers` ADD COLUMN `AvatarImageDataUrl` longtext NULL;");
EnsureMySqlColumn(conn, "AspNetUsers", "GoogleSubject", "ALTER TABLE `AspNetUsers` ADD COLUMN `GoogleSubject` longtext NULL;");
EnsureMySqlColumn(conn, "AspNetUsers", "GoogleEmail", "ALTER TABLE `AspNetUsers` ADD COLUMN `GoogleEmail` longtext NULL;");
@@ -811,6 +868,49 @@ PRIMARY KEY (`Id`)
cmd.ExecuteNonQuery();
}
if (!HasMySqlTable(conn, "CvUploadArtifacts"))
{
using var cmd = conn.CreateCommand();
cmd.CommandText = @"CREATE TABLE IF NOT EXISTS `CvUploadArtifacts` (
`Id` int NOT NULL AUTO_INCREMENT,
`OwnerUserId` varchar(255) NOT NULL,
`OriginalFileName` longtext NOT NULL,
`StoredFileName` longtext NOT NULL,
`MimeType` longtext NOT NULL,
`ByteSize` bigint NOT NULL,
`Sha256` longtext NOT NULL,
`StoragePath` longtext NOT NULL,
`UploadedAtUtc` datetime(6) NOT NULL,
PRIMARY KEY (`Id`)
);";
cmd.ExecuteNonQuery();
}
if (!HasMySqlTable(conn, "CvExtractionRuns"))
{
using var cmd = conn.CreateCommand();
cmd.CommandText = @"CREATE TABLE IF NOT EXISTS `CvExtractionRuns` (
`Id` int NOT NULL AUTO_INCREMENT,
`OwnerUserId` varchar(255) NOT NULL,
`ArtifactId` int NULL,
`Trigger` longtext NOT NULL,
`ParserVersion` longtext NOT NULL,
`NormalizerVersion` longtext NOT NULL,
`LlmPromptVersion` longtext NOT NULL,
`Status` longtext NOT NULL,
`RawExtractedText` longtext NULL,
`NormalizedText` longtext NULL,
`StructuredProfileJson` longtext NULL,
`ErrorMessage` longtext NULL,
`StartedAtUtc` datetime(6) NOT NULL,
`CompletedAtUtc` datetime(6) NULL,
`AppliedAtUtc` datetime(6) NULL,
PRIMARY KEY (`Id`),
CONSTRAINT `FK_CvExtractionRuns_CvUploadArtifacts_ArtifactId` FOREIGN KEY (`ArtifactId`) REFERENCES `CvUploadArtifacts` (`Id`) ON DELETE SET NULL
);";
cmd.ExecuteNonQuery();
}
if (!MySqlIndexExists(conn, "Companies", "IX_Companies_OwnerUserId"))
{
using var cmd = conn.CreateCommand();
@@ -824,6 +924,27 @@ PRIMARY KEY (`Id`)
cmd.CommandText = "CREATE INDEX `IX_JobApplications_OwnerUserId` ON `JobApplications` (`OwnerUserId`);";
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();
}
}
}