@rpcbase/migrations 0.1.0 → 0.3.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/dist/assertCurrent.d.ts.map +1 -1
- package/dist/databaseProvider.d.ts +1 -0
- package/dist/databaseProvider.d.ts.map +1 -1
- package/dist/diffResources.d.ts.map +1 -1
- package/dist/helpers.d.ts +2 -1
- package/dist/helpers.d.ts.map +1 -1
- package/dist/index.js +121 -24
- package/dist/index.js.map +1 -1
- package/dist/inspectResources.d.ts.map +1 -1
- package/dist/planner.d.ts.map +1 -1
- package/dist/resources.d.ts.map +1 -1
- package/dist/runner.d.ts.map +1 -1
- package/dist/types.d.ts +5 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assertCurrent.d.ts","sourceRoot":"","sources":["../src/assertCurrent.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,yBAAyB,EACzB,yBAAyB,EACzB,aAAa,EACb,oBAAoB,EACrB,MAAM,SAAS,CAAA;AAGhB,eAAO,MAAM,uBAAuB,GAClC,UAAU,yBAAyB,EACnC,UAAU,yBAAyB,EACnC,UAAS,oBAAyB,KACjC,OAAO,CAAC,aAAa,
|
|
1
|
+
{"version":3,"file":"assertCurrent.d.ts","sourceRoot":"","sources":["../src/assertCurrent.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,yBAAyB,EACzB,yBAAyB,EACzB,aAAa,EACb,oBAAoB,EACrB,MAAM,SAAS,CAAA;AAGhB,eAAO,MAAM,uBAAuB,GAClC,UAAU,yBAAyB,EACnC,UAAU,yBAAyB,EACnC,UAAS,oBAAyB,KACjC,OAAO,CAAC,aAAa,CAcvB,CAAA"}
|
|
@@ -4,6 +4,7 @@ export type CreateMigrationDatabaseProviderOptions = {
|
|
|
4
4
|
client: MongoClient;
|
|
5
5
|
appName: string;
|
|
6
6
|
tenantCollection?: string;
|
|
7
|
+
initializingTenantStaleAfterMs?: number;
|
|
7
8
|
filesystemRequired?: (tenantId: string, signal: AbortSignal) => boolean | Promise<boolean>;
|
|
8
9
|
};
|
|
9
10
|
export declare const createMigrationDatabaseProvider: (options: CreateMigrationDatabaseProviderOptions) => MigrationDatabaseProvider;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"databaseProvider.d.ts","sourceRoot":"","sources":["../src/databaseProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE9C,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAA;AAiBxD,MAAM,MAAM,sCAAsC,GAAG;IACnD,MAAM,EAAE,WAAW,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAC3F,CAAA;AAED,eAAO,MAAM,+BAA+B,GAC1C,SAAS,sCAAsC,KAC9C,
|
|
1
|
+
{"version":3,"file":"databaseProvider.d.ts","sourceRoot":"","sources":["../src/databaseProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE9C,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAA;AAiBxD,MAAM,MAAM,sCAAsC,GAAG;IACnD,MAAM,EAAE,WAAW,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,8BAA8B,CAAC,EAAE,MAAM,CAAA;IACvC,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAC3F,CAAA;AAED,eAAO,MAAM,+BAA+B,GAC1C,SAAS,sCAAsC,KAC9C,yBAkEF,CAAA;AAED,eAAO,MAAM,wBAAwB,GAAI,IAAI,EAAE,KAAG,MAAyB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diffResources.d.ts","sourceRoot":"","sources":["../src/diffResources.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAKV,cAAc,EACd,kBAAkB,EAEnB,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"diffResources.d.ts","sourceRoot":"","sources":["../src/diffResources.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAKV,cAAc,EACd,kBAAkB,EAEnB,MAAM,SAAS,CAAA;AAyChB,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,cAAc,EACtB,OAAO,cAAc,KACpB,kBAoBF,CAAA"}
|
package/dist/helpers.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Db } from 'mongodb';
|
|
2
|
-
import { MigrationHelpers } from './types';
|
|
2
|
+
import { MigrationHelpers, MongoResources } from './types';
|
|
3
3
|
export type CreateMigrationHelpersOptions = {
|
|
4
4
|
searchTimeoutMs?: number;
|
|
5
5
|
searchPollIntervalMs?: number;
|
|
6
6
|
};
|
|
7
7
|
export declare const createMigrationHelpers: (db: Db, signal: AbortSignal, options?: CreateMigrationHelpersOptions) => MigrationHelpers;
|
|
8
|
+
export declare const reconcileRuntimeIndexOptions: (db: Db, resources: MongoResources, signal: AbortSignal) => Promise<void>;
|
|
8
9
|
//# sourceMappingURL=helpers.d.ts.map
|
package/dist/helpers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAY,MAAM,SAAS,CAAA;AAI3C,OAAO,KAAK,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAY,MAAM,SAAS,CAAA;AAI3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAwC/D,MAAM,MAAM,6BAA6B,GAAG;IAC1C,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAC9B,CAAA;AAED,eAAO,MAAM,sBAAsB,GACjC,IAAI,EAAE,EACN,QAAQ,WAAW,EACnB,UAAS,6BAAkC,KAC1C,gBAwJF,CAAA;AAED,eAAO,MAAM,4BAA4B,GACvC,IAAI,EAAE,EACN,WAAW,cAAc,EACzB,QAAQ,WAAW,KAClB,OAAO,CAAC,IAAI,CAoCd,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -20,6 +20,7 @@ var scopes = /* @__PURE__ */ new Set([
|
|
|
20
20
|
"tenant",
|
|
21
21
|
"filesystem"
|
|
22
22
|
]);
|
|
23
|
+
var runtimeIndexOptions = /* @__PURE__ */ new Set(["expireAfterSeconds"]);
|
|
23
24
|
var assertName = (value, label) => {
|
|
24
25
|
const normalized = value.trim();
|
|
25
26
|
if (!normalized) throw new Error(`${label} is required`);
|
|
@@ -59,12 +60,18 @@ var normalizeCollection = (resource) => {
|
|
|
59
60
|
var normalizeIndex = (resource) => {
|
|
60
61
|
assertScope(resource.scope);
|
|
61
62
|
if (Object.keys(resource.key).length === 0) throw new Error("Index key cannot be empty");
|
|
63
|
+
const optionNames = new Set(Object.keys(resource.options ?? {}));
|
|
64
|
+
const unsupportedRuntimeOption = Object.keys(resource.runtimeOptions ?? {}).find((name) => !runtimeIndexOptions.has(name));
|
|
65
|
+
if (unsupportedRuntimeOption) throw new Error(`Unsupported runtime-managed index option: ${unsupportedRuntimeOption}`);
|
|
66
|
+
const overlappingRuntimeOption = Object.keys(resource.runtimeOptions ?? {}).find((name) => optionNames.has(name));
|
|
67
|
+
if (overlappingRuntimeOption) throw new Error(`Index option ${overlappingRuntimeOption} cannot be both fixed and runtime-managed`);
|
|
62
68
|
return {
|
|
63
69
|
scope: resource.scope,
|
|
64
70
|
collection: assertName(resource.collection, "Index collection"),
|
|
65
71
|
name: assertName(resource.name, "Index name"),
|
|
66
72
|
key: structuredClone(resource.key),
|
|
67
|
-
...resource.options ? { options: copyDocument(resource.options) } : {}
|
|
73
|
+
...resource.options ? { options: copyDocument(resource.options) } : {},
|
|
74
|
+
...resource.runtimeOptions ? { runtimeOptions: copyDocument(resource.runtimeOptions) } : {}
|
|
68
75
|
};
|
|
69
76
|
};
|
|
70
77
|
var normalizeSearchIndex = (resource) => {
|
|
@@ -95,7 +102,8 @@ var checksumInput = (resources) => ({
|
|
|
95
102
|
indexes: resources.indexes.map((resource) => ({
|
|
96
103
|
...resource,
|
|
97
104
|
key: Object.entries(resource.key),
|
|
98
|
-
options: resource.options ?? {}
|
|
105
|
+
options: resource.options ?? {},
|
|
106
|
+
...resource.runtimeOptions ? { runtimeOptions: Object.keys(resource.runtimeOptions).sort() } : {}
|
|
99
107
|
})),
|
|
100
108
|
searchIndexes: resources.searchIndexes,
|
|
101
109
|
collectionValidators: resources.collectionValidators
|
|
@@ -123,15 +131,18 @@ var mergeMongoResources = (resourceSets) => {
|
|
|
123
131
|
const indexes = /* @__PURE__ */ new Map();
|
|
124
132
|
const searchIndexes = /* @__PURE__ */ new Map();
|
|
125
133
|
const validators = /* @__PURE__ */ new Map();
|
|
126
|
-
const merge = (target, resource, identity, label) => {
|
|
134
|
+
const merge = (target, resource, identity, label, comparisonValue = (value) => value) => {
|
|
127
135
|
const key = identity(resource);
|
|
128
136
|
const previous = target.get(key);
|
|
129
|
-
if (previous && canonicalStringify(previous) !== canonicalStringify(resource)) throw new Error(`Conflicting ${label} resource across migration sources: ${key}`);
|
|
137
|
+
if (previous && canonicalStringify(comparisonValue(previous)) !== canonicalStringify(comparisonValue(resource))) throw new Error(`Conflicting ${label} resource across migration sources: ${key}`);
|
|
130
138
|
target.set(key, resource);
|
|
131
139
|
};
|
|
132
140
|
for (const resources of resourceSets) {
|
|
133
141
|
for (const resource of resources.collections) merge(collections, resource, collectionIdentity$1, "collection");
|
|
134
|
-
for (const resource of resources.indexes) merge(indexes, resource, indexIdentity$1, "index")
|
|
142
|
+
for (const resource of resources.indexes) merge(indexes, resource, indexIdentity$1, "index", (value) => ({
|
|
143
|
+
...value,
|
|
144
|
+
key: Object.entries(value.key)
|
|
145
|
+
}));
|
|
135
146
|
for (const resource of resources.searchIndexes) merge(searchIndexes, resource, indexIdentity$1, "Search index");
|
|
136
147
|
for (const resource of resources.collectionValidators) merge(validators, resource, validatorIdentity$1, "collection validator");
|
|
137
148
|
}
|
|
@@ -149,7 +160,8 @@ var indexIdentity = (resource) => `${resource.scope}:${resource.collection}:${re
|
|
|
149
160
|
var validatorIdentity = (resource) => `${resource.scope}:${resource.collection}`;
|
|
150
161
|
var indexComparisonValue = (resource) => ({
|
|
151
162
|
...resource,
|
|
152
|
-
key: Object.entries(resource.key)
|
|
163
|
+
key: Object.entries(resource.key),
|
|
164
|
+
runtimeOptions: Object.keys(resource.runtimeOptions ?? {}).sort()
|
|
153
165
|
});
|
|
154
166
|
var diffSet = (before, after, identity, comparisonValue = (resource) => resource) => {
|
|
155
167
|
const beforeById = new Map(before.map((resource) => [identity(resource), resource]));
|
|
@@ -508,7 +520,10 @@ var inspectMongoResources = async (db, resources, options = {}) => {
|
|
|
508
520
|
continue;
|
|
509
521
|
}
|
|
510
522
|
const actualDefinition = normalizeIndexDefinition(actual.key ?? {}, actual, expected.key);
|
|
511
|
-
const expectedDefinition = normalizeIndexDefinition(expected.key,
|
|
523
|
+
const expectedDefinition = normalizeIndexDefinition(expected.key, {
|
|
524
|
+
...expected.options ?? {},
|
|
525
|
+
...expected.runtimeOptions ?? {}
|
|
526
|
+
});
|
|
512
527
|
if (!same$1(actualDefinition.key, expectedDefinition.key)) divergences.push({
|
|
513
528
|
code: "index_key_mismatch",
|
|
514
529
|
scope: expected.scope,
|
|
@@ -520,15 +535,20 @@ var inspectMongoResources = async (db, resources, options = {}) => {
|
|
|
520
535
|
});
|
|
521
536
|
const expectedOptions = expectedDefinition.options;
|
|
522
537
|
const actualOptions = actualDefinition.options;
|
|
523
|
-
if (!same$1(actualOptions, expectedOptions))
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
538
|
+
if (!same$1(actualOptions, expectedOptions)) {
|
|
539
|
+
const runtimeOptionNames = new Set(Object.keys(expected.runtimeOptions ?? {}));
|
|
540
|
+
const fixedOptions = (indexOptions) => Object.fromEntries(Object.entries(indexOptions).filter(([name]) => !runtimeOptionNames.has(name)));
|
|
541
|
+
const runtimeOnly = runtimeOptionNames.size > 0 && same$1(fixedOptions(actualOptions), fixedOptions(expectedOptions));
|
|
542
|
+
divergences.push({
|
|
543
|
+
code: runtimeOnly ? "runtime_index_options_mismatch" : "index_options_mismatch",
|
|
544
|
+
scope: expected.scope,
|
|
545
|
+
collection: expected.collection,
|
|
546
|
+
resource: expected.name,
|
|
547
|
+
expected: expectedOptions,
|
|
548
|
+
actual: actualOptions,
|
|
549
|
+
message: message(expected.collection, expected.name, "index options differ")
|
|
550
|
+
});
|
|
551
|
+
}
|
|
532
552
|
}
|
|
533
553
|
for (const expected of resources.collectionValidators) {
|
|
534
554
|
const collection = collectionsByName.get(expected.collection);
|
|
@@ -757,12 +777,45 @@ var createMigrationHelpers = (db, signal, options = {}) => {
|
|
|
757
777
|
});
|
|
758
778
|
for (const index of resources.indexes) await ensureIndex(index.collection, index.key, {
|
|
759
779
|
name: index.name,
|
|
760
|
-
...index.options ?? {}
|
|
780
|
+
...index.options ?? {},
|
|
781
|
+
...index.runtimeOptions ?? {}
|
|
761
782
|
});
|
|
762
783
|
for (const index of resources.searchIndexes) await ensureSearchIndex(index.collection, index.name, index.definition);
|
|
763
784
|
}
|
|
764
785
|
};
|
|
765
786
|
};
|
|
787
|
+
var reconcileRuntimeIndexOptions = async (db, resources, signal) => {
|
|
788
|
+
for (const index of resources.indexes) {
|
|
789
|
+
const runtimeOptions = index.runtimeOptions ?? {};
|
|
790
|
+
if (Object.keys(runtimeOptions).length === 0) continue;
|
|
791
|
+
signal.throwIfAborted();
|
|
792
|
+
let indexes;
|
|
793
|
+
try {
|
|
794
|
+
indexes = await db.collection(index.collection).listIndexes().toArray();
|
|
795
|
+
} catch (error) {
|
|
796
|
+
if (namespaceMissing(error)) continue;
|
|
797
|
+
throw error;
|
|
798
|
+
}
|
|
799
|
+
const actual = indexes.find((candidate) => candidate.name === index.name);
|
|
800
|
+
if (!actual) continue;
|
|
801
|
+
const actualDefinition = normalizeIndexDefinition(actual.key ?? {}, actual, index.key);
|
|
802
|
+
const expectedDefinition = normalizeIndexDefinition(index.key, {
|
|
803
|
+
...index.options ?? {},
|
|
804
|
+
...runtimeOptions
|
|
805
|
+
});
|
|
806
|
+
const runtimeOptionNames = new Set(Object.keys(runtimeOptions));
|
|
807
|
+
const fixedOptions = (options) => Object.fromEntries(Object.entries(options).filter(([name]) => !runtimeOptionNames.has(name)));
|
|
808
|
+
if (!same(actualDefinition.key, expectedDefinition.key) || !same(fixedOptions(actualDefinition.options), fixedOptions(expectedDefinition.options))) continue;
|
|
809
|
+
if (!Object.keys(runtimeOptions).some((name) => !same(actualDefinition.options[name], expectedDefinition.options[name]))) continue;
|
|
810
|
+
await db.command({
|
|
811
|
+
collMod: index.collection,
|
|
812
|
+
index: {
|
|
813
|
+
name: index.name,
|
|
814
|
+
...runtimeOptions
|
|
815
|
+
}
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
};
|
|
766
819
|
//#endregion
|
|
767
820
|
//#region src/errors.ts
|
|
768
821
|
var MigrationIntegrityError = class extends Error {
|
|
@@ -811,11 +864,21 @@ var createMigrationDatabaseProvider = (options) => {
|
|
|
811
864
|
const appName = normalizeAppName(options.appName);
|
|
812
865
|
const globalDbName = `${appName}-global-db`;
|
|
813
866
|
const tenantCollection = options.tenantCollection?.trim() || "rbtenants";
|
|
867
|
+
const initializingTenantStaleAfterMs = options.initializingTenantStaleAfterMs ?? 5 * 6e4;
|
|
868
|
+
if (!Number.isFinite(initializingTenantStaleAfterMs) || initializingTenantStaleAfterMs < 0) throw new Error("initializingTenantStaleAfterMs must be a non-negative finite number");
|
|
869
|
+
const staleInitializingFilter = () => ({
|
|
870
|
+
provisioningStatus: "initializing",
|
|
871
|
+
$or: [{ provisioningStartedAt: { $exists: false } }, { provisioningStartedAt: { $lte: new Date(Date.now() - initializingTenantStaleAfterMs) } }]
|
|
872
|
+
});
|
|
814
873
|
return {
|
|
815
874
|
global: () => options.client.db(globalDbName),
|
|
816
875
|
tenantIds: async (signal) => {
|
|
817
876
|
signal.throwIfAborted();
|
|
818
|
-
const documents = await options.client.db(globalDbName).collection(tenantCollection).find({ $or: [
|
|
877
|
+
const documents = await options.client.db(globalDbName).collection(tenantCollection).find({ $or: [
|
|
878
|
+
{ provisioningStatus: { $exists: false } },
|
|
879
|
+
{ provisioningStatus: "active" },
|
|
880
|
+
staleInitializingFilter()
|
|
881
|
+
] }, { projection: { tenantId: 1 } }).sort({ tenantId: 1 }).toArray();
|
|
819
882
|
signal.throwIfAborted();
|
|
820
883
|
return [...new Set(documents.flatMap((document) => typeof document.tenantId === "string" && document.tenantId.trim() ? [normalizeTenantId(document.tenantId)] : []))];
|
|
821
884
|
},
|
|
@@ -827,6 +890,21 @@ var createMigrationDatabaseProvider = (options) => {
|
|
|
827
890
|
return Boolean(tenant);
|
|
828
891
|
},
|
|
829
892
|
tenant: (tenantId) => options.client.db(`${appName}-${normalizeTenantId(tenantId)}-db`),
|
|
893
|
+
activateRecoveredTenant: async (tenantId, signal) => {
|
|
894
|
+
signal.throwIfAborted();
|
|
895
|
+
const result = await options.client.db(globalDbName).collection(tenantCollection).updateOne({
|
|
896
|
+
tenantId: normalizeTenantId(tenantId),
|
|
897
|
+
...staleInitializingFilter()
|
|
898
|
+
}, {
|
|
899
|
+
$set: {
|
|
900
|
+
provisioningStatus: "active",
|
|
901
|
+
provisionedAt: /* @__PURE__ */ new Date()
|
|
902
|
+
},
|
|
903
|
+
$unset: { provisioningError: "" }
|
|
904
|
+
});
|
|
905
|
+
signal.throwIfAborted();
|
|
906
|
+
return result.matchedCount === 1;
|
|
907
|
+
},
|
|
830
908
|
filesystemRequired: options.filesystemRequired ?? (() => false),
|
|
831
909
|
filesystem: (tenantId) => options.client.db(`${appName}-${normalizeTenantId(tenantId)}-filesystem-db`)
|
|
832
910
|
};
|
|
@@ -968,7 +1046,9 @@ var planMigrations = async (registry, provider, options = {}) => {
|
|
|
968
1046
|
databases,
|
|
969
1047
|
hasPending: databases.some((database) => database.pending.length > 0 || database.running.length > 0 || database.failed.length > 0),
|
|
970
1048
|
hasOffline: databases.some((database) => database.pending.some((migration) => migration.mode === "offline") || [...database.running, ...database.failed].some((id) => registry.migrationsById.get(id)?.mode === "offline")),
|
|
971
|
-
|
|
1049
|
+
hasRollbackIncompatible: databases.some((database) => database.pending.some((migration) => migration.rollback === "incompatible") || [...database.running, ...database.failed].some((id) => registry.migrationsById.get(id)?.rollback === "incompatible")),
|
|
1050
|
+
hasAppliedRollbackIncompatible: databases.some((database) => database.applied.some((id) => registry.migrationsById.get(id)?.rollback === "incompatible")),
|
|
1051
|
+
hasErrors: databases.some((database) => database.integrityErrors.length > 0 || database.running.length === 0 && database.failed.length === 0 && database.resourceDivergences.some((divergence) => divergence.code !== "runtime_index_options_mismatch"))
|
|
972
1052
|
};
|
|
973
1053
|
};
|
|
974
1054
|
//#endregion
|
|
@@ -1118,7 +1198,7 @@ var combineSignals = (...signals) => {
|
|
|
1118
1198
|
};
|
|
1119
1199
|
var assertPlanCanRun = (plan) => {
|
|
1120
1200
|
const retrying = plan.running.length > 0 || plan.failed.length > 0;
|
|
1121
|
-
const errors = [...plan.integrityErrors, ...retrying ? [] : plan.resourceDivergences.map((divergence) => divergence.message)];
|
|
1201
|
+
const errors = [...plan.integrityErrors, ...retrying ? [] : plan.resourceDivergences.filter((divergence) => divergence.code !== "runtime_index_options_mismatch").map((divergence) => divergence.message)];
|
|
1122
1202
|
if (errors.length > 0) throw new MigrationIntegrityError(`${plan.database}: ${errors.join("; ")}`);
|
|
1123
1203
|
};
|
|
1124
1204
|
var recordForMigration = (migration, lock, attempt, release) => ({
|
|
@@ -1276,8 +1356,15 @@ var applyMigration = async (registry, target, migration, lock, signal, release)
|
|
|
1276
1356
|
};
|
|
1277
1357
|
var sourcePredecessorsApplied = (registry, migration, applied) => registry.sources.find((source) => source.name === migration.source)?.migrations.filter((candidate) => candidate.scope === migration.scope && candidate.sourcePosition < migration.sourcePosition).every((candidate) => applied.has(candidate.qualifiedId)) ?? false;
|
|
1278
1358
|
var runTarget = async (registry, target, lock, signal, options, earlierScopeDependencyApplied) => {
|
|
1279
|
-
|
|
1359
|
+
let plan = await planMigrationTarget(registry, target, { signal });
|
|
1280
1360
|
assertPlanCanRun(plan);
|
|
1361
|
+
if (plan.resourceDivergences.some((divergence) => divergence.code === "runtime_index_options_mismatch")) {
|
|
1362
|
+
const history = await readMigrationHistory(target.db);
|
|
1363
|
+
const expectedResources = getExpectedResources(registry, target.scope, history);
|
|
1364
|
+
await reconcileRuntimeIndexOptions(target.db, expectedResources, signal);
|
|
1365
|
+
plan = await planMigrationTarget(registry, target, { signal });
|
|
1366
|
+
assertPlanCanRun(plan);
|
|
1367
|
+
}
|
|
1281
1368
|
const applied = new Set(plan.applied);
|
|
1282
1369
|
const migrationsToRun = registry.migrations.filter((migration) => migration.scope === target.scope && !applied.has(migration.qualifiedId));
|
|
1283
1370
|
for (const migration of migrationsToRun) {
|
|
@@ -1353,10 +1440,20 @@ var runMigrations = async (registry, provider, options = {}) => {
|
|
|
1353
1440
|
return false;
|
|
1354
1441
|
});
|
|
1355
1442
|
});
|
|
1356
|
-
|
|
1443
|
+
const plan = await planMigrations(registry, provider, {
|
|
1357
1444
|
tenantId: options.tenantId,
|
|
1358
1445
|
signal
|
|
1359
1446
|
});
|
|
1447
|
+
let activatedRecoveredTenant = false;
|
|
1448
|
+
if (!options.initializeTenant && provider.activateRecoveredTenant) for (const tenantId of tenantApplied.keys()) {
|
|
1449
|
+
const tenantPlans = plan.databases.filter((database) => database.tenantId === tenantId);
|
|
1450
|
+
if (!(tenantPlans.length > 0 && tenantPlans.every((database) => database.pending.length === 0 && database.running.length === 0 && database.failed.length === 0 && database.integrityErrors.length === 0 && database.resourceDivergences.length === 0))) continue;
|
|
1451
|
+
if (await provider.activateRecoveredTenant(tenantId, signal)) activatedRecoveredTenant = true;
|
|
1452
|
+
}
|
|
1453
|
+
return activatedRecoveredTenant ? await planMigrations(registry, provider, {
|
|
1454
|
+
tenantId: options.tenantId,
|
|
1455
|
+
signal
|
|
1456
|
+
}) : plan;
|
|
1360
1457
|
} finally {
|
|
1361
1458
|
await lock.release();
|
|
1362
1459
|
}
|
|
@@ -1377,7 +1474,7 @@ var assertMigrationsCurrent = async (registry, provider, options = {}) => {
|
|
|
1377
1474
|
if (database.running.length > 0) errors.push(`${database.database}: migration running`);
|
|
1378
1475
|
if (database.failed.length > 0) errors.push(`${database.database}: migration failed`);
|
|
1379
1476
|
errors.push(...database.integrityErrors.map((error) => `${database.database}: ${error}`));
|
|
1380
|
-
errors.push(...database.resourceDivergences.map((divergence) => `${database.database}: ${divergence.message}`));
|
|
1477
|
+
errors.push(...database.resourceDivergences.filter((divergence) => divergence.code !== "runtime_index_options_mismatch").map((divergence) => `${database.database}: ${divergence.message}`));
|
|
1381
1478
|
}
|
|
1382
1479
|
if (errors.length > 0) throw new MigrationIntegrityError(errors.join("; "));
|
|
1383
1480
|
return plan;
|
|
@@ -1561,6 +1658,6 @@ var testSingleMigration = async (options) => {
|
|
|
1561
1658
|
}
|
|
1562
1659
|
};
|
|
1563
1660
|
//#endregion
|
|
1564
|
-
export { MIGRATIONS_COLLECTION, MIGRATION_LOCKS_COLLECTION, MigrationIntegrityError, MigrationLockLostError, MigrationLockUnavailableError, acquireMigrationLock, assertMigrationsCurrent, canonicalChecksum, canonicalStringify, collectMigrationTargets, compileMigrationRegistry, computeMigrationIntegrity, createMigrationDatabaseProvider, createMigrationHelpers, createMigrationIntegrityPlugin, defineMigration, defineMigrationSource, defineMongoResources, diffMongoResources, filterMongoResources, getExpectedResources, getMigrationDatabaseName, initializeTenantMigrations, inspectMongoResources, mergeMongoResources, planMigrationTarget, planMigrations, readMigrationHistory, runMigrations, sha256, testMigrationRegistry, testSingleMigration };
|
|
1661
|
+
export { MIGRATIONS_COLLECTION, MIGRATION_LOCKS_COLLECTION, MigrationIntegrityError, MigrationLockLostError, MigrationLockUnavailableError, acquireMigrationLock, assertMigrationsCurrent, canonicalChecksum, canonicalStringify, collectMigrationTargets, compileMigrationRegistry, computeMigrationIntegrity, createMigrationDatabaseProvider, createMigrationHelpers, createMigrationIntegrityPlugin, defineMigration, defineMigrationSource, defineMongoResources, diffMongoResources, filterMongoResources, getExpectedResources, getMigrationDatabaseName, initializeTenantMigrations, inspectMongoResources, mergeMongoResources, planMigrationTarget, planMigrations, readMigrationHistory, reconcileRuntimeIndexOptions, runMigrations, sha256, testMigrationRegistry, testSingleMigration };
|
|
1565
1662
|
|
|
1566
1663
|
//# sourceMappingURL=index.js.map
|