@balena/pinejs 14.44.0-linear-runtime-migrator-9d426d29f2b01ef0425c72333c2c691976fdc219 → 15.0.0-delete-state-default-user-permissions-57ce3dc6141cd1e8159f4c34da29d1fb113242c6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. package/.versionbot/CHANGELOG.yml +126 -31
  2. package/CHANGELOG.md +63 -5
  3. package/VERSION +1 -1
  4. package/docs/Migrations.md +1 -101
  5. package/out/bin/utils.d.ts +2 -2
  6. package/out/config-loader/config-loader.d.ts +2 -2
  7. package/out/config-loader/config-loader.js +20 -29
  8. package/out/config-loader/config-loader.js.map +1 -1
  9. package/out/config-loader/env.d.ts +0 -3
  10. package/out/config-loader/env.js +0 -3
  11. package/out/config-loader/env.js.map +1 -1
  12. package/out/data-server/sbvr-server.d.ts +1 -3
  13. package/out/data-server/sbvr-server.js +1 -4
  14. package/out/data-server/sbvr-server.js.map +1 -1
  15. package/out/migrator/migrations.sbvr +0 -66
  16. package/out/migrator/migrator.d.ts +17 -0
  17. package/out/migrator/migrator.js +185 -0
  18. package/out/migrator/migrator.js.map +1 -0
  19. package/out/pinejs-session-store/pinejs-session-store.js +1 -4
  20. package/out/pinejs-session-store/pinejs-session-store.js.map +1 -1
  21. package/out/sbvr-api/abstract-sql.d.ts +1 -1
  22. package/out/sbvr-api/permissions.d.ts +5 -5
  23. package/out/sbvr-api/permissions.js +3 -6
  24. package/out/sbvr-api/permissions.js.map +1 -1
  25. package/out/sbvr-api/sbvr-utils.d.ts +4 -6
  26. package/out/sbvr-api/sbvr-utils.js +5 -17
  27. package/out/sbvr-api/sbvr-utils.js.map +1 -1
  28. package/out/server-glue/module.d.ts +3 -3
  29. package/out/server-glue/module.js +1 -2
  30. package/out/server-glue/module.js.map +1 -1
  31. package/package.json +7 -7
  32. package/src/config-loader/config-loader.ts +27 -62
  33. package/src/config-loader/env.ts +0 -3
  34. package/src/data-server/sbvr-server.js +1 -4
  35. package/src/migrator/migrations.sbvr +0 -66
  36. package/src/migrator/migrator.ts +278 -0
  37. package/src/pinejs-session-store/pinejs-session-store.ts +1 -4
  38. package/src/sbvr-api/permissions.ts +3 -6
  39. package/src/sbvr-api/sbvr-utils.ts +4 -22
  40. package/src/server-glue/module.ts +2 -3
  41. package/out/migrator/async.d.ts +0 -6
  42. package/out/migrator/async.js +0 -154
  43. package/out/migrator/async.js.map +0 -1
  44. package/out/migrator/sync.d.ts +0 -9
  45. package/out/migrator/sync.js +0 -117
  46. package/out/migrator/sync.js.map +0 -1
  47. package/out/migrator/utils.d.ts +0 -51
  48. package/out/migrator/utils.js +0 -187
  49. package/out/migrator/utils.js.map +0 -1
  50. package/src/migrator/async.ts +0 -273
  51. package/src/migrator/sync.ts +0 -167
  52. package/src/migrator/utils.ts +0 -293
