40 lines
1.7 KiB
Markdown
40 lines
1.7 KiB
Markdown
# Migrations and compatibility
|
|
|
|
The API applies EF Core migrations on startup and performs guarded legacy-schema reconciliation for SQLite and MariaDB/MySQL compatibility. Fresh and repeated disposable SQLite migration chains are the normal local verification; generated provider SQL is not proof of a live production migration.
|
|
|
|
The `Job`/`JobApplication` opportunity cutover is an expand/verify/contract change. Keep dual writes and compatibility reads until a production report and restored-backup rehearsal pass, then observe one release before removing legacy columns in a later migration. Never edit the history of an applied migration.
|
|
|
|
### Production cutover validation
|
|
|
|
After the additive backfill, run these read-only MariaDB/MySQL checks against production and a restored
|
|
backup. Every result must be `0`; do not turn them into an update script.
|
|
|
|
```sql
|
|
SELECT COUNT(*) AS missing_job
|
|
FROM JobApplications
|
|
WHERE JobId IS NULL;
|
|
|
|
SELECT COUNT(*) AS missing_target
|
|
FROM JobApplications a
|
|
LEFT JOIN Jobs j ON j.Id = a.JobId
|
|
WHERE a.JobId IS NOT NULL AND j.Id IS NULL;
|
|
|
|
SELECT COUNT(*) AS owner_mismatch
|
|
FROM JobApplications a
|
|
JOIN Jobs j ON j.Id = a.JobId
|
|
WHERE NOT (a.OwnerUserId <=> j.OwnerUserId);
|
|
|
|
SELECT COUNT(*) AS field_mismatch
|
|
FROM JobApplications a
|
|
JOIN Jobs j ON j.Id = a.JobId
|
|
WHERE NOT (a.CompanyId <=> j.CompanyId)
|
|
OR NOT (a.JobTitle <=> j.JobTitle)
|
|
OR NOT (a.Location <=> j.Location)
|
|
OR NOT (a.JobUrl <=> j.JobUrl)
|
|
OR NOT (a.Description <=> j.Description)
|
|
OR NOT (a.Salary <=> j.Salary);
|
|
```
|
|
|
|
Observe one release after the checks pass, then change reads, re-run the checks on a fresh restore, and
|
|
only then make `JobId` required and remove duplicated opportunity columns in a later migration.
|