fix(new): ledger every schema migration
Amp-Thread-ID: https://ampcode.com/threads/T-019e55df-9bcd-73e6-9935-c1e6238cd273 Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
1 parent
0b53eec292
commit
df9317ef4b
2 files changed
+50
-11
No files matched your search
@@ -9,16 +9,22 @@ import { skillHardeningSchema } from "./migrations/007-skill-hardening";
|
||||
import { providerHealthSchema } from "./migrations/008-provider-health";
|
||||
import { socialGovernanceSchema } from "./migrations/009-social-governance";
|
||||
|
||||
const MIGRATIONS: Array<{ version: number; sql: string }> = [
|
||||
{ version: 1, sql: initialEnterpriseSchema },
|
||||
{ version: 2, sql: collaborationProviderPolicySchema },
|
||||
{ version: 3, sql: onboardingExecutionSchema },
|
||||
{ version: 4, sql: filesPinnedAndScheduledPosts },
|
||||
{ version: 5, sql: chatReadState },
|
||||
{ version: 6, sql: appStateSchema },
|
||||
{ version: 7, sql: skillHardeningSchema },
|
||||
{ version: 8, sql: providerHealthSchema },
|
||||
{ version: 9, sql: socialGovernanceSchema },
|
||||
interface Migration {
|
||||
version: number;
|
||||
name: string;
|
||||
sql: string;
|
||||
}
|
||||
|
||||
const MIGRATIONS: Migration[] = [
|
||||
{ version: 1, name: "initial_enterprise_schema", sql: initialEnterpriseSchema },
|
||||
{ version: 2, name: "collaboration_provider_policy_schema", sql: collaborationProviderPolicySchema },
|
||||
{ version: 3, name: "onboarding_execution_schema", sql: onboardingExecutionSchema },
|
||||
{ version: 4, name: "files_pinned_and_scheduled_posts", sql: filesPinnedAndScheduledPosts },
|
||||
{ version: 5, name: "chat_read_state", sql: chatReadState },
|
||||
{ version: 6, name: "app_state", sql: appStateSchema },
|
||||
{ version: 7, name: "skill_hardening", sql: skillHardeningSchema },
|
||||
{ version: 8, name: "provider_health", sql: providerHealthSchema },
|
||||
{ version: 9, name: "social_governance", sql: socialGovernanceSchema },
|
||||
];
|
||||
|
||||
const SCHEMA_VERSION = MIGRATIONS[MIGRATIONS.length - 1].version;
|
||||
@@ -37,10 +43,35 @@ export function installSchema(db: DatabaseSync): void {
|
||||
if (currentVersion > SCHEMA_VERSION) {
|
||||
throw new Error(`Database schema ${currentVersion} is newer than supported schema ${SCHEMA_VERSION}.`);
|
||||
}
|
||||
backfillMigrationLedger(db, currentVersion);
|
||||
|
||||
for (const migration of MIGRATIONS) {
|
||||
if (currentVersion >= migration.version) continue;
|
||||
db.exec(migration.sql);
|
||||
applyMigration(db, migration);
|
||||
currentVersion = migration.version;
|
||||
}
|
||||
}
|
||||
|
||||
function applyMigration(db: DatabaseSync, migration: Migration): void {
|
||||
db.exec("begin immediate");
|
||||
try {
|
||||
db.exec(migration.sql);
|
||||
recordMigration(db, migration);
|
||||
db.exec("commit");
|
||||
} catch (error) {
|
||||
db.exec("rollback");
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
function backfillMigrationLedger(db: DatabaseSync, currentVersion: number): void {
|
||||
for (const migration of MIGRATIONS) {
|
||||
if (migration.version > currentVersion) return;
|
||||
recordMigration(db, migration);
|
||||
}
|
||||
}
|
||||
|
||||
function recordMigration(db: DatabaseSync, migration: Migration): void {
|
||||
db.prepare("insert or ignore into schema_migrations(version, name, applied_at) values (?, ?, datetime('now'))")
|
||||
.run(migration.version, migration.name);
|
||||
}
|
||||
@@ -19,6 +19,14 @@ function createConnection(): DatabaseConnection {
|
||||
}
|
||||
|
||||
describe("domain services", () => {
|
||||
test("records every applied schema migration version", () => {
|
||||
const connection = createConnection();
|
||||
|
||||
const rows = connection.db.prepare("select version from schema_migrations order by version asc").all() as Array<{ version: number }>;
|
||||
expect(rows.map((row) => row.version)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
connection.close();
|
||||
});
|
||||
|
||||
test("creates an organization with providers, chat spaces, employee, and audit", () => {
|
||||
const connection = createConnection();
|
||||
const organization = new OrganizationService(connection.db);
|
||||
|
||||
Reference in new issue
Block a user