@@ -0,0 +1,278 @@
1
+ import type { Tx } from '../database-layer/db';
2
+ import type { Resolvable } from '../sbvr-api/common-types';
3
+ import type { Config, Model } from '../config-loader/config-loader';
4
+
5
+ import { Engines } from '@balena/abstract-sql-compiler';
6
+ import * as _ from 'lodash';
7
+ import { TypedError } from 'typed-error';
8
+ import { migrator as migratorEnv } from '../config-loader/env';
9
+ import * as sbvrUtils from '../sbvr-api/sbvr-utils';
10
+ import { delay } from '../sbvr-api/control-flow';
11
+
12
+ // tslint:disable-next-line:no-var-requires
13
+ const modelText: string = require('./migrations.sbvr');
14
+
15
+ type ApiRootModel = Model & { apiRoot: string };
16
+
17
+ type SbvrUtils = typeof sbvrUtils;
18
+
19
+ type MigrationTuple = [string, Migration];
20
+
21
+ export type MigrationFn = (tx: Tx, sbvrUtils: SbvrUtils) => Resolvable<void>;
22
+
23
+ export type Migration = string | MigrationFn;
24
+
25
+ export class MigrationError extends TypedError {}
26
+
27
+ // Tagged template to convert binds from `?` format to the necessary output format,
28
+ // eg `$1`/`$2`/etc for postgres
29
+ const binds = (strings: TemplateStringsArray, ...bindNums: number[]) =>
30
+ strings
31
+ .map((str, i) => {
32
+ if (i === bindNums.length) {
33
+ return str;
34
+ }
35
+ if (i + 1 !== bindNums[i]) {
36
+ throw new SyntaxError('Migration sql binds must be sequential');
37
+ }
38
+ if (sbvrUtils.db.engine === Engines.postgres) {
39
+ return str + `$${bindNums[i]}`;
40
+ }
41
+ return str + `?`;
42
+ })
43
+ .join('');
44
+
45
+ export const postRun = async (tx: Tx, model: ApiRootModel): Promise<void> => {
46
+ const { initSql } = model;
47
+ if (initSql == null) {
48
+ return;
49
+ }
50
+
51
+ const modelName = model.apiRoot;
52
+
53
+ const exists = await checkModelAlreadyExists(tx, modelName);
54
+ if (!exists) {
55
+ (sbvrUtils.api.migrations?.logger.info ?? console.info)(
56
+ 'First time executing, running init script',
57
+ );
58
+ await lockMigrations(tx, modelName, async () => {
59
+ await tx.executeSql(initSql);
60
+ });
61
+ }
62
+ };
63
+
64
+ export const run = async (tx: Tx, model: ApiRootModel): Promise<void> => {
65
+ const { migrations } = model;
66
+ if (migrations == null || _.isEmpty(migrations)) {
67
+ return;
68
+ }
69
+
70
+ const modelName = model.apiRoot;
71
+
72
+ // migrations only run if the model has been executed before,
73
+ // to make changes that can't be automatically applied
74
+ const exists = await checkModelAlreadyExists(tx, modelName);
75
+ if (!exists) {
76
+ (sbvrUtils.api.migrations?.logger.info ?? console.info)(
77
+ 'First time model has executed, skipping migrations',
78
+ );
79
+
80
+ return await setExecutedMigrations(tx, modelName, Object.keys(migrations));
81
+ }
82
+ await lockMigrations(tx, modelName, async () => {
83
+ const executedMigrations = await getExecutedMigrations(tx, modelName);
84
+ const pendingMigrations = filterAndSortPendingMigrations(
85
+ migrations,
86
+ executedMigrations,
87
+ );
88
+ if (pendingMigrations.length === 0) {
89
+ return;
90
+ }
91
+
92
+ const newlyExecutedMigrations = await executeMigrations(
93
+ tx,
94
+ pendingMigrations,
95
+ );
96
+ await setExecutedMigrations(tx, modelName, [
97
+ ...executedMigrations,
98
+ ...newlyExecutedMigrations,
99
+ ]);
100
+ });
101
+ };
102
+
103
+ const checkModelAlreadyExists = async (
104
+ tx: Tx,
105
+ modelName: string,
106
+ ): Promise<boolean> => {
107
+ const result = await tx.tableList("name = 'migration'");
108
+ if (result.rows.length === 0) {
109
+ return false;
110
+ }
111
+ const { rows } = await tx.executeSql(
112
+ binds`
113
+ SELECT 1
114
+ FROM "model"
115
+ WHERE "model"."is of-vocabulary" = ${1}
116
+ LIMIT 1`,
117
+ [modelName],
118
+ );
119
+
120
+ return rows.length > 0;
121
+ };
122
+
123
+ const getExecutedMigrations = async (
124
+ tx: Tx,
125
+ modelName: string,
126
+ ): Promise<string[]> => {
127
+ const { rows } = await tx.executeSql(
128
+ binds`
129
+ SELECT "migration"."executed migrations" AS "executed_migrations"
130
+ FROM "migration"
131
+ WHERE "migration"."model name" = ${1}`,
132
+ [modelName],
133
+ );
134
+
135
+ const data = rows[0];
136
+ if (data == null) {
137
+ return [];
138
+ }
139
+
140
+ return JSON.parse(data.executed_migrations) as string[];
141
+ };
142
+
143
+ const setExecutedMigrations = async (
144
+ tx: Tx,
145
+ modelName: string,
146
+ executedMigrations: string[],
147
+ ): Promise<void> => {
148
+ const stringifiedMigrations = JSON.stringify(executedMigrations);
149
+
150
+ const result = await tx.tableList("name = 'migration'");
151
+ if (result.rows.length === 0) {
152
+ return;
153
+ }
154
+
155
+ const { rowsAffected } = await tx.executeSql(
156
+ binds`
157
+ UPDATE "migration"
158
+ SET "model name" = ${1},
159
+ "executed migrations" = ${2}
160
+ WHERE "migration"."model name" = ${3}`,
161
+ [modelName, stringifiedMigrations, modelName],
162
+ );
163
+
164
+ if (rowsAffected === 0) {
165
+ await tx.executeSql(
166
+ binds`
167
+ INSERT INTO "migration" ("model name", "executed migrations")
168
+ VALUES (${1}, ${2})`,
169
+ [modelName, stringifiedMigrations],
170
+ );
171
+ }
172
+ };
173
+
174
+ // turns {"key1": migration, "key3": migration, "key2": migration}
175
+ // into [["key1", migration], ["key2", migration], ["key3", migration]]
176
+ const filterAndSortPendingMigrations = (
177
+ migrations: NonNullable<Model['migrations']>,
178
+ executedMigrations: string[],
179
+ ): MigrationTuple[] =>
180
+ (_(migrations).omit(executedMigrations) as _.Object<typeof migrations>)
181
+ .toPairs()
182
+ .sortBy(([migrationKey]) => migrationKey)
183
+ .value();
184
+
185
+ const lockMigrations = async <T>(
186
+ tx: Tx,
187
+ modelName: string,
188
+ fn: () => Promise<T>,
189
+ ): Promise<T> => {
190
+ try {
191
+ await tx.executeSql(
192
+ binds`
193
+ DELETE FROM "migration lock"
194
+ WHERE "model name" = ${1}
195
+ AND "created at" < ${2}`,
196
+ [modelName, new Date(Date.now() - migratorEnv.lockTimeout)],
197
+ );
198
+ await tx.executeSql(
199
+ binds`
200
+ INSERT INTO "migration lock" ("model name")
201
+ VALUES (${1})`,
202
+ [modelName],
203
+ );
204
+ } catch (err) {
205
+ await delay(migratorEnv.lockFailDelay);
206
+ throw err;
207
+ }
208
+ try {
209
+ return await fn();
210
+ } finally {
211
+ try {
212
+ await tx.executeSql(
213
+ binds`
214
+ DELETE FROM "migration lock"
215
+ WHERE "model name" = ${1}`,
216
+ [modelName],
217
+ );
218
+ } catch {
219
+ // We ignore errors here as it's mostly likely caused by the migration failing and
220
+ // rolling back the transaction, and if we rethrow here we'll overwrite the real error
221
+ // making it much harder for users to see what went wrong and fix it
222
+ }
223
+ }
224
+ };
225
+
226
+ const executeMigrations = async (
227
+ tx: Tx,
228
+ migrations: MigrationTuple[] = [],
229
+ ): Promise<string[]> => {
230
+ try {
231
+ for (const migration of migrations) {
232
+ await executeMigration(tx, migration);
233
+ }
234
+ } catch (err) {
235
+ (sbvrUtils.api.migrations?.logger.error ?? console.error)(
236
+ 'Error while executing migrations, rolled back',
237
+ );
238
+ throw new MigrationError(err);
239
+ }
240
+ return migrations.map(([migrationKey]) => migrationKey); // return migration keys
241
+ };
242
+
243
+ const executeMigration = async (
244
+ tx: Tx,
245
+ [key, migration]: MigrationTuple,
246
+ ): Promise<void> => {
247
+ (sbvrUtils.api.migrations?.logger.info ?? console.info)(
248
+ `Running migration ${JSON.stringify(key)}`,
249
+ );
250
+
251
+ if (typeof migration === 'function') {
252
+ await migration(tx, sbvrUtils);
253
+ } else if (typeof migration === 'string') {
254
+ await tx.executeSql(migration);
255
+ } else {
256
+ throw new MigrationError(`Invalid migration type: ${typeof migration}`);
257
+ }
258
+ };
259
+
260
+ export const config: Config = {
261
+ models: [
262
+ {
263
+ modelName: 'migrations',
264
+ apiRoot: 'migrations',
265
+ modelText,
266
+ migrations: {
267
+ '11.0.0-modified-at': `
268
+ ALTER TABLE "migration"
269
+ ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
270
+ `,
271
+ '11.0.1-modified-at': `
272
+ ALTER TABLE "migration lock"
273
+ ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
274
+ `,
275
+ },
276
+ },
277
+ ],
278
+ };
@@ -4,7 +4,6 @@ import type { AnyObject } from '../sbvr-api/common-types';
4
4
  import { Store } from 'express-session';
