refactor(db): migrate career profile aggregate
Transfer the canonical career profile, revision history, and six relational child collections to provider-aware migration ownership. Preserve legacy JSON, ordered child data, indexes, and cascade semantics.
This commit is contained in:
@@ -40,9 +40,7 @@ Neither a single reconciliation position nor one shared provider sequence works:
|
||||
|
||||
- **Pass 1 must come first.** A legacy database has hand-added columns and Identity tables that
|
||||
predate the migrations; without repairing them (and stamping the legacy migration id into
|
||||
`__EFMigrationsHistory`) `Migrate()` collides with them. `AddCareerProfileRelationalChildren` also
|
||||
adds children that reference `CareerProfiles`, a **reconciler-owned** table — so it must exist
|
||||
before migrations run.
|
||||
`__EFMigrationsHistory`) `Migrate()` collides with them.
|
||||
- **The final pass must come after.** On a brand-new database the migration-owned tables do not exist during
|
||||
pass 1, so every reconciler table that references one (FK into `JobApplications`) is skipped, as
|
||||
are the index and `AUTO_INCREMENT` repairs.
|
||||
@@ -67,7 +65,9 @@ already-correct database. Two consequences worth knowing:
|
||||
Created by EF migrations, never by the reconciler:
|
||||
|
||||
`AccountDeletionFiles`, `AccountDeletionRequests`, `AiInteractions`, `AiUsageRecords`, `AiWorkspaceNotes`,
|
||||
`ApplicationChecklistItems`, `Attachments`, `Companies`, `CoverLetterVersions`,
|
||||
`ApplicationChecklistItems`, `Attachments`, `CareerCertifications`, `CareerEducations`,
|
||||
`CareerExperiences`, `CareerLanguages`, `CareerProfiles`, `CareerProfileVersions`, `CareerProjects`,
|
||||
`CareerSkills`, `Companies`, `CoverLetterVersions`,
|
||||
`Correspondences`, `CvExtractionRuns`, `CvUploadArtifacts`, `CvVariants`, `CvVariantVersions`,
|
||||
`EmailDrafts`, `EmailSendAttempts`, `GmailConnections`,
|
||||
`GmailReviewDecisions`, `ImapConnections`, `InterviewPrepItems`, `InterviewPrepNotes`, `JobApplications`, `JobEvents`, `Jobs`,
|
||||
@@ -127,6 +127,11 @@ remains cascading.
|
||||
AI-generated questions, answers, preparation state, sources, and ordering are retained; application
|
||||
deletion remains cascading.
|
||||
|
||||
The Career Profile aggregate (`CareerProfiles`, `CareerProfileVersions`, and all six relational
|
||||
child tables) moved in `20260830133000_AdoptCareerProfileSchema`. Canonical/long-tail JSON,
|
||||
append-only history, stable child keys and ordering are retained; bounded MariaDB owner/item keys
|
||||
keep all aggregate indexes provider-safe.
|
||||
|
||||
The reconciler may **repair** these (add a missing column, add an index, fix a non-`AUTO_INCREMENT`
|
||||
primary key) and may seed the default `RuleSettings` row — but it must never `CREATE TABLE` them.
|
||||
It used to create `RuleSettings`, which is precisely why a clean install failed with
|
||||
@@ -134,12 +139,7 @@ It used to create `RuleSettings`, which is precisely why a clean install failed
|
||||
|
||||
### Reconciler-owned
|
||||
|
||||
Created by `StartupInitializationExtensions`, with a **no-op migration** holding the model snapshot:
|
||||
|
||||
`CareerProfiles`, `CareerProfileVersions`, the six CareerProfile children (`CareerExperiences`,
|
||||
`CareerEducations`, `CareerSkills`, `CareerProjects`, `CareerCertifications`, `CareerLanguages`).
|
||||
|
||||
The seven ASP.NET Identity tables are also currently reconciler-owned, despite older wording that
|
||||
The seven ASP.NET Identity tables are currently reconciler-owned, despite older wording that
|
||||
called them migration-owned: `AspNetRoles`, `AspNetUsers`, `AspNetRoleClaims`, `AspNetUserClaims`,
|
||||
`AspNetUserLogins`, `AspNetUserRoles`, and `AspNetUserTokens`. Guarded migration bootstraps for
|
||||
`AspNetUsers` supports standalone traversal but does not yet transfer ownership. The historical
|
||||
@@ -153,11 +153,11 @@ No-op migrations, each with a comment explaining why:
|
||||
|
||||
| Migration | Tables |
|
||||
|---|---|
|
||||
| `20260717222917_AddCareerProfileRelationalChildren` | the six CareerProfile children |
|
||||
| `20260717222917_AddCareerProfileRelationalChildren` | historical no-op; ownership transferred by `20260830133000_AdoptCareerProfileSchema` |
|
||||
| `20260718074509_AddCvVariants` | historical no-op; ownership transferred by `20260830128000_AdoptCvVariantSchema` |
|
||||
| `20260718131138_AddAiInteractions` | historical no-op; ownership transferred by `20260830129000_AdoptAiInteractionSchema` |
|
||||
| `20260719085904_AddApplicationChecklistItems` | historical no-op; ownership transferred by `20260830130000_AdoptApplicationChecklistSchema` |
|
||||
| `20260719094728_SyncCareerChildKeyLengths` | snapshot sync only |
|
||||
| `20260719094728_SyncCareerChildKeyLengths` | historical snapshot sync; ownership transferred by `20260830133000_AdoptCareerProfileSchema` |
|
||||
| `20260719120954_AddCoverLetterVersions` | historical no-op; ownership transferred by `20260830131000_AdoptCoverLetterVersionSchema` |
|
||||
| `20260719145044_AddInterviewPrepItems` | historical no-op; ownership transferred by `20260830132000_AdoptInterviewPrepItemSchema` |
|
||||
|
||||
@@ -170,7 +170,7 @@ skips it on a fresh database and pass 2 creates it:
|
||||
|---|---|
|
||||
| `TailoredCvDrafts`, `InterviewPrepNotes`, `AiWorkspaceNotes`, `CvVariants`, `AiInteractions`, `ApplicationChecklistItems`, `CoverLetterVersions`, `InterviewPrepItems` | `JobApplications` (migration-owned) |
|
||||
| `CvVariantVersions` | `CvVariants` |
|
||||
| `CareerProfileVersions`, the six CareerProfile children | `CareerProfiles` |
|
||||
| `CareerProfileVersions`, the six CareerProfile children | `CareerProfiles` (migration-owned) |
|
||||
| `CvExtractionRuns` | `CvUploadArtifacts` |
|
||||
|
||||
Index creation goes through one helper, `EnsureMySqlIndex`, which is guarded on **table** existence
|
||||
|
||||
Reference in New Issue
Block a user