@webiny/data-migration 0.0.0-unstable.aa00eecd97 → 0.0.0-unstable.ac6ebf63c6
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/MigrationRunner.d.ts +8 -4
- package/MigrationRunner.js +109 -50
- package/MigrationRunner.js.map +1 -1
- package/README.md +9 -4
- package/cli/CliMigrationRunReporter.d.ts +13 -0
- package/cli/CliMigrationRunReporter.js +50 -0
- package/cli/CliMigrationRunReporter.js.map +1 -0
- package/cli/InteractiveCliStatusReporter.d.ts +11 -0
- package/cli/InteractiveCliStatusReporter.js +66 -0
- package/cli/InteractiveCliStatusReporter.js.map +1 -0
- package/cli/LogReporter.d.ts +10 -0
- package/cli/LogReporter.js +36 -0
- package/cli/LogReporter.js.map +1 -0
- package/cli/LogStream.d.ts +10 -0
- package/cli/LogStream.js +51 -0
- package/cli/LogStream.js.map +1 -0
- package/cli/MigrationRunReporter.d.ts +4 -0
- package/cli/MigrationRunReporter.js +3 -0
- package/cli/MigrationRunReporter.js.map +1 -0
- package/cli/MigrationRunner.d.ts +45 -0
- package/cli/MigrationRunner.js +128 -0
- package/cli/MigrationRunner.js.map +1 -0
- package/cli/MigrationStatusReporter.d.ts +4 -0
- package/cli/MigrationStatusReporter.js +3 -0
- package/cli/MigrationStatusReporter.js.map +1 -0
- package/cli/NonInteractiveCliStatusReporter.d.ts +9 -0
- package/cli/NonInteractiveCliStatusReporter.js +35 -0
- package/cli/NonInteractiveCliStatusReporter.js.map +1 -0
- package/cli/VoidStatusReporter.d.ts +4 -0
- package/cli/VoidStatusReporter.js +7 -0
- package/cli/VoidStatusReporter.js.map +1 -0
- package/cli/getDuration.js +3 -8
- package/cli/getDuration.js.map +1 -1
- package/cli/index.d.ts +10 -3
- package/cli/index.js +11 -37
- package/cli/index.js.map +1 -1
- package/createPinoLogger.d.ts +4 -7
- package/createPinoLogger.js +11 -16
- package/createPinoLogger.js.map +1 -1
- package/createTable.d.ts +4 -4
- package/createTable.js +8 -11
- package/createTable.js.map +1 -1
- package/handlers/createDdbEsProjectMigration.d.ts +7 -7
- package/handlers/createDdbEsProjectMigration.js +41 -45
- package/handlers/createDdbEsProjectMigration.js.map +1 -1
- package/handlers/createDdbProjectMigration.d.ts +5 -5
- package/handlers/createDdbProjectMigration.js +37 -41
- package/handlers/createDdbProjectMigration.js.map +1 -1
- package/handlers/createPatternMatcher.d.ts +1 -1
- package/handlers/createPatternMatcher.js +5 -11
- package/handlers/createPatternMatcher.js.map +1 -1
- package/handlers/devVersionErrorResponse.js +3 -8
- package/handlers/devVersionErrorResponse.js.map +1 -1
- package/index.d.ts +6 -7
- package/index.js +7 -70
- package/index.js.map +1 -1
- package/package.json +19 -35
- package/repository/migrations.repository.d.ts +3 -3
- package/repository/migrations.repository.js +18 -31
- package/repository/migrations.repository.js.map +1 -1
- package/symbols.js +8 -19
- package/symbols.js.map +1 -1
- package/types.d.ts +9 -6
- package/types.js +2 -11
- package/types.js.map +1 -1
- package/cli/getMigrationStatus.d.ts +0 -9
- package/cli/getMigrationStatus.js +0 -27
- package/cli/getMigrationStatus.js.map +0 -1
- package/cli/printReport.d.ts +0 -9
- package/cli/printReport.js +0 -57
- package/cli/printReport.js.map +0 -1
- package/cli/runMigration.d.ts +0 -13
- package/cli/runMigration.js +0 -85
- package/cli/runMigration.js.map +0 -1
- package/createId.d.ts +0 -1
- package/createId.js +0 -14
- package/createId.js.map +0 -1
- package/repository/createStandardEntity.d.ts +0 -5
- package/repository/createStandardEntity.js +0 -37
- package/repository/createStandardEntity.js.map +0 -1
package/MigrationRunner.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { Logger } from "
|
|
2
|
-
import { MigrationRepository, DataMigration, ExecutionTimeLimiter, MigrationStatus } from "./types";
|
|
3
|
-
export
|
|
1
|
+
import type { Logger } from "@webiny/logger";
|
|
2
|
+
import type { MigrationRepository, DataMigration, ExecutionTimeLimiter, MigrationStatus } from "./types.js";
|
|
3
|
+
export type IsMigrationApplicable = (migration: DataMigration) => boolean;
|
|
4
4
|
export declare class MigrationRunner {
|
|
5
5
|
private readonly logger;
|
|
6
6
|
private readonly migrations;
|
|
7
7
|
private readonly repository;
|
|
8
8
|
private readonly timeLimiter;
|
|
9
|
+
private context;
|
|
9
10
|
constructor(repository: MigrationRepository, timeLimiter: ExecutionTimeLimiter, migrations: DataMigration[], logger: Logger | undefined);
|
|
10
|
-
|
|
11
|
+
setContext(context: Record<string, any>): void;
|
|
12
|
+
execute(projectVersion: string, isApplicable?: IsMigrationApplicable, forceExecute?: boolean): Promise<void>;
|
|
11
13
|
getStatus(): Promise<MigrationStatus>;
|
|
12
14
|
private validateIds;
|
|
13
15
|
private createCheckpoint;
|
|
@@ -15,4 +17,6 @@ export declare class MigrationRunner {
|
|
|
15
17
|
private getOrCreateRunItem;
|
|
16
18
|
private setRunItem;
|
|
17
19
|
private setRunItemAndSave;
|
|
20
|
+
private printForceExecuteEnvVars;
|
|
21
|
+
private printSkipExecuteEnvVars;
|
|
18
22
|
}
|
package/MigrationRunner.js
CHANGED
|
@@ -1,17 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
});
|
|
7
|
-
exports.MigrationRunner = void 0;
|
|
8
|
-
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
|
|
9
|
-
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
10
|
-
var _semver = require("semver");
|
|
11
|
-
var _ioc = require("@webiny/ioc");
|
|
12
|
-
var _utils = require("@webiny/utils");
|
|
13
|
-
var _symbols = require("./symbols");
|
|
14
|
-
var _createPinoLogger = require("./createPinoLogger");
|
|
1
|
+
import { coerce } from "semver";
|
|
2
|
+
import { inject, makeInjectable } from "@webiny/ioc";
|
|
3
|
+
import { executeWithRetry, mdbid } from "@webiny/utils";
|
|
4
|
+
import { MigrationRepositorySymbol, LoggerSymbol, MigrationSymbol, ExecutionTimeLimiterSymbol } from "./symbols.js";
|
|
5
|
+
import { createPinoLogger, getChildLogger } from "./createPinoLogger.js";
|
|
15
6
|
const getCurrentISOTime = () => {
|
|
16
7
|
return new Date().toISOString();
|
|
17
8
|
};
|
|
@@ -21,23 +12,43 @@ const getRunItemDuration = runItem => {
|
|
|
21
12
|
}
|
|
22
13
|
return new Date(runItem.finishedOn).getTime() - new Date(runItem.startedOn).getTime();
|
|
23
14
|
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* This allows us to force-execute a migration, even if it's not in the list of the applicable migrations.
|
|
18
|
+
* Example: WEBINY_MIGRATION_FORCE_EXECUTE_5_35_0_006=true
|
|
19
|
+
*/
|
|
20
|
+
const shouldForceExecute = mig => {
|
|
21
|
+
const key = `WEBINY_MIGRATION_FORCE_EXECUTE_${mig.getId().replace(/[\.\-]/g, "_")}`;
|
|
22
|
+
return process.env[key] === "true";
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* This allows us to always skip a migration.
|
|
27
|
+
* Example: WEBINY_MIGRATION_SKIP_5_35_0_006=true
|
|
28
|
+
*/
|
|
29
|
+
const shouldSkip = mig => {
|
|
30
|
+
const key = `WEBINY_MIGRATION_SKIP_${mig.getId().replace(/[\.\-]/g, "_")}`;
|
|
31
|
+
return process.env[key] === "true";
|
|
32
|
+
};
|
|
24
33
|
class MigrationNotFinished extends Error {}
|
|
25
34
|
class MigrationInProgress extends Error {}
|
|
26
|
-
class MigrationRunner {
|
|
35
|
+
export class MigrationRunner {
|
|
36
|
+
context = {};
|
|
27
37
|
constructor(repository, timeLimiter, migrations, logger) {
|
|
28
|
-
(0, _defineProperty2.default)(this, "logger", void 0);
|
|
29
|
-
(0, _defineProperty2.default)(this, "migrations", void 0);
|
|
30
|
-
(0, _defineProperty2.default)(this, "repository", void 0);
|
|
31
|
-
(0, _defineProperty2.default)(this, "timeLimiter", void 0);
|
|
32
38
|
this.repository = repository;
|
|
33
39
|
this.timeLimiter = timeLimiter;
|
|
34
40
|
this.migrations = migrations || [];
|
|
35
41
|
if (!logger) {
|
|
36
|
-
logger =
|
|
42
|
+
logger = createPinoLogger();
|
|
37
43
|
}
|
|
38
44
|
this.logger = logger;
|
|
39
45
|
}
|
|
40
|
-
|
|
46
|
+
setContext(context) {
|
|
47
|
+
this.context = context;
|
|
48
|
+
}
|
|
49
|
+
async execute(projectVersion, isApplicable,
|
|
50
|
+
// Force execute applicable migrations.
|
|
51
|
+
forceExecute = false) {
|
|
41
52
|
const lastRun = await this.getOrCreateRun();
|
|
42
53
|
try {
|
|
43
54
|
this.validateIds(this.migrations);
|
|
@@ -56,7 +67,7 @@ class MigrationRunner {
|
|
|
56
67
|
|
|
57
68
|
// Get current version, and coerce it to a valid SemVer.
|
|
58
69
|
// With this, we can run migrations targeted for stable versions, released under a preid tag (e.g., `beta`).
|
|
59
|
-
const currentVersion =
|
|
70
|
+
const currentVersion = coerce(projectVersion) + "";
|
|
60
71
|
const startingId = latestMigration ? latestMigration.id : `${currentVersion}-000`;
|
|
61
72
|
const lastId = `${currentVersion}-999`;
|
|
62
73
|
|
|
@@ -82,7 +93,22 @@ class MigrationRunner {
|
|
|
82
93
|
return mig.getId() > startingId && mig.getId() <= lastId;
|
|
83
94
|
};
|
|
84
95
|
const isMigrationApplicable = isApplicable || defaultIsApplicable;
|
|
96
|
+
this.printForceExecuteEnvVars();
|
|
97
|
+
this.printSkipExecuteEnvVars();
|
|
98
|
+
if (forceExecute) {
|
|
99
|
+
this.logger.info(`ALL APPLICABLE MIGRATIONS WILL BE FORCE-EXECUTED! (via --force flag)`);
|
|
100
|
+
}
|
|
85
101
|
const executableMigrations = this.migrations.filter(mig => {
|
|
102
|
+
if (shouldSkip(mig)) {
|
|
103
|
+
this.setRunItem(lastRun, {
|
|
104
|
+
id: mig.getId(),
|
|
105
|
+
status: "skipped"
|
|
106
|
+
});
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
if (shouldForceExecute(mig)) {
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
86
112
|
if (!isMigrationApplicable(mig)) {
|
|
87
113
|
this.setRunItem(lastRun, {
|
|
88
114
|
id: mig.getId(),
|
|
@@ -98,10 +124,12 @@ class MigrationRunner {
|
|
|
98
124
|
const shouldCreateCheckpoint = () => {
|
|
99
125
|
return this.timeLimiter() < 120000;
|
|
100
126
|
};
|
|
127
|
+
|
|
128
|
+
//
|
|
101
129
|
for (const migration of executableMigrations) {
|
|
102
130
|
const runItem = this.getOrCreateRunItem(lastRun, migration);
|
|
103
131
|
const checkpoint = await this.repository.getCheckpoint(migration.getId());
|
|
104
|
-
const logger =
|
|
132
|
+
const logger = getChildLogger(this.logger, migration);
|
|
105
133
|
if (checkpoint) {
|
|
106
134
|
this.logger.info(checkpoint, `Found checkpoint ${migration.getId()}.`);
|
|
107
135
|
}
|
|
@@ -109,6 +137,7 @@ class MigrationRunner {
|
|
|
109
137
|
projectVersion,
|
|
110
138
|
logger,
|
|
111
139
|
checkpoint,
|
|
140
|
+
forceExecute: forceExecute || shouldForceExecute(migration),
|
|
112
141
|
runningOutOfTime: shouldCreateCheckpoint,
|
|
113
142
|
createCheckpoint: async data => {
|
|
114
143
|
await this.createCheckpoint(migration, data);
|
|
@@ -119,19 +148,19 @@ class MigrationRunner {
|
|
|
119
148
|
throw new MigrationNotFinished();
|
|
120
149
|
}
|
|
121
150
|
};
|
|
122
|
-
const shouldExecute = checkpoint ? true : await migration.shouldExecute(context);
|
|
123
|
-
if (!shouldExecute) {
|
|
124
|
-
this.logger.info(`Skipping migration %s.`, migration.getId());
|
|
125
|
-
runItem.status = "skipped";
|
|
126
|
-
await this.setRunItemAndSave(lastRun, runItem);
|
|
127
|
-
await this.repository.logMigration({
|
|
128
|
-
id: migration.getId(),
|
|
129
|
-
description: migration.getDescription(),
|
|
130
|
-
reason: "skipped"
|
|
131
|
-
});
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
151
|
try {
|
|
152
|
+
const shouldExecute = checkpoint || context.forceExecute ? true : await migration.shouldExecute(context);
|
|
153
|
+
if (!shouldExecute) {
|
|
154
|
+
this.logger.info(`Skipping migration %s.`, migration.getId());
|
|
155
|
+
runItem.status = "skipped";
|
|
156
|
+
await this.setRunItemAndSave(lastRun, runItem);
|
|
157
|
+
await this.repository.logMigration({
|
|
158
|
+
id: migration.getId(),
|
|
159
|
+
description: migration.getDescription(),
|
|
160
|
+
reason: "skipped"
|
|
161
|
+
});
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
135
164
|
lastRun.status = "running";
|
|
136
165
|
runItem.status = "running";
|
|
137
166
|
if (!runItem.startedOn) {
|
|
@@ -160,12 +189,15 @@ class MigrationRunner {
|
|
|
160
189
|
this.logger.error(err, err.message);
|
|
161
190
|
return;
|
|
162
191
|
} finally {
|
|
163
|
-
// We sum duration from the previous run with the current run.
|
|
164
192
|
runItem.finishedOn = getCurrentISOTime();
|
|
165
193
|
|
|
166
194
|
// Update run stats.
|
|
167
195
|
await this.setRunItemAndSave(lastRun, runItem);
|
|
168
|
-
|
|
196
|
+
if (runItem.status === "pending") {
|
|
197
|
+
this.logger.info(`Pausing migration %s, awaiting continuation.`, migration.getId());
|
|
198
|
+
} else {
|
|
199
|
+
this.logger.info(`Finished executing migration %s in %sms.`, migration.getId(), getRunItemDuration(runItem));
|
|
200
|
+
}
|
|
169
201
|
}
|
|
170
202
|
await this.repository.logMigration({
|
|
171
203
|
id: migration.getId(),
|
|
@@ -191,13 +223,15 @@ class MigrationRunner {
|
|
|
191
223
|
// Since we don't store migration descriptions to DB, we need to fetch them from actual migration objects.
|
|
192
224
|
const withDescriptions = lastRun.migrations.map(mig => {
|
|
193
225
|
const dataMigration = this.migrations.find(dm => dm.getId() === mig.id);
|
|
194
|
-
return
|
|
226
|
+
return {
|
|
227
|
+
...mig,
|
|
195
228
|
description: dataMigration ? dataMigration.getDescription() : "N/A"
|
|
196
|
-
}
|
|
229
|
+
};
|
|
197
230
|
});
|
|
198
|
-
return
|
|
231
|
+
return {
|
|
232
|
+
...lastRun,
|
|
199
233
|
migrations: withDescriptions
|
|
200
|
-
}
|
|
234
|
+
};
|
|
201
235
|
}
|
|
202
236
|
validateIds(migrations) {
|
|
203
237
|
const ids = new Set();
|
|
@@ -219,7 +253,7 @@ class MigrationRunner {
|
|
|
219
253
|
async createCheckpoint(migration, checkpoint) {
|
|
220
254
|
this.logger.info(checkpoint, `Saving checkpoint ${migration.getId()}`);
|
|
221
255
|
const execute = () => this.repository.createCheckpoint(migration.getId(), checkpoint);
|
|
222
|
-
await
|
|
256
|
+
await executeWithRetry(execute);
|
|
223
257
|
}
|
|
224
258
|
async getOrCreateRun() {
|
|
225
259
|
const resolvedStatus = ["done", "error"];
|
|
@@ -230,11 +264,12 @@ class MigrationRunner {
|
|
|
230
264
|
}
|
|
231
265
|
if (!lastRun || resolvedStatus.includes(lastRun.status)) {
|
|
232
266
|
lastRun = {
|
|
233
|
-
id:
|
|
267
|
+
id: mdbid(),
|
|
234
268
|
status: "init",
|
|
235
269
|
startedOn: getCurrentISOTime(),
|
|
236
270
|
finishedOn: "",
|
|
237
|
-
migrations: []
|
|
271
|
+
migrations: [],
|
|
272
|
+
context: this.context
|
|
238
273
|
};
|
|
239
274
|
await this.repository.saveRun(lastRun);
|
|
240
275
|
}
|
|
@@ -243,9 +278,10 @@ class MigrationRunner {
|
|
|
243
278
|
getOrCreateRunItem(run, migration) {
|
|
244
279
|
const existingItem = run.migrations.find(item => item.id === migration.getId());
|
|
245
280
|
if (existingItem) {
|
|
246
|
-
return
|
|
281
|
+
return {
|
|
282
|
+
...existingItem,
|
|
247
283
|
status: "running"
|
|
248
|
-
}
|
|
284
|
+
};
|
|
249
285
|
}
|
|
250
286
|
return {
|
|
251
287
|
id: migration.getId(),
|
|
@@ -265,11 +301,34 @@ class MigrationRunner {
|
|
|
265
301
|
this.setRunItem(run, item);
|
|
266
302
|
await this.repository.saveRun(run);
|
|
267
303
|
}
|
|
304
|
+
printForceExecuteEnvVars() {
|
|
305
|
+
const forceKeys = Object.keys(process.env).filter(key => key.startsWith("WEBINY_MIGRATION_FORCE_EXECUTE_"));
|
|
306
|
+
if (!forceKeys.length) {
|
|
307
|
+
this.logger.info(`No migrations are enforced via WEBINY_MIGRATION_FORCE_EXECUTE environment variable.`);
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
this.logger.info(`FORCED MIGRATIONS DETECTED!`);
|
|
311
|
+
for (const key of forceKeys) {
|
|
312
|
+
this.logger.info(`${key}=${process.env[key]}`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
printSkipExecuteEnvVars() {
|
|
316
|
+
const skipKeys = Object.keys(process.env).filter(key => key.startsWith("WEBINY_MIGRATION_SKIP_"));
|
|
317
|
+
if (!skipKeys.length) {
|
|
318
|
+
this.logger.info(`No migrations are skipped via WEBINY_MIGRATION_SKIP environment variable.`);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
this.logger.info(`SKIPPED MIGRATIONS DETECTED!`);
|
|
322
|
+
for (const key of skipKeys) {
|
|
323
|
+
this.logger.info(`${key}=${process.env[key]}`);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
268
326
|
}
|
|
269
|
-
|
|
270
|
-
(0, _ioc.makeInjectable)(MigrationRunner, [(0, _ioc.inject)(_symbols.MigrationRepositorySymbol), (0, _ioc.inject)(_symbols.ExecutionTimeLimiterSymbol), (0, _ioc.inject)(_symbols.MigrationSymbol, {
|
|
327
|
+
makeInjectable(MigrationRunner, [inject(MigrationRepositorySymbol), inject(ExecutionTimeLimiterSymbol), inject(MigrationSymbol, {
|
|
271
328
|
multi: true,
|
|
272
329
|
optional: true
|
|
273
|
-
}),
|
|
330
|
+
}), inject(LoggerSymbol, {
|
|
274
331
|
optional: true
|
|
275
|
-
})]);
|
|
332
|
+
})]);
|
|
333
|
+
|
|
334
|
+
//# sourceMappingURL=MigrationRunner.js.map
|
package/MigrationRunner.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["getCurrentISOTime","Date","toISOString","getRunItemDuration","runItem","startedOn","finishedOn","getTime","MigrationNotFinished","Error","MigrationInProgress","MigrationRunner","constructor","repository","timeLimiter","migrations","logger","createPinoLogger","execute","projectVersion","isApplicable","lastRun","getOrCreateRun","validateIds","err","status","error","message","saveRun","latestMigration","listMigrations","limit","info","currentVersion","coerce","startingId","id","lastId","logMigration","description","reason","defaultIsApplicable","mig","getId","isMigrationApplicable","executableMigrations","filter","setRunItem","sort","a","b","length","shouldCreateCheckpoint","migration","getOrCreateRunItem","checkpoint","getCheckpoint","getChildLogger","context","runningOutOfTime","createCheckpoint","data","createCheckpointAndExit","shouldExecute","setRunItemAndSave","getDescription","name","stack","code","deleteCheckpoint","getStatus","getLastRun","withDescriptions","map","dataMigration","find","dm","ids","Set","endsWith","has","add","executeWithRetry","resolvedStatus","unresolvedStatus","includes","mdbid","run","existingItem","item","index","findIndex","push","slice","makeInjectable","inject","MigrationRepositorySymbol","ExecutionTimeLimiterSymbol","MigrationSymbol","multi","optional","LoggerSymbol"],"sources":["MigrationRunner.ts"],"sourcesContent":["import { coerce } from \"semver\";\nimport { Logger } from \"pino\";\nimport { inject, makeInjectable } from \"@webiny/ioc\";\nimport { executeWithRetry, mdbid } from \"@webiny/utils\";\nimport {\n MigrationRepositorySymbol,\n LoggerSymbol,\n MigrationSymbol,\n ExecutionTimeLimiterSymbol\n} from \"./symbols\";\nimport { createPinoLogger, getChildLogger } from \"./createPinoLogger\";\nimport {\n MigrationRepository,\n DataMigration,\n DataMigrationContext,\n ExecutionTimeLimiter,\n MigrationRun,\n MigrationStatus,\n MigrationRunItem\n} from \"~/types\";\n\nexport type IsMigrationApplicable = (migration: DataMigration) => boolean;\n\nconst getCurrentISOTime = () => {\n return new Date().toISOString();\n};\n\nconst getRunItemDuration = (runItem: MigrationRunItem) => {\n if (!runItem.startedOn || !runItem.finishedOn) {\n return \"N/A\";\n }\n\n return new Date(runItem.finishedOn).getTime() - new Date(runItem.startedOn).getTime();\n};\n\nclass MigrationNotFinished extends Error {}\nclass MigrationInProgress extends Error {}\n\nexport class MigrationRunner {\n private readonly logger: Logger;\n private readonly migrations: DataMigration[];\n private readonly repository: MigrationRepository;\n private readonly timeLimiter: ExecutionTimeLimiter;\n\n constructor(\n repository: MigrationRepository,\n timeLimiter: ExecutionTimeLimiter,\n migrations: DataMigration[],\n logger: Logger | undefined\n ) {\n this.repository = repository;\n this.timeLimiter = timeLimiter;\n this.migrations = migrations || [];\n\n if (!logger) {\n logger = createPinoLogger();\n }\n this.logger = logger;\n }\n\n async execute(projectVersion: string, isApplicable?: IsMigrationApplicable) {\n const lastRun = await this.getOrCreateRun();\n\n try {\n this.validateIds(this.migrations);\n } catch (err) {\n lastRun.status = \"error\";\n lastRun.error = {\n message: err.message\n };\n await this.repository.saveRun(lastRun);\n return;\n }\n\n const [latestMigration] = await this.repository.listMigrations({ limit: 1 });\n\n this.logger.info(`Project version is %s.`, projectVersion);\n\n // Get current version, and coerce it to a valid SemVer.\n // With this, we can run migrations targeted for stable versions, released under a preid tag (e.g., `beta`).\n const currentVersion = coerce(projectVersion) + \"\";\n const startingId = latestMigration ? latestMigration.id : `${currentVersion}-000`;\n const lastId = `${currentVersion}-999`;\n\n // Create initial migration record.\n if (!latestMigration) {\n this.logger.info(\n `No migrations were ever executed. Creating initial migration record %s.`,\n startingId\n );\n await this.repository.logMigration({\n id: startingId,\n description: \"starting point for applicable migrations detection\",\n startedOn: getCurrentISOTime(),\n finishedOn: getCurrentISOTime(),\n reason: \"initial migration\"\n });\n } else {\n this.logger.info(`Latest migration ID is %s.`, latestMigration.id);\n }\n\n if (isApplicable) {\n this.logger.info(`Using custom \"isApplicable\" function.`);\n } else {\n this.logger.info(`Using migrations in the range of %s to %s.`, startingId, lastId);\n }\n\n const defaultIsApplicable: IsMigrationApplicable = mig => {\n return mig.getId() > startingId && mig.getId() <= lastId;\n };\n\n const isMigrationApplicable = isApplicable || defaultIsApplicable;\n\n const executableMigrations = this.migrations\n .filter(mig => {\n if (!isMigrationApplicable(mig)) {\n this.setRunItem(lastRun, {\n id: mig.getId(),\n status: \"not-applicable\"\n });\n\n return false;\n }\n return true;\n })\n .sort((a, b) => (a.getId() > b.getId() ? 1 : -1));\n\n this.logger.info(\n `Found %s applicable out of %s available migration(s).`,\n executableMigrations.length,\n this.migrations.length\n );\n\n // Are we're within the last 2 minutes of the execution time limit?\n const shouldCreateCheckpoint = () => {\n return this.timeLimiter() < 120000;\n };\n\n for (const migration of executableMigrations) {\n const runItem = this.getOrCreateRunItem(lastRun, migration);\n const checkpoint = await this.repository.getCheckpoint(migration.getId());\n const logger = getChildLogger(this.logger, migration);\n\n if (checkpoint) {\n this.logger.info(checkpoint, `Found checkpoint ${migration.getId()}.`);\n }\n\n const context: DataMigrationContext = {\n projectVersion,\n logger,\n checkpoint,\n runningOutOfTime: shouldCreateCheckpoint,\n createCheckpoint: async (data: unknown) => {\n await this.createCheckpoint(migration, data);\n },\n createCheckpointAndExit: async (data: unknown) => {\n await this.createCheckpoint(migration, data);\n // We throw an error to break out of the migration execution completely.\n throw new MigrationNotFinished();\n }\n };\n const shouldExecute = checkpoint ? true : await migration.shouldExecute(context);\n\n if (!shouldExecute) {\n this.logger.info(`Skipping migration %s.`, migration.getId());\n runItem.status = \"skipped\";\n\n await this.setRunItemAndSave(lastRun, runItem);\n\n await this.repository.logMigration({\n id: migration.getId(),\n description: migration.getDescription(),\n reason: \"skipped\"\n });\n\n continue;\n }\n\n try {\n lastRun.status = \"running\";\n runItem.status = \"running\";\n if (!runItem.startedOn) {\n runItem.startedOn = getCurrentISOTime();\n }\n await this.setRunItemAndSave(lastRun, runItem);\n this.logger.info(\n `Executing migration %s: %s`,\n migration.getId(),\n migration.getDescription()\n );\n await migration.execute(context);\n runItem.status = \"done\";\n } catch (err) {\n // If `MigrationNotFinished` was thrown, we will need to resume the migration.\n if (err instanceof MigrationNotFinished) {\n lastRun.status = \"pending\";\n runItem.status = \"pending\";\n return;\n }\n\n runItem.status = \"error\";\n lastRun.status = \"error\";\n lastRun.error = {\n name: err.name || \"Migration error\",\n message: err.message,\n stack: err.stack,\n data: err.data,\n code: err.code\n };\n this.logger.error(err, err.message);\n return;\n } finally {\n // We sum duration from the previous run with the current run.\n runItem.finishedOn = getCurrentISOTime();\n\n // Update run stats.\n await this.setRunItemAndSave(lastRun, runItem);\n\n this.logger.info(\n `Finished executing migration %s in %sms.`,\n migration.getId(),\n getRunItemDuration(runItem)\n );\n }\n\n await this.repository.logMigration({\n id: migration.getId(),\n description: migration.getDescription(),\n startedOn: runItem.startedOn,\n finishedOn: runItem.finishedOn,\n reason: \"executed\"\n });\n\n this.logger.info(`Deleting checkpoint ${migration.getId()}.`);\n await this.repository.deleteCheckpoint(migration.getId());\n }\n\n lastRun.status = \"done\";\n lastRun.finishedOn = getCurrentISOTime();\n await this.repository.saveRun(lastRun);\n\n this.logger.info(`Finished processing applicable migrations.`);\n }\n\n async getStatus(): Promise<MigrationStatus> {\n const lastRun = await this.repository.getLastRun();\n if (!lastRun) {\n throw new Error(`No migrations were ever executed!`);\n }\n\n // Since we don't store migration descriptions to DB, we need to fetch them from actual migration objects.\n const withDescriptions = lastRun.migrations.map(mig => {\n const dataMigration = this.migrations.find(dm => dm.getId() === mig.id);\n return {\n ...mig,\n description: dataMigration ? dataMigration.getDescription() : \"N/A\"\n };\n });\n\n return { ...lastRun, migrations: withDescriptions };\n }\n\n private validateIds(migrations: DataMigration[]) {\n const ids = new Set();\n for (const mig of migrations) {\n const id = mig.getId();\n if (id.endsWith(\"-000\")) {\n const error = new Error(`Migration ID must not end with \"000\": ${id}`);\n this.logger.error(error);\n throw error;\n }\n\n if (ids.has(id)) {\n const error = new Error(`Duplicate migration ID found: ${id}`);\n this.logger.error(error);\n throw error;\n }\n ids.add(id);\n }\n }\n\n private async createCheckpoint(migration: DataMigration, checkpoint: unknown) {\n this.logger.info(checkpoint, `Saving checkpoint ${migration.getId()}`);\n const execute = () => this.repository.createCheckpoint(migration.getId(), checkpoint);\n await executeWithRetry(execute);\n }\n\n private async getOrCreateRun() {\n const resolvedStatus: Array<MigrationRun[\"status\"]> = [\"done\", \"error\"];\n const unresolvedStatus: Array<MigrationRun[\"status\"]> = [\"init\", \"running\"];\n\n let lastRun = await this.repository.getLastRun();\n\n if (lastRun && unresolvedStatus.includes(lastRun.status)) {\n throw new MigrationInProgress(`Migration is already in progress (ID: ${lastRun.id})!`);\n }\n\n if (!lastRun || resolvedStatus.includes(lastRun.status)) {\n lastRun = {\n id: mdbid(),\n status: \"init\",\n startedOn: getCurrentISOTime(),\n finishedOn: \"\",\n migrations: []\n };\n\n await this.repository.saveRun(lastRun);\n }\n\n return lastRun;\n }\n\n private getOrCreateRunItem(run: MigrationRun, migration: DataMigration): MigrationRunItem {\n const existingItem = run.migrations.find(item => item.id === migration.getId());\n if (existingItem) {\n return {\n ...existingItem,\n status: \"running\"\n };\n }\n\n return {\n id: migration.getId(),\n status: \"running\"\n };\n }\n\n private setRunItem(run: MigrationRun, item: MigrationRunItem) {\n const index = run.migrations.findIndex(runItem => runItem.id === item.id);\n if (index < 0) {\n run.migrations.push(item);\n } else {\n run.migrations = [\n ...run.migrations.slice(0, index),\n item,\n ...run.migrations.slice(index + 1)\n ];\n }\n\n run.migrations = run.migrations.sort((a, b) => (a.id > b.id ? 1 : -1));\n }\n\n private async setRunItemAndSave(run: MigrationRun, item: MigrationRunItem) {\n this.setRunItem(run, item);\n await this.repository.saveRun(run);\n }\n}\n\nmakeInjectable(MigrationRunner, [\n inject(MigrationRepositorySymbol),\n inject(ExecutionTimeLimiterSymbol),\n inject(MigrationSymbol, { multi: true, optional: true }),\n inject(LoggerSymbol, { optional: true })\n]);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["coerce","inject","makeInjectable","executeWithRetry","mdbid","MigrationRepositorySymbol","LoggerSymbol","MigrationSymbol","ExecutionTimeLimiterSymbol","createPinoLogger","getChildLogger","getCurrentISOTime","Date","toISOString","getRunItemDuration","runItem","startedOn","finishedOn","getTime","shouldForceExecute","mig","key","getId","replace","process","env","shouldSkip","MigrationNotFinished","Error","MigrationInProgress","MigrationRunner","context","constructor","repository","timeLimiter","migrations","logger","setContext","execute","projectVersion","isApplicable","forceExecute","lastRun","getOrCreateRun","validateIds","err","status","error","message","saveRun","latestMigration","listMigrations","limit","info","currentVersion","startingId","id","lastId","logMigration","description","reason","defaultIsApplicable","isMigrationApplicable","printForceExecuteEnvVars","printSkipExecuteEnvVars","executableMigrations","filter","setRunItem","sort","a","b","length","shouldCreateCheckpoint","migration","getOrCreateRunItem","checkpoint","getCheckpoint","runningOutOfTime","createCheckpoint","data","createCheckpointAndExit","shouldExecute","setRunItemAndSave","getDescription","name","stack","code","deleteCheckpoint","getStatus","getLastRun","withDescriptions","map","dataMigration","find","dm","ids","Set","endsWith","has","add","resolvedStatus","unresolvedStatus","includes","run","existingItem","item","index","findIndex","push","slice","forceKeys","Object","keys","startsWith","skipKeys","multi","optional"],"sources":["MigrationRunner.ts"],"sourcesContent":["import { coerce } from \"semver\";\nimport type { Logger } from \"@webiny/logger\";\nimport { inject, makeInjectable } from \"@webiny/ioc\";\nimport { executeWithRetry, mdbid } from \"@webiny/utils\";\nimport {\n MigrationRepositorySymbol,\n LoggerSymbol,\n MigrationSymbol,\n ExecutionTimeLimiterSymbol\n} from \"./symbols.js\";\nimport { createPinoLogger, getChildLogger } from \"./createPinoLogger.js\";\nimport type {\n MigrationRepository,\n DataMigration,\n DataMigrationContext,\n ExecutionTimeLimiter,\n MigrationRun,\n MigrationStatus,\n MigrationRunItem\n} from \"~/types.js\";\n\nexport type IsMigrationApplicable = (migration: DataMigration) => boolean;\n\nconst getCurrentISOTime = () => {\n return new Date().toISOString();\n};\n\nconst getRunItemDuration = (runItem: MigrationRunItem) => {\n if (!runItem.startedOn || !runItem.finishedOn) {\n return \"N/A\";\n }\n\n return new Date(runItem.finishedOn).getTime() - new Date(runItem.startedOn).getTime();\n};\n\n/**\n * This allows us to force-execute a migration, even if it's not in the list of the applicable migrations.\n * Example: WEBINY_MIGRATION_FORCE_EXECUTE_5_35_0_006=true\n */\nconst shouldForceExecute = (mig: DataMigration) => {\n const key = `WEBINY_MIGRATION_FORCE_EXECUTE_${mig.getId().replace(/[\\.\\-]/g, \"_\")}`;\n\n return process.env[key] === \"true\";\n};\n\n/**\n * This allows us to always skip a migration.\n * Example: WEBINY_MIGRATION_SKIP_5_35_0_006=true\n */\nconst shouldSkip = (mig: DataMigration) => {\n const key = `WEBINY_MIGRATION_SKIP_${mig.getId().replace(/[\\.\\-]/g, \"_\")}`;\n\n return process.env[key] === \"true\";\n};\n\nclass MigrationNotFinished extends Error {}\nclass MigrationInProgress extends Error {}\n\nexport class MigrationRunner {\n private readonly logger: Logger;\n private readonly migrations: DataMigration[];\n private readonly repository: MigrationRepository;\n private readonly timeLimiter: ExecutionTimeLimiter;\n private context: Record<string, any> = {};\n\n constructor(\n repository: MigrationRepository,\n timeLimiter: ExecutionTimeLimiter,\n migrations: DataMigration[],\n logger: Logger | undefined\n ) {\n this.repository = repository;\n this.timeLimiter = timeLimiter;\n this.migrations = migrations || [];\n\n if (!logger) {\n logger = createPinoLogger();\n }\n this.logger = logger;\n }\n\n setContext(context: Record<string, any>) {\n this.context = context;\n }\n\n async execute(\n projectVersion: string,\n isApplicable?: IsMigrationApplicable,\n // Force execute applicable migrations.\n forceExecute = false\n ) {\n const lastRun = await this.getOrCreateRun();\n\n try {\n this.validateIds(this.migrations);\n } catch (err) {\n lastRun.status = \"error\";\n lastRun.error = {\n message: err.message\n };\n await this.repository.saveRun(lastRun);\n return;\n }\n\n const [latestMigration] = await this.repository.listMigrations({ limit: 1 });\n\n this.logger.info(`Project version is %s.`, projectVersion);\n\n // Get current version, and coerce it to a valid SemVer.\n // With this, we can run migrations targeted for stable versions, released under a preid tag (e.g., `beta`).\n const currentVersion = coerce(projectVersion) + \"\";\n const startingId = latestMigration ? latestMigration.id : `${currentVersion}-000`;\n const lastId = `${currentVersion}-999`;\n\n // Create initial migration record.\n if (!latestMigration) {\n this.logger.info(\n `No migrations were ever executed. Creating initial migration record %s.`,\n startingId\n );\n await this.repository.logMigration({\n id: startingId,\n description: \"starting point for applicable migrations detection\",\n startedOn: getCurrentISOTime(),\n finishedOn: getCurrentISOTime(),\n reason: \"initial migration\"\n });\n } else {\n this.logger.info(`Latest migration ID is %s.`, latestMigration.id);\n }\n\n if (isApplicable) {\n this.logger.info(`Using custom \"isApplicable\" function.`);\n } else {\n this.logger.info(`Using migrations in the range of %s to %s.`, startingId, lastId);\n }\n\n const defaultIsApplicable: IsMigrationApplicable = mig => {\n return mig.getId() > startingId && mig.getId() <= lastId;\n };\n\n const isMigrationApplicable = isApplicable || defaultIsApplicable;\n\n this.printForceExecuteEnvVars();\n this.printSkipExecuteEnvVars();\n\n if (forceExecute) {\n this.logger.info(\n `ALL APPLICABLE MIGRATIONS WILL BE FORCE-EXECUTED! (via --force flag)`\n );\n }\n\n const executableMigrations = this.migrations\n .filter(mig => {\n if (shouldSkip(mig)) {\n this.setRunItem(lastRun, {\n id: mig.getId(),\n status: \"skipped\"\n });\n\n return false;\n }\n\n if (shouldForceExecute(mig)) {\n return true;\n }\n\n if (!isMigrationApplicable(mig)) {\n this.setRunItem(lastRun, {\n id: mig.getId(),\n status: \"not-applicable\"\n });\n\n return false;\n }\n return true;\n })\n .sort((a, b) => (a.getId() > b.getId() ? 1 : -1));\n\n this.logger.info(\n `Found %s applicable out of %s available migration(s).`,\n executableMigrations.length,\n this.migrations.length\n );\n\n // Are we're within the last 2 minutes of the execution time limit?\n const shouldCreateCheckpoint = () => {\n return this.timeLimiter() < 120000;\n };\n\n //\n for (const migration of executableMigrations) {\n const runItem = this.getOrCreateRunItem(lastRun, migration);\n const checkpoint = await this.repository.getCheckpoint(migration.getId());\n const logger = getChildLogger(this.logger, migration);\n\n if (checkpoint) {\n this.logger.info(checkpoint, `Found checkpoint ${migration.getId()}.`);\n }\n\n const context: DataMigrationContext = {\n projectVersion,\n logger,\n checkpoint,\n forceExecute: forceExecute || shouldForceExecute(migration),\n runningOutOfTime: shouldCreateCheckpoint,\n createCheckpoint: async (data: unknown) => {\n await this.createCheckpoint(migration, data);\n },\n createCheckpointAndExit: async (data: unknown) => {\n await this.createCheckpoint(migration, data);\n // We throw an error to break out of the migration execution completely.\n throw new MigrationNotFinished();\n }\n };\n try {\n const shouldExecute =\n checkpoint || context.forceExecute\n ? true\n : await migration.shouldExecute(context);\n\n if (!shouldExecute) {\n this.logger.info(`Skipping migration %s.`, migration.getId());\n runItem.status = \"skipped\";\n\n await this.setRunItemAndSave(lastRun, runItem);\n\n await this.repository.logMigration({\n id: migration.getId(),\n description: migration.getDescription(),\n reason: \"skipped\"\n });\n\n continue;\n }\n\n lastRun.status = \"running\";\n runItem.status = \"running\";\n if (!runItem.startedOn) {\n runItem.startedOn = getCurrentISOTime();\n }\n await this.setRunItemAndSave(lastRun, runItem);\n this.logger.info(\n `Executing migration %s: %s`,\n migration.getId(),\n migration.getDescription()\n );\n await migration.execute(context);\n runItem.status = \"done\";\n } catch (err) {\n // If `MigrationNotFinished` was thrown, we will need to resume the migration.\n if (err instanceof MigrationNotFinished) {\n lastRun.status = \"pending\";\n runItem.status = \"pending\";\n return;\n }\n\n runItem.status = \"error\";\n lastRun.status = \"error\";\n lastRun.error = {\n name: err.name || \"Migration error\",\n message: err.message,\n stack: err.stack,\n data: err.data,\n code: err.code\n };\n this.logger.error(err, err.message);\n return;\n } finally {\n runItem.finishedOn = getCurrentISOTime();\n\n // Update run stats.\n await this.setRunItemAndSave(lastRun, runItem);\n\n if (runItem.status === \"pending\") {\n this.logger.info(\n `Pausing migration %s, awaiting continuation.`,\n migration.getId()\n );\n } else {\n this.logger.info(\n `Finished executing migration %s in %sms.`,\n migration.getId(),\n getRunItemDuration(runItem)\n );\n }\n }\n\n await this.repository.logMigration({\n id: migration.getId(),\n description: migration.getDescription(),\n startedOn: runItem.startedOn,\n finishedOn: runItem.finishedOn,\n reason: \"executed\"\n });\n\n this.logger.info(`Deleting checkpoint ${migration.getId()}.`);\n await this.repository.deleteCheckpoint(migration.getId());\n }\n\n lastRun.status = \"done\";\n lastRun.finishedOn = getCurrentISOTime();\n await this.repository.saveRun(lastRun);\n\n this.logger.info(`Finished processing applicable migrations.`);\n }\n\n async getStatus(): Promise<MigrationStatus> {\n const lastRun = await this.repository.getLastRun();\n if (!lastRun) {\n throw new Error(`No migrations were ever executed!`);\n }\n\n // Since we don't store migration descriptions to DB, we need to fetch them from actual migration objects.\n const withDescriptions = lastRun.migrations.map(mig => {\n const dataMigration = this.migrations.find(dm => dm.getId() === mig.id);\n return {\n ...mig,\n description: dataMigration ? dataMigration.getDescription() : \"N/A\"\n };\n });\n\n return { ...lastRun, migrations: withDescriptions };\n }\n\n private validateIds(migrations: DataMigration[]) {\n const ids = new Set();\n for (const mig of migrations) {\n const id = mig.getId();\n if (id.endsWith(\"-000\")) {\n const error = new Error(`Migration ID must not end with \"000\": ${id}`);\n this.logger.error(error);\n throw error;\n }\n\n if (ids.has(id)) {\n const error = new Error(`Duplicate migration ID found: ${id}`);\n this.logger.error(error);\n throw error;\n }\n ids.add(id);\n }\n }\n\n private async createCheckpoint(migration: DataMigration, checkpoint: unknown) {\n this.logger.info(checkpoint, `Saving checkpoint ${migration.getId()}`);\n const execute = () => this.repository.createCheckpoint(migration.getId(), checkpoint);\n await executeWithRetry(execute);\n }\n\n private async getOrCreateRun() {\n const resolvedStatus: Array<MigrationRun[\"status\"]> = [\"done\", \"error\"];\n const unresolvedStatus: Array<MigrationRun[\"status\"]> = [\"init\", \"running\"];\n\n let lastRun = await this.repository.getLastRun();\n\n if (lastRun && unresolvedStatus.includes(lastRun.status)) {\n throw new MigrationInProgress(`Migration is already in progress (ID: ${lastRun.id})!`);\n }\n\n if (!lastRun || resolvedStatus.includes(lastRun.status)) {\n lastRun = {\n id: mdbid(),\n status: \"init\",\n startedOn: getCurrentISOTime(),\n finishedOn: \"\",\n migrations: [],\n context: this.context\n };\n\n await this.repository.saveRun(lastRun);\n }\n\n return lastRun;\n }\n\n private getOrCreateRunItem(run: MigrationRun, migration: DataMigration): MigrationRunItem {\n const existingItem = run.migrations.find(item => item.id === migration.getId());\n if (existingItem) {\n return {\n ...existingItem,\n status: \"running\"\n };\n }\n\n return {\n id: migration.getId(),\n status: \"running\"\n };\n }\n\n private setRunItem(run: MigrationRun, item: MigrationRunItem) {\n const index = run.migrations.findIndex(runItem => runItem.id === item.id);\n if (index < 0) {\n run.migrations.push(item);\n } else {\n run.migrations = [\n ...run.migrations.slice(0, index),\n item,\n ...run.migrations.slice(index + 1)\n ];\n }\n\n run.migrations = run.migrations.sort((a, b) => (a.id > b.id ? 1 : -1));\n }\n\n private async setRunItemAndSave(run: MigrationRun, item: MigrationRunItem) {\n this.setRunItem(run, item);\n await this.repository.saveRun(run);\n }\n\n private printForceExecuteEnvVars() {\n const forceKeys = Object.keys(process.env).filter(key =>\n key.startsWith(\"WEBINY_MIGRATION_FORCE_EXECUTE_\")\n );\n\n if (!forceKeys.length) {\n this.logger.info(\n `No migrations are enforced via WEBINY_MIGRATION_FORCE_EXECUTE environment variable.`\n );\n\n return;\n }\n\n this.logger.info(`FORCED MIGRATIONS DETECTED!`);\n for (const key of forceKeys) {\n this.logger.info(`${key}=${process.env[key]}`);\n }\n }\n\n private printSkipExecuteEnvVars() {\n const skipKeys = Object.keys(process.env).filter(key =>\n key.startsWith(\"WEBINY_MIGRATION_SKIP_\")\n );\n\n if (!skipKeys.length) {\n this.logger.info(\n `No migrations are skipped via WEBINY_MIGRATION_SKIP environment variable.`\n );\n\n return;\n }\n\n this.logger.info(`SKIPPED MIGRATIONS DETECTED!`);\n for (const key of skipKeys) {\n this.logger.info(`${key}=${process.env[key]}`);\n }\n }\n}\n\nmakeInjectable(MigrationRunner, [\n inject(MigrationRepositorySymbol),\n inject(ExecutionTimeLimiterSymbol),\n inject(MigrationSymbol, { multi: true, optional: true }),\n inject(LoggerSymbol, { optional: true })\n]);\n"],"mappings":"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","ignoreList":[]}
|
package/README.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# @webiny/data-migration
|
|
2
2
|
|
|
3
|
-
[!
|
|
4
|
-
[
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
> [!NOTE]
|
|
4
|
+
> This package is part of the [Webiny](https://www.webiny.com) monorepo.
|
|
5
|
+
> It’s **included in every Webiny project by default** and is not meant to be used as a standalone package.
|
|
6
|
+
|
|
7
|
+
📘 **Documentation:** [https://www.webiny.com/docs](https://www.webiny.com/docs)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
_This README file is automatically generated during the publish process._
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { MigrationRunnerResult, MigrationRunReporter } from "../cli/index.js";
|
|
2
|
+
import type { LogReporter } from "../cli/index.js";
|
|
3
|
+
import { UiService } from "@webiny/project/abstractions/index.js";
|
|
4
|
+
export interface CliMigrationRunReporterDi {
|
|
5
|
+
uiService: UiService.Interface;
|
|
6
|
+
}
|
|
7
|
+
export declare class CliMigrationRunReporter implements MigrationRunReporter {
|
|
8
|
+
private di;
|
|
9
|
+
private logReporter;
|
|
10
|
+
constructor(logReporter: LogReporter, di: CliMigrationRunReporterDi);
|
|
11
|
+
report(result: MigrationRunnerResult): Promise<void>;
|
|
12
|
+
private makeEven;
|
|
13
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import center from "center-align";
|
|
2
|
+
export class CliMigrationRunReporter {
|
|
3
|
+
constructor(logReporter, di) {
|
|
4
|
+
this.logReporter = logReporter;
|
|
5
|
+
this.di = di;
|
|
6
|
+
}
|
|
7
|
+
report(result) {
|
|
8
|
+
const {
|
|
9
|
+
uiService: ui
|
|
10
|
+
} = this.di;
|
|
11
|
+
result.onSuccess(data => {
|
|
12
|
+
const functionName = result.getFunctionName().split(":").pop();
|
|
13
|
+
process.stdout.write("\n");
|
|
14
|
+
ui.success(`Data migration Lambda %s executed successfully!`, functionName);
|
|
15
|
+
const {
|
|
16
|
+
migrations,
|
|
17
|
+
...run
|
|
18
|
+
} = data;
|
|
19
|
+
if (!migrations.length) {
|
|
20
|
+
ui.info(`No applicable migrations were found!`);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const maxLength = Math.max(...migrations.map(mig => mig.status.length)) + 2;
|
|
24
|
+
ui.info(`Migration run: %s`, run.id);
|
|
25
|
+
ui.info(`Status: %s`, run.status);
|
|
26
|
+
ui.info(`Started on: %s`, run.startedOn);
|
|
27
|
+
if (run.status === "done") {
|
|
28
|
+
ui.info(`Finished on: %s`, run.finishedOn);
|
|
29
|
+
}
|
|
30
|
+
for (const migration of migrations) {
|
|
31
|
+
ui.info(...[`[%s] %s: ${migration.description}`, center(this.makeEven(migration.status), maxLength), migration.id]);
|
|
32
|
+
}
|
|
33
|
+
this.logReporter.printLogStreamLinks();
|
|
34
|
+
});
|
|
35
|
+
result.onError(error => {
|
|
36
|
+
ui.error(error.message);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Process the result!
|
|
40
|
+
return result.process();
|
|
41
|
+
}
|
|
42
|
+
makeEven(str) {
|
|
43
|
+
if (str.length % 2 > 0) {
|
|
44
|
+
return str + " ";
|
|
45
|
+
}
|
|
46
|
+
return str;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
//# sourceMappingURL=CliMigrationRunReporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["center","CliMigrationRunReporter","constructor","logReporter","di","report","result","uiService","ui","onSuccess","data","functionName","getFunctionName","split","pop","process","stdout","write","success","migrations","run","length","info","maxLength","Math","max","map","mig","status","id","startedOn","finishedOn","migration","description","makeEven","printLogStreamLinks","onError","error","message","str"],"sources":["CliMigrationRunReporter.ts"],"sourcesContent":["import type { MigrationRunnerResult, MigrationRunReporter } from \"~/cli/index.js\";\nimport center from \"center-align\";\nimport type { LogReporter } from \"~/cli/index.js\";\nimport { UiService } from \"@webiny/project/abstractions/index.js\";\n\nexport interface CliMigrationRunReporterDi {\n uiService: UiService.Interface;\n}\n\nexport class CliMigrationRunReporter implements MigrationRunReporter {\n private di: {\n uiService: UiService.Interface;\n };\n private logReporter: LogReporter;\n\n constructor(logReporter: LogReporter, di: CliMigrationRunReporterDi) {\n this.logReporter = logReporter;\n this.di = di;\n }\n\n report(result: MigrationRunnerResult): Promise<void> {\n const { uiService: ui } = this.di;\n\n result.onSuccess(data => {\n const functionName = result.getFunctionName().split(\":\").pop();\n process.stdout.write(\"\\n\");\n ui.success(`Data migration Lambda %s executed successfully!`, functionName);\n\n const { migrations, ...run } = data;\n if (!migrations.length) {\n ui.info(`No applicable migrations were found!`);\n return;\n }\n\n const maxLength = Math.max(...migrations.map(mig => mig.status.length)) + 2;\n ui.info(`Migration run: %s`, run.id);\n ui.info(`Status: %s`, run.status);\n ui.info(`Started on: %s`, run.startedOn);\n if (run.status === \"done\") {\n ui.info(`Finished on: %s`, run.finishedOn);\n }\n for (const migration of migrations) {\n ui.info(\n ...[\n `[%s] %s: ${migration.description}`,\n center(this.makeEven(migration.status), maxLength),\n migration.id\n ]\n );\n }\n\n this.logReporter.printLogStreamLinks();\n });\n\n result.onError(error => {\n ui.error(error.message);\n });\n\n // Process the result!\n return result.process();\n }\n\n private makeEven(str: string) {\n if (str.length % 2 > 0) {\n return str + \" \";\n }\n return str;\n }\n}\n"],"mappings":"AACA,OAAOA,MAAM,MAAM,cAAc;AAQjC,OAAO,MAAMC,uBAAuB,CAAiC;EAMjEC,WAAWA,CAACC,WAAwB,EAAEC,EAA6B,EAAE;IACjE,IAAI,CAACD,WAAW,GAAGA,WAAW;IAC9B,IAAI,CAACC,EAAE,GAAGA,EAAE;EAChB;EAEAC,MAAMA,CAACC,MAA6B,EAAiB;IACjD,MAAM;MAAEC,SAAS,EAAEC;IAAG,CAAC,GAAG,IAAI,CAACJ,EAAE;IAEjCE,MAAM,CAACG,SAAS,CAACC,IAAI,IAAI;MACrB,MAAMC,YAAY,GAAGL,MAAM,CAACM,eAAe,CAAC,CAAC,CAACC,KAAK,CAAC,GAAG,CAAC,CAACC,GAAG,CAAC,CAAC;MAC9DC,OAAO,CAACC,MAAM,CAACC,KAAK,CAAC,IAAI,CAAC;MAC1BT,EAAE,CAACU,OAAO,CAAC,iDAAiD,EAAEP,YAAY,CAAC;MAE3E,MAAM;QAAEQ,UAAU;QAAE,GAAGC;MAAI,CAAC,GAAGV,IAAI;MACnC,IAAI,CAACS,UAAU,CAACE,MAAM,EAAE;QACpBb,EAAE,CAACc,IAAI,CAAC,sCAAsC,CAAC;QAC/C;MACJ;MAEA,MAAMC,SAAS,GAAGC,IAAI,CAACC,GAAG,CAAC,GAAGN,UAAU,CAACO,GAAG,CAACC,GAAG,IAAIA,GAAG,CAACC,MAAM,CAACP,MAAM,CAAC,CAAC,GAAG,CAAC;MAC3Eb,EAAE,CAACc,IAAI,CAAC,mBAAmB,EAAEF,GAAG,CAACS,EAAE,CAAC;MACpCrB,EAAE,CAACc,IAAI,CAAC,YAAY,EAAEF,GAAG,CAACQ,MAAM,CAAC;MACjCpB,EAAE,CAACc,IAAI,CAAC,gBAAgB,EAAEF,GAAG,CAACU,SAAS,CAAC;MACxC,IAAIV,GAAG,CAACQ,MAAM,KAAK,MAAM,EAAE;QACvBpB,EAAE,CAACc,IAAI,CAAC,iBAAiB,EAAEF,GAAG,CAACW,UAAU,CAAC;MAC9C;MACA,KAAK,MAAMC,SAAS,IAAIb,UAAU,EAAE;QAChCX,EAAE,CAACc,IAAI,CACH,GAAG,CACC,YAAYU,SAAS,CAACC,WAAW,EAAE,EACnCjC,MAAM,CAAC,IAAI,CAACkC,QAAQ,CAACF,SAAS,CAACJ,MAAM,CAAC,EAAEL,SAAS,CAAC,EAClDS,SAAS,CAACH,EAAE,CAEpB,CAAC;MACL;MAEA,IAAI,CAAC1B,WAAW,CAACgC,mBAAmB,CAAC,CAAC;IAC1C,CAAC,CAAC;IAEF7B,MAAM,CAAC8B,OAAO,CAACC,KAAK,IAAI;MACpB7B,EAAE,CAAC6B,KAAK,CAACA,KAAK,CAACC,OAAO,CAAC;IAC3B,CAAC,CAAC;;IAEF;IACA,OAAOhC,MAAM,CAACS,OAAO,CAAC,CAAC;EAC3B;EAEQmB,QAAQA,CAACK,GAAW,EAAE;IAC1B,IAAIA,GAAG,CAAClB,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE;MACpB,OAAOkB,GAAG,GAAG,GAAG;IACpB;IACA,OAAOA,GAAG;EACd;AACJ","ignoreList":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { MigrationStatusReporter } from "../cli/MigrationStatusReporter.js";
|
|
2
|
+
import type { MigrationStatus } from "../types.js";
|
|
3
|
+
import type { LogReporter } from "../cli/LogReporter.js";
|
|
4
|
+
export declare class InteractiveCliStatusReporter implements MigrationStatusReporter {
|
|
5
|
+
private logReporter;
|
|
6
|
+
private firstCall;
|
|
7
|
+
constructor(logReporter: LogReporter);
|
|
8
|
+
report(migrationStatus: MigrationStatus): Promise<void>;
|
|
9
|
+
private clearLine;
|
|
10
|
+
private getDuration;
|
|
11
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import readline from "readline";
|
|
2
|
+
export class InteractiveCliStatusReporter {
|
|
3
|
+
firstCall = true;
|
|
4
|
+
constructor(logReporter) {
|
|
5
|
+
this.logReporter = logReporter;
|
|
6
|
+
console.log(`Using "InteractiveCliStatusReporter".`);
|
|
7
|
+
}
|
|
8
|
+
async report(migrationStatus) {
|
|
9
|
+
const {
|
|
10
|
+
status,
|
|
11
|
+
migrations,
|
|
12
|
+
context
|
|
13
|
+
} = migrationStatus;
|
|
14
|
+
this.clearLine();
|
|
15
|
+
const currentLogStreamName = context?.logStreamName;
|
|
16
|
+
if (currentLogStreamName) {
|
|
17
|
+
this.logReporter.initializeStream(currentLogStreamName);
|
|
18
|
+
if (this.firstCall) {
|
|
19
|
+
this.logReporter.printLogStreamLinks();
|
|
20
|
+
process.stdout.write(`\n---------- MIGRATION LOGS START ----------\n\n`);
|
|
21
|
+
}
|
|
22
|
+
await this.logReporter.printLogs(currentLogStreamName);
|
|
23
|
+
}
|
|
24
|
+
if (status === "running") {
|
|
25
|
+
const currentMigration = migrations.find(mig => mig.status === "running");
|
|
26
|
+
if (currentMigration) {
|
|
27
|
+
const duration = this.getDuration(String(currentMigration.startedOn));
|
|
28
|
+
process.stdout.write(`Running data migration ${currentMigration.id} (${duration})...`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (status === "init") {
|
|
32
|
+
process.stdout.write(`Checking data migrations...`);
|
|
33
|
+
}
|
|
34
|
+
if (["done", "error"].includes(status)) {
|
|
35
|
+
this.clearLine();
|
|
36
|
+
process.stdout.write(`Migration run finished, waiting for latest logs...`);
|
|
37
|
+
|
|
38
|
+
// We want to give AWS some time for the latest log events to become available.
|
|
39
|
+
await new Promise(resolve => {
|
|
40
|
+
setTimeout(resolve, 8000);
|
|
41
|
+
});
|
|
42
|
+
if (currentLogStreamName) {
|
|
43
|
+
this.clearLine();
|
|
44
|
+
await this.logReporter.printLogs(currentLogStreamName);
|
|
45
|
+
process.stdout.write(`\n---------- MIGRATION LOGS END ----------\n`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
this.firstCall = false;
|
|
49
|
+
}
|
|
50
|
+
clearLine() {
|
|
51
|
+
readline.clearLine(process.stdout, 0);
|
|
52
|
+
readline.cursorTo(process.stdout, 0);
|
|
53
|
+
}
|
|
54
|
+
getDuration(since) {
|
|
55
|
+
const ms = new Date().getTime() - new Date(since).getTime();
|
|
56
|
+
let seconds = Math.floor(ms / 1000);
|
|
57
|
+
let minutes = undefined;
|
|
58
|
+
if (seconds > 60) {
|
|
59
|
+
minutes = Math.floor(seconds / 60);
|
|
60
|
+
seconds = Math.floor(seconds % 60);
|
|
61
|
+
}
|
|
62
|
+
return minutes ? `${minutes}m ${seconds}s` : `${seconds}s`;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
//# sourceMappingURL=InteractiveCliStatusReporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["readline","InteractiveCliStatusReporter","firstCall","constructor","logReporter","console","log","report","migrationStatus","status","migrations","context","clearLine","currentLogStreamName","logStreamName","initializeStream","printLogStreamLinks","process","stdout","write","printLogs","currentMigration","find","mig","duration","getDuration","String","startedOn","id","includes","Promise","resolve","setTimeout","cursorTo","since","ms","Date","getTime","seconds","Math","floor","minutes","undefined"],"sources":["InteractiveCliStatusReporter.ts"],"sourcesContent":["import readline from \"readline\";\nimport type { MigrationStatusReporter } from \"~/cli/MigrationStatusReporter.js\";\nimport type { MigrationStatus } from \"~/types.js\";\nimport type { LogReporter } from \"~/cli/LogReporter.js\";\n\nexport class InteractiveCliStatusReporter implements MigrationStatusReporter {\n private logReporter: LogReporter;\n private firstCall = true;\n\n constructor(logReporter: LogReporter) {\n this.logReporter = logReporter;\n console.log(`Using \"InteractiveCliStatusReporter\".`);\n }\n\n async report(migrationStatus: MigrationStatus) {\n const { status, migrations, context } = migrationStatus;\n this.clearLine();\n\n const currentLogStreamName = context?.logStreamName;\n if (currentLogStreamName) {\n this.logReporter.initializeStream(currentLogStreamName);\n if (this.firstCall) {\n this.logReporter.printLogStreamLinks();\n process.stdout.write(`\\n---------- MIGRATION LOGS START ----------\\n\\n`);\n }\n await this.logReporter.printLogs(currentLogStreamName);\n }\n\n if (status === \"running\") {\n const currentMigration = migrations.find(mig => mig.status === \"running\");\n if (currentMigration) {\n const duration = this.getDuration(String(currentMigration.startedOn));\n process.stdout.write(\n `Running data migration ${currentMigration.id} (${duration})...`\n );\n }\n }\n\n if (status === \"init\") {\n process.stdout.write(`Checking data migrations...`);\n }\n\n if ([\"done\", \"error\"].includes(status)) {\n this.clearLine();\n process.stdout.write(`Migration run finished, waiting for latest logs...`);\n\n // We want to give AWS some time for the latest log events to become available.\n await new Promise(resolve => {\n setTimeout(resolve, 8000);\n });\n\n if (currentLogStreamName) {\n this.clearLine();\n await this.logReporter.printLogs(currentLogStreamName);\n process.stdout.write(`\\n---------- MIGRATION LOGS END ----------\\n`);\n }\n }\n\n this.firstCall = false;\n }\n\n private clearLine() {\n readline.clearLine(process.stdout, 0);\n readline.cursorTo(process.stdout, 0);\n }\n\n private getDuration(since: string) {\n const ms = new Date().getTime() - new Date(since).getTime();\n let seconds = Math.floor(ms / 1000);\n let minutes = undefined;\n if (seconds > 60) {\n minutes = Math.floor(seconds / 60);\n seconds = Math.floor(seconds % 60);\n }\n\n return minutes ? `${minutes}m ${seconds}s` : `${seconds}s`;\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { LogStream } from "./LogStream.js";
|
|
2
|
+
export declare class LogReporter {
|
|
3
|
+
private readonly logGroupName;
|
|
4
|
+
private readonly logsCreatedSince;
|
|
5
|
+
private readonly logStreams;
|
|
6
|
+
constructor(functionName: string);
|
|
7
|
+
printLogs(logStreamName: string): Promise<void>;
|
|
8
|
+
printLogStreamLinks(): void;
|
|
9
|
+
initializeStream(name: string): LogStream;
|
|
10
|
+
}
|