5
5
  import * as permissions from '../sbvr-api/permissions';
6
6
  import { api } from '../sbvr-api/sbvr-utils';
7
- import { defaultMigrationCategory } from '../migrator/utils';
8
7
 
9
8
  export { Store };
10
9
 
@@ -170,12 +169,10 @@ export class PinejsSessionStore extends Store {
170
169
  error: true,
171
170
  },
172
171
  migrations: {
173
- [defaultMigrationCategory]: {
174
- '11.0.0-modified-at': `
172
+ '11.0.0-modified-at': `
175
173
  ALTER TABLE "session"
176
174
  ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
177
175
  `,
178
- },
179
176
  },
180
177
  },
181
178
  ],
@@ -50,7 +50,6 @@ import {
50
50
  ODataRequest,
51
51
  } from './uri-parser';
52
52
  import memoizeWeak = require('memoizee/weak');
53
- import { defaultMigrationCategory } from '../migrator/utils';
54
53
 
55
54
  // tslint:disable-next-line:no-var-requires
56
55
  const userModel: string = require('./user.sbvr');
@@ -1680,8 +1679,7 @@ export const config = {
1680
1679
  modelText: userModel,
1681
1680
  customServerCode: exports,
1682
1681
  migrations: {
1683
- [defaultMigrationCategory]: {
1684
- '11.0.0-modified-at': `
1682
+ '11.0.0-modified-at': `
1685
1683
  ALTER TABLE "actor"
1686
1684
  ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1687
1685
 
@@ -1705,15 +1703,14 @@ export const config = {
1705
1703
  ALTER TABLE "user-has-permission"
1706
1704
  ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1707
1705
  `,
1708
- '11.0.1-modified-at': `
1706
+ '11.0.1-modified-at': `
1709
1707
  ALTER TABLE "role-has-permission"
1710
1708
  ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1711
1709
  `,
1712
- '14.42.0-api-key-expiry-date': `
1710
+ '14.42.0-api-key-expiry-date': `
1713
1711
  ALTER TABLE "api key"
1714
1712
  ADD COLUMN IF NOT EXISTS "expiry date" TIMESTAMP NULL;
1715
1713
  `,
1716
- },
1717
1714
  },
