@proteinjs/db 1.29.2 → 1.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/dist/generated/index.js +1 -1
- package/dist/generated/index.js.map +1 -1
- package/dist/generated/test/index.js +1 -1
- package/dist/generated/test/index.js.map +1 -1
- package/dist/src/MigrationRunner.d.ts +11 -0
- package/dist/src/MigrationRunner.d.ts.map +1 -1
- package/dist/src/MigrationRunner.js +47 -7
- package/dist/src/MigrationRunner.js.map +1 -1
- package/generated/index.ts +1 -1
- package/generated/test/index.ts +1 -1
- package/package.json +3 -3
- package/src/MigrationRunner.ts +41 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@proteinjs/db",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.30.0",
|
|
4
4
|
"main": "./dist/generated/index.js",
|
|
5
5
|
"types": "./dist/generated/index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"test": "jest --passWithNoTests"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@proteinjs/db-query": "^1.6.
|
|
44
|
+
"@proteinjs/db-query": "^1.6.3",
|
|
45
45
|
"@proteinjs/logger": "^1.0.21",
|
|
46
46
|
"@proteinjs/reflection": "^1.1.12",
|
|
47
47
|
"@proteinjs/serializer": "^1.1.10",
|
|
@@ -66,5 +66,5 @@
|
|
|
66
66
|
"ts-jest": "29.1.1",
|
|
67
67
|
"typescript": "5.2.2"
|
|
68
68
|
},
|
|
69
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "fd3dd48fae93c6da8c0b3decd6dd30a506a9109a"
|
|
70
70
|
}
|
package/src/MigrationRunner.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Moment, moment } from './opt/moment';
|
|
2
|
-
import { getDb } from './Db';
|
|
2
|
+
import { Db, getDb, getDbAsSystem } from './Db';
|
|
3
3
|
import { Table } from './Table';
|
|
4
4
|
import { SourceRecordRepo } from './source/SourceRecordRepo';
|
|
5
5
|
import { MigrationRunnerService, getMigrationRunnerService } from './services/MigrationRunnerService';
|
|
@@ -32,16 +32,41 @@ export class MigrationRunner implements MigrationRunnerService {
|
|
|
32
32
|
*/
|
|
33
33
|
runMigration(id: string): Promise<void> {
|
|
34
34
|
const migrationTable: Table<Migration> = new MigrationTable();
|
|
35
|
-
const migration =
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
const migration = this.resolveMigration(migrationTable, id);
|
|
36
|
+
return this.runAndRecord(migrationTable, migration, getDb);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Boot-path API: at server boot no user session exists, so `getDb()` (which `runMigration`
|
|
41
|
+
* records through) fail-closes on the migration table's doors. This method reads and records
|
|
42
|
+
* run state through `getDbAsSystem()` instead — it is the seam a future migrations-auto-run
|
|
43
|
+
* rides (deploy-coupled migrations call it during server startup).
|
|
44
|
+
*
|
|
45
|
+
* 'ensure' = idempotent: a row already in 'success' status is logged and skipped. A prior
|
|
46
|
+
* 'failure' row is retried by design — a fixed migration should run on the next boot.
|
|
47
|
+
*/
|
|
48
|
+
async ensureMigrationRun(id: string): Promise<void> {
|
|
49
|
+
const migrationTable: Table<Migration> = new MigrationTable();
|
|
50
|
+
const db = getDbAsSystem();
|
|
51
|
+
const migrationRow = await db.get(migrationTable, { id });
|
|
52
|
+
if (migrationRow?.status === 'success') {
|
|
53
|
+
this.logger.info({ message: `Migration (${id}) already applied, skipping` });
|
|
54
|
+
return;
|
|
38
55
|
}
|
|
39
56
|
|
|
40
|
-
|
|
57
|
+
const migration = this.resolveMigration(migrationTable, id);
|
|
58
|
+
await this.runAndRecord(migrationTable, migration, () => db);
|
|
41
59
|
}
|
|
42
60
|
|
|
43
|
-
|
|
44
|
-
|
|
61
|
+
// The db is taken as a provider, resolved inside this async body: on the service path,
|
|
62
|
+
// constructing the Db is itself run infrastructure — its failure must REJECT the detached
|
|
63
|
+
// promise, not throw synchronously from runMigration (only a bogus id may reach the client).
|
|
64
|
+
private async runAndRecord(
|
|
65
|
+
migrationTable: Table<Migration>,
|
|
66
|
+
migration: Migration,
|
|
67
|
+
getRunDb: () => Db
|
|
68
|
+
): Promise<void> {
|
|
69
|
+
const db = getRunDb();
|
|
45
70
|
migration.status = 'running';
|
|
46
71
|
migration.startTime = moment();
|
|
47
72
|
await db.update(migrationTable, migration);
|
|
@@ -66,6 +91,15 @@ export class MigrationRunner implements MigrationRunnerService {
|
|
|
66
91
|
});
|
|
67
92
|
}
|
|
68
93
|
|
|
94
|
+
private resolveMigration(migrationTable: Table<Migration>, id: string): Migration {
|
|
95
|
+
const migration = new SourceRecordRepo().getSourceRecord<Migration>(migrationTable.name, id);
|
|
96
|
+
if (!migration) {
|
|
97
|
+
throw new Error(`Unable to find migration source record for id: ${id}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return migration;
|
|
101
|
+
}
|
|
102
|
+
|
|
69
103
|
private duration(start: Moment, end: Moment): string {
|
|
70
104
|
const duration = moment.duration(end.diff(start));
|
|
71
105
|
const parts: string[] = [];
|