1718
1715
  },
1719
1716
  ] as sbvrUtils.ExecutableModel[],
@@ -33,9 +33,7 @@ import { PinejsClientCore, PromiseResultTypes } from 'pinejs-client-core';
33
33
 
34
34
  import { ExtendedSBVRParser } from '../extended-sbvr-parser/extended-sbvr-parser';
35
35
 
36
- import { defaultMigrationCategory } from '../migrator/utils';
37
- import * as asyncMigrator from '../migrator/async';
38
- import * as syncMigrator from '../migrator/sync';
36
+ import * as migrator from '../migrator/migrator';
39
37
  import { generateODataMetadata } from '../odata-metadata/odata-metadata-generator';
40
38
 
41
39
  // tslint:disable-next-line:no-var-requires
@@ -432,20 +430,6 @@ export const generateModels = (
432
430
  return { vocab, se, lf, abstractSql, sql, odataMetadata };
433
431
  };
434
432
 
435
- export const executeAsyncModelMigration = (
436
- model: ExecutableModel,
437
- ): Promise<void> => executeAsyncModelMigrations([model]);
438
-
439
- export const executeAsyncModelMigrations = async (
440
- execModels: ExecutableModel[],
441
- ): Promise<void> => {
442
- await Promise.all(
443
- execModels.map(async (model) => {
444
- await asyncMigrator.run(model);
445
- }),
446
- );
447
- };
448
-
449
433
  export const executeModel = (
450
434
  tx: Db.Tx,
451
435
  model: ExecutableModel,
@@ -460,7 +444,7 @@ export const executeModels = async (
460
444
  execModels.map(async (model) => {
461
445
  const { apiRoot } = model;
462
446
 
463
- await syncMigrator.run(tx, model);
447
+ await migrator.run(tx, model);
464
448
  const compiledModel = generateModels(model, db.engine);
465
449
 
466
450
  // Create tables related to terms and fact types
@@ -477,7 +461,7 @@ export const executeModels = async (
477
461
  }
478
462
  await promise;
479
463
  }
480
- await syncMigrator.postRun(tx, model);
464
+ await migrator.postRun(tx, model);
481
465
 
482
466
  odataResponse.prepareModel(compiledModel.abstractSql);
483
467
  deepFreeze(compiledModel.abstractSql);
@@ -1638,12 +1622,10 @@ export const executeStandardModels = async (tx: Db.Tx): Promise<void> => {
1638
1622
  log: false,
1639
1623
  },
1640
1624
  migrations: {
1641
- [defaultMigrationCategory]: {
1642
- '11.0.0-modified-at': `
1625
+ '11.0.0-modified-at': `
1643
1626
  ALTER TABLE "model"
1644
1627
  ADD COLUMN IF NOT EXISTS "modified at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL;
1645
1628
  `,
1646
- },
1647
1629
  },
1648
1630
  });
1649
1631
  await executeModels(tx, permissions.config.models);
@@ -4,8 +4,7 @@ import './sbvr-loader';
4
4
 
5
5
  import * as dbModule from '../database-layer/db';
6
6
  import * as configLoader from '../config-loader/config-loader';
7
- import * as migrator from '../migrator/sync';
8
- import * as migratorUtils from '../migrator/utils';
7
+ import * as migrator from '../migrator/migrator';
9
8
 
10
9
  import * as sbvrUtils from '../sbvr-api/sbvr-utils';
11
10
 
@@ -18,7 +17,7 @@ export * as env from '../config-loader/env';
18
17
  export * as types from '../sbvr-api/common-types';
19
18
  export * as hooks from '../sbvr-api/hooks';
20
19
  export type { configLoader as ConfigLoader };
21
- export type { migratorUtils as Migrator };
20
+ export type { migrator as Migrator };
22
21
 
23
22
  let envDatabaseOptions: dbModule.DatabaseOptions<string>;
24
23
  if (dbModule.engines.websql != null) {
@@ -1,6 +0,0 @@
1
- import type { Model } from '../config-loader/config-loader';
2
- declare type ApiRootModel = Model & {
3
- apiRoot: string;
4
- };
5
- export declare const run: (model: ApiRootModel) => Promise<void>;
6
- export {};
@@ -1,154 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.run = void 0;
4
- const _ = require("lodash");
5
- const sbvrUtils = require("../sbvr-api/sbvr-utils");
6
- const utils_1 = require("./utils");
7
- const run = async (model) => {
8
- const { migrations } = model;
9
- if (migrations == null ||
10
- _.isEmpty(migrations) ||
11
- migrations[utils_1.migrationCategories.async] === undefined) {
12
- return;
13
- }
14
- await $run(model, migrations[utils_1.migrationCategories.async]);
15
- };
16
- exports.run = run;
17
- const $run = async (model, migrations) => {
18
- var _a, _b, _c, _d;
19
- const modelName = model.apiRoot;
20
- let exists;
21
- await sbvrUtils.db.transaction(async (tx) => {
22
- var _a, _b;
23
- exists = await (0, utils_1.checkModelAlreadyExists)(tx, modelName);
24
- if (!exists) {
25
- ((_b = (_a = sbvrUtils.api.migrations) === null || _a === void 0 ? void 0 : _a.logger.info) !== null && _b !== void 0 ? _b : console.info)('First time model has executed, skipping migrations');
26
- return await (0, utils_1.setExecutedMigrations)(tx, modelName, Object.keys(migrations));
27
- }
28
- });
29
- if (!exists) {
30
- return;
31
- }
32
- let pendingMigrations = [];
33
- await sbvrUtils.db.transaction(async (tx) => {
34
- const executedMigrations = await (0, utils_1.getExecutedMigrations)(tx, modelName);
35
- pendingMigrations = filterAndSortPendingAsyncMigrations(migrations, executedMigrations);
36
- });
37
- for (const [key, migration] of pendingMigrations) {
38
- const initMigrationState = {
39
- migration_key: key,
40
- start_time: new Date(Date.now()),
41
- last_run_time: new Date(Date.now()),
42
- run_counter: 0,
43
- migrated_rows: 0,
44
- error_counter: 0,
45
- error_threshold: utils_1.migratorEnv.asyncMigrationDefaultErrorThreshold,
46
- delayMS: utils_1.migratorEnv.asyncMigrationDefaultDelayMS,
47
- backoffDelayMS: utils_1.migratorEnv.asyncMigrationDefaultBackoffDelayMS,
48
- converged_time: undefined,
49
- last_error_message: undefined,
50
- is_backoff: false,
51
- should_stop: false,
52
- };
53
- let asyncRunnerMigratorFn;
54
- if (typeof migration === 'object') {
55
- if (migration.fn && typeof migration.fn === 'function') {
56
- asyncRunnerMigratorFn = async (tx) => (await migration.fn(tx, sbvrUtils))
57
- .rowsAffected;
58
- }
59
- else if (migration.sql && typeof migration.sql === 'string') {
60
- asyncRunnerMigratorFn = async (tx) => (await tx.executeSql(migration.sql)).rowsAffected;
61
- }
62
- else {
63
- ((_b = (_a = sbvrUtils.api.migrations) === null || _a === void 0 ? void 0 : _a.logger.error) !== null && _b !== void 0 ? _b : console.error)(`Invalid migration object: ${JSON.stringify(migration, null, 2)}`);
64
- continue;
65
- }
66
- initMigrationState.backoffDelayMS =
67
- migration.backoffDelayMS ||
68
- utils_1.migratorEnv.asyncMigrationDefaultBackoffDelayMS;
69
- initMigrationState.delayMS =
70
- migration.delayMS || utils_1.migratorEnv.asyncMigrationDefaultDelayMS;
71
- initMigrationState.error_threshold =
72
- migration.errorThreshold ||
73
- utils_1.migratorEnv.asyncMigrationDefaultErrorThreshold;
74
- }
75
- else if (typeof migration === 'string') {
76
- asyncRunnerMigratorFn = async (tx) => (await tx.executeSql(migration)).rowsAffected;
77
- }
78
- else {
79
- ((_d = (_c = sbvrUtils.api.migrations) === null || _c === void 0 ? void 0 : _c.logger.error) !== null && _d !== void 0 ? _d : console.error)(`Invalid async migration object: ${JSON.stringify(migration, null, 2)}`);
80
- continue;
81
- }
82
- await sbvrUtils.db.transaction(async (tx) => (0, utils_1.initMigrationStatus)(tx, initMigrationState));
83
- const asyncRunner = async () => {
84
- await sbvrUtils.db.transaction(async (tx) => {
85
- await (0, utils_1.lockMigrations)(tx, modelName, async () => {
86
- var _a, _b, _c, _d;
87
- const migrationState = await (0, utils_1.readMigrationStatus)(tx, key);
88
- if (!migrationState || migrationState.should_stop === true) {
89
- ((_b = (_a = sbvrUtils.api.migrations) === null || _a === void 0 ? void 0 : _a.logger.info) !== null && _b !== void 0 ? _b : console.info)(`stopping async migration: ${key}`);
90
- clearInterval(asyncScheduler);
91
- return;
92
- }
93
- try {
94
- clearInterval(asyncScheduler);
95
- if (migrationState.last_run_time) {
96
- const durationSinceLastRun = Date.now().valueOf() - migrationState.last_run_time.valueOf();
97
- if ((migrationState.is_backoff &&
98
- durationSinceLastRun < migrationState.backoffDelayMS) ||
99
- (!migrationState.is_backoff &&
100
- durationSinceLastRun < migrationState.delayMS)) {
101
- return;
102
- }
103
- }
104
- migrationState.last_run_time = new Date(Date.now());
105
- migrationState.run_counter += 1;
106
- let migratedRows = 0;
107
- await sbvrUtils.db.transaction(async (migrationTx) => {
108
- migratedRows = (await (asyncRunnerMigratorFn === null || asyncRunnerMigratorFn === void 0 ? void 0 : asyncRunnerMigratorFn(migrationTx))) || 0;
109
- });
110
- migrationState.migrated_rows += migratedRows;
111
- if (migratedRows === 0) {
112
- migrationState.is_backoff = true;
113
- if (!migrationState.converged_time) {
114
- migrationState.converged_time = new Date(Date.now());
115
- }
116
- }
117
- else {
118
- migrationState.is_backoff = false;
119
- }
120
- }
121
- catch (err) {
122
- migrationState.error_counter++;
123
- if (migrationState.error_counter % migrationState.error_threshold ===
124
- 0) {
125
- migrationState.last_error_message = `${err.name} ${err.message}`;
126
- ((_d = (_c = sbvrUtils.api.migrations) === null || _c === void 0 ? void 0 : _c.logger.error) !== null && _d !== void 0 ? _d : console.error)(`${key}: ${err.name} ${err.message}`);
127
- migrationState.is_backoff = true;
128
- }
129
- }
130
- finally {
131
- if (migrationState.is_backoff) {
132
- asyncScheduler = setInterval(asyncRunner, migrationState.backoffDelayMS);
133
- }
134
- else {
135
- asyncScheduler = setInterval(asyncRunner, migrationState.delayMS);
136
- }
137
- await (0, utils_1.updateMigrationStatus)(tx, migrationState);
138
- }
139
- });
140
- });
141
- };
142
- let asyncScheduler = setInterval(asyncRunner, initMigrationState.delayMS);
143
- }
144
- };
145
- const filterAndSortPendingAsyncMigrations = (migrations, executedMigrations) => {
146
- var _a;
147
- const latestExecutedMigration = (_a = executedMigrations.sort().pop()) !== null && _a !== void 0 ? _a : '';
148
- return _(migrations).omit(executedMigrations)
149
- .toPairs()
150
- .filter(([migrationKey]) => migrationKey > latestExecutedMigration)
151
- .sortBy(([migrationKey]) => migrationKey)
152
- .value();
153
- };
154
- //# sourceMappingURL=async.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"async.js","sourceRoot":"","sources":["../../src/migrator/async.ts"],"names":[],"mappings":"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"}
@@ -1,9 +0,0 @@
1
- import type { Tx } from '../database-layer/db';
2
- import type { Config, Model } from '../config-loader/config-loader';
3
- declare type ApiRootModel = Model & {
4
- apiRoot: string;
5
- };
6
- export declare const postRun: (tx: Tx, model: ApiRootModel) => Promise<void>;
7
- export declare const run: (tx: Tx, model: ApiRootModel) => Promise<void>;
8
- export declare const config: Config;
9
- export {};