@ftschopp/dynatable-migrations 1.2.4 → 1.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/core/errors.d.ts +25 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +47 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/tracker.d.ts +14 -0
- package/dist/core/tracker.d.ts.map +1 -1
- package/dist/core/tracker.js +135 -94
- package/dist/core/tracker.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/errors.ts +55 -0
- package/src/core/tracker.test.ts +131 -0
- package/src/core/tracker.ts +147 -102
- package/src/index.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## @ftschopp/dynatable-migrations [1.2.5](https://github.com/ftschopp/dynatable/compare/@ftschopp/dynatable-migrations@1.2.4...@ftschopp/dynatable-migrations@1.2.5) (2026-05-08)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **migrations:** make markAsApplied idempotent and surface typed errors ([#29](https://github.com/ftschopp/dynatable/issues/29)) ([133b836](https://github.com/ftschopp/dynatable/commit/133b83656c0891a04a155c603f53220dadaa6f87)), closes [#10](https://github.com/ftschopp/dynatable/issues/10)
|
|
7
|
+
|
|
1
8
|
## @ftschopp/dynatable-migrations [1.2.4](https://github.com/ftschopp/dynatable/compare/@ftschopp/dynatable-migrations@1.2.3...@ftschopp/dynatable-migrations@1.2.4) (2026-05-08)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown by `markAsApplied` when the version already has a tracking record
|
|
3
|
+
* in a non-applied state (e.g. `failed`, `rolled_back`) and therefore
|
|
4
|
+
* cannot be silently treated as an idempotent re-apply. Surfaces the
|
|
5
|
+
* existing state so the caller can decide whether to retry, recover, or
|
|
6
|
+
* roll back.
|
|
7
|
+
*/
|
|
8
|
+
export declare class MigrationAlreadyAppliedError extends Error {
|
|
9
|
+
readonly version: string;
|
|
10
|
+
readonly currentStatus: string | undefined;
|
|
11
|
+
constructor(version: string, currentStatus: string | undefined);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Thrown when a tracker write is cancelled because the migration lock was
|
|
15
|
+
* taken by another process between `acquireLock()` and the write itself
|
|
16
|
+
* (e.g. the original lock TTL expired and a second worker took over).
|
|
17
|
+
*
|
|
18
|
+
* The transaction was rolled back atomically — no partial state was
|
|
19
|
+
* written. The safe action is to stop the current `up()` / `down()` run.
|
|
20
|
+
*/
|
|
21
|
+
export declare class MigrationLockLostError extends Error {
|
|
22
|
+
readonly version: string;
|
|
23
|
+
constructor(version: string);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,SAAgB,OAAO,EAAE,MAAM,CAAC;IAChC,SAAgB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;gBAEtC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,SAAS;CAgB/D;AAED;;;;;;;GAOG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,SAAgB,OAAO,EAAE,MAAM,CAAC;gBAEpB,OAAO,EAAE,MAAM;CAc5B"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MigrationLockLostError = exports.MigrationAlreadyAppliedError = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Thrown by `markAsApplied` when the version already has a tracking record
|
|
6
|
+
* in a non-applied state (e.g. `failed`, `rolled_back`) and therefore
|
|
7
|
+
* cannot be silently treated as an idempotent re-apply. Surfaces the
|
|
8
|
+
* existing state so the caller can decide whether to retry, recover, or
|
|
9
|
+
* roll back.
|
|
10
|
+
*/
|
|
11
|
+
class MigrationAlreadyAppliedError extends Error {
|
|
12
|
+
constructor(version, currentStatus) {
|
|
13
|
+
super(`Migration "${version}" already has a tracking record in state ` +
|
|
14
|
+
`"${currentStatus ?? 'unknown'}" — cannot mark as applied. ` +
|
|
15
|
+
`If you want to re-apply this version, roll it back first ` +
|
|
16
|
+
`(or recover the failed run) and try again.`);
|
|
17
|
+
this.name = 'MigrationAlreadyAppliedError';
|
|
18
|
+
this.version = version;
|
|
19
|
+
this.currentStatus = currentStatus;
|
|
20
|
+
if (typeof Error.captureStackTrace === 'function') {
|
|
21
|
+
Error.captureStackTrace(this, MigrationAlreadyAppliedError);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.MigrationAlreadyAppliedError = MigrationAlreadyAppliedError;
|
|
26
|
+
/**
|
|
27
|
+
* Thrown when a tracker write is cancelled because the migration lock was
|
|
28
|
+
* taken by another process between `acquireLock()` and the write itself
|
|
29
|
+
* (e.g. the original lock TTL expired and a second worker took over).
|
|
30
|
+
*
|
|
31
|
+
* The transaction was rolled back atomically — no partial state was
|
|
32
|
+
* written. The safe action is to stop the current `up()` / `down()` run.
|
|
33
|
+
*/
|
|
34
|
+
class MigrationLockLostError extends Error {
|
|
35
|
+
constructor(version) {
|
|
36
|
+
super(`Migration lock was lost during markAsApplied("${version}"). ` +
|
|
37
|
+
`Another worker may have taken over. The transaction was rolled ` +
|
|
38
|
+
`back atomically; no partial state was written.`);
|
|
39
|
+
this.name = 'MigrationLockLostError';
|
|
40
|
+
this.version = version;
|
|
41
|
+
if (typeof Error.captureStackTrace === 'function') {
|
|
42
|
+
Error.captureStackTrace(this, MigrationLockLostError);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.MigrationLockLostError = MigrationLockLostError;
|
|
47
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":";;;AAAA;;;;;;GAMG;AACH,MAAa,4BAA6B,SAAQ,KAAK;IAIrD,YAAY,OAAe,EAAE,aAAiC;QAC5D,KAAK,CACH,cAAc,OAAO,2CAA2C;YAC9D,IAAI,aAAa,IAAI,SAAS,8BAA8B;YAC5D,2DAA2D;YAC3D,4CAA4C,CAC/C,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,8BAA8B,CAAC;QAC3C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,OAAQ,KAAoD,CAAC,iBAAiB,KAAK,UAAU,EAAE,CAAC;YAEhG,KACD,CAAC,iBAAiB,CAAC,IAAI,EAAE,4BAA4B,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;CACF;AApBD,oEAoBC;AAED;;;;;;;GAOG;AACH,MAAa,sBAAuB,SAAQ,KAAK;IAG/C,YAAY,OAAe;QACzB,KAAK,CACH,iDAAiD,OAAO,MAAM;YAC5D,iEAAiE;YACjE,gDAAgD,CACnD,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,OAAQ,KAAoD,CAAC,iBAAiB,KAAK,UAAU,EAAE,CAAC;YAEhG,KACD,CAAC,iBAAiB,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;CACF;AAjBD,wDAiBC"}
|
package/dist/core/tracker.d.ts
CHANGED
|
@@ -42,6 +42,20 @@ export declare class DynamoDBMigrationTracker implements MigrationTracker {
|
|
|
42
42
|
* Handles both new migrations and re-applying rolled back migrations
|
|
43
43
|
*/
|
|
44
44
|
markAsApplied(version: string, name: string, schemaDefinition?: Record<string, any>, schemaChanges?: SchemaChange[], checksum?: string): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Inspect a `TransactionCanceledException` raised by `markAsApplied` and
|
|
47
|
+
* either swallow it (idempotent re-apply) or re-throw a typed error.
|
|
48
|
+
*
|
|
49
|
+
* The TransactWrite items are: [lockOwnershipCheck, migrationRow, currentPointer].
|
|
50
|
+
* Each item produces an entry in `CancellationReasons`.
|
|
51
|
+
* - reasons[0] failing → the lock was lost → MigrationLockLostError.
|
|
52
|
+
* - reasons[1] failing → the migration row already exists in a state the
|
|
53
|
+
* write refused. Re-fetch the record:
|
|
54
|
+
* * status === 'applied' → idempotent re-apply, return silently.
|
|
55
|
+
* * other states → MigrationAlreadyAppliedError with the
|
|
56
|
+
* current state, so the caller can decide what to do.
|
|
57
|
+
*/
|
|
58
|
+
private handleMarkAsAppliedCancellation;
|
|
45
59
|
/**
|
|
46
60
|
* Mark migration as rolled back using TransactWrite for atomicity
|
|
47
61
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/core/tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAS/D,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/core/tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAS/D,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAI5F,oFAAoF;AACpF,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C,qBAAa,wBAAyB,YAAW,gBAAgB;IAC/D,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAuB;IACrC,iDAAiD;IACjD,SAAgB,cAAc,EAAE,MAAM,CAAC;gBAE3B,MAAM,EAAE,sBAAsB,EAAE,MAAM,EAAE,eAAe;IAQnE,OAAO,KAAK,OAAO,GAKlB;IAED,wEAAwE;IACxE,OAAO,CAAC,WAAW;IASnB,gFAAgF;IAChF,OAAO,CAAC,kBAAkB;IAcpB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBjC;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAiCrC;;;;;OAKG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBlC;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAyBlC;;OAEG;IACG,oBAAoB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAuBlD,iBAAiB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAcjD;;;OAGG;IACG,aAAa,CACjB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACtC,aAAa,CAAC,EAAE,YAAY,EAAE,EAC9B,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC;IA2HhB;;;;;;;;;;;;OAYG;YACW,+BAA+B;IA2B7C;;OAEG;IACG,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuDhD,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8D3D,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCvD,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAc9D,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAInD"}
|
package/dist/core/tracker.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.DynamoDBMigrationTracker = exports.DEFAULT_LOCK_TTL_SECONDS = void 0;
|
|
4
4
|
const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
|
|
5
5
|
const semver_1 = require("./semver");
|
|
6
|
+
const errors_1 = require("./errors");
|
|
6
7
|
/** Default lock TTL in seconds. Configurable via MigrationConfig.lockTtlSeconds. */
|
|
7
8
|
exports.DEFAULT_LOCK_TTL_SECONDS = 300; // 5 minutes
|
|
8
9
|
class DynamoDBMigrationTracker {
|
|
@@ -179,109 +180,149 @@ class DynamoDBMigrationTracker {
|
|
|
179
180
|
const now = new Date().toISOString();
|
|
180
181
|
// Check if migration record already exists (e.g., rolled back or failed)
|
|
181
182
|
const existing = await this.getMigration(version);
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
183
|
+
try {
|
|
184
|
+
if (existing) {
|
|
185
|
+
// Update existing record (re-applying a rolled back or failed migration)
|
|
186
|
+
// Build dynamic update expression - DynamoDB doesn't accept undefined values
|
|
187
|
+
const setParts = ['#status = :status', 'appliedAt = :appliedAt', '#name = :name'];
|
|
188
|
+
const expressionValues = {
|
|
189
|
+
':status': 'applied',
|
|
190
|
+
':appliedAt': now,
|
|
191
|
+
':name': name,
|
|
192
|
+
};
|
|
193
|
+
if (schemaDefinition !== undefined) {
|
|
194
|
+
setParts.push('schemaDefinition = :schemaDef');
|
|
195
|
+
expressionValues[':schemaDef'] = schemaDefinition;
|
|
196
|
+
}
|
|
197
|
+
if (schemaChanges !== undefined) {
|
|
198
|
+
setParts.push('schemaChanges = :schemaChanges');
|
|
199
|
+
expressionValues[':schemaChanges'] = schemaChanges;
|
|
200
|
+
}
|
|
201
|
+
if (checksum !== undefined) {
|
|
202
|
+
setParts.push('checksum = :checksum');
|
|
203
|
+
expressionValues[':checksum'] = checksum;
|
|
204
|
+
}
|
|
205
|
+
await this.client.send(new lib_dynamodb_1.TransactWriteCommand({
|
|
206
|
+
TransactItems: [
|
|
207
|
+
this.lockOwnershipCheck(),
|
|
208
|
+
{
|
|
209
|
+
Update: {
|
|
210
|
+
TableName: this.tableName,
|
|
211
|
+
Key: {
|
|
212
|
+
PK: this.trackingPrefix,
|
|
213
|
+
SK: version,
|
|
214
|
+
},
|
|
215
|
+
UpdateExpression: `SET ${setParts.join(', ')} REMOVE #error, failedAt, rolledBackAt`,
|
|
216
|
+
ExpressionAttributeNames: {
|
|
217
|
+
'#status': 'status',
|
|
218
|
+
'#name': 'name',
|
|
219
|
+
'#error': 'error',
|
|
220
|
+
},
|
|
221
|
+
ExpressionAttributeValues: expressionValues,
|
|
222
|
+
// Only allow re-applying if not currently applied
|
|
223
|
+
ConditionExpression: '#status <> :status',
|
|
218
224
|
},
|
|
219
|
-
ExpressionAttributeValues: expressionValues,
|
|
220
|
-
// Only allow re-applying if not currently applied
|
|
221
|
-
ConditionExpression: '#status <> :status',
|
|
222
225
|
},
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
226
|
+
{
|
|
227
|
+
Update: {
|
|
228
|
+
TableName: this.tableName,
|
|
229
|
+
Key: {
|
|
230
|
+
PK: `${this.trackingPrefix}#CURRENT`,
|
|
231
|
+
SK: `${this.trackingPrefix}#CURRENT`,
|
|
232
|
+
},
|
|
233
|
+
UpdateExpression: 'SET currentVersion = :version, updatedAt = :updatedAt, GSI1SK = :gsi1sk',
|
|
234
|
+
ExpressionAttributeValues: {
|
|
235
|
+
':version': version,
|
|
236
|
+
':updatedAt': now,
|
|
237
|
+
':gsi1sk': version,
|
|
238
|
+
},
|
|
236
239
|
},
|
|
237
240
|
},
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
241
|
+
],
|
|
242
|
+
}));
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
// Create new migration record
|
|
246
|
+
await this.client.send(new lib_dynamodb_1.TransactWriteCommand({
|
|
247
|
+
TransactItems: [
|
|
248
|
+
this.lockOwnershipCheck(),
|
|
249
|
+
{
|
|
250
|
+
Put: {
|
|
251
|
+
TableName: this.tableName,
|
|
252
|
+
Item: {
|
|
253
|
+
PK: this.trackingPrefix,
|
|
254
|
+
SK: version,
|
|
255
|
+
version,
|
|
256
|
+
name,
|
|
257
|
+
timestamp: now,
|
|
258
|
+
appliedAt: now,
|
|
259
|
+
status: 'applied',
|
|
260
|
+
schemaDefinition,
|
|
261
|
+
schemaChanges,
|
|
262
|
+
checksum,
|
|
263
|
+
},
|
|
264
|
+
// Ensure migration wasn't already applied (uniqueness on
|
|
265
|
+
// SK; PK is shared across all migration rows).
|
|
266
|
+
ConditionExpression: 'attribute_not_exists(SK)',
|
|
261
267
|
},
|
|
262
|
-
// Ensure migration wasn't already applied (uniqueness on
|
|
263
|
-
// SK; PK is shared across all migration rows).
|
|
264
|
-
ConditionExpression: 'attribute_not_exists(SK)',
|
|
265
268
|
},
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
269
|
+
{
|
|
270
|
+
Update: {
|
|
271
|
+
TableName: this.tableName,
|
|
272
|
+
Key: {
|
|
273
|
+
PK: `${this.trackingPrefix}#CURRENT`,
|
|
274
|
+
SK: `${this.trackingPrefix}#CURRENT`,
|
|
275
|
+
},
|
|
276
|
+
UpdateExpression: 'SET currentVersion = :version, updatedAt = :updatedAt, GSI1SK = :gsi1sk',
|
|
277
|
+
ExpressionAttributeValues: {
|
|
278
|
+
':version': version,
|
|
279
|
+
':updatedAt': now,
|
|
280
|
+
':gsi1sk': version,
|
|
281
|
+
},
|
|
279
282
|
},
|
|
280
283
|
},
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
284
|
+
],
|
|
285
|
+
}));
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
catch (err) {
|
|
289
|
+
await this.handleMarkAsAppliedCancellation(err, version);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Inspect a `TransactionCanceledException` raised by `markAsApplied` and
|
|
294
|
+
* either swallow it (idempotent re-apply) or re-throw a typed error.
|
|
295
|
+
*
|
|
296
|
+
* The TransactWrite items are: [lockOwnershipCheck, migrationRow, currentPointer].
|
|
297
|
+
* Each item produces an entry in `CancellationReasons`.
|
|
298
|
+
* - reasons[0] failing → the lock was lost → MigrationLockLostError.
|
|
299
|
+
* - reasons[1] failing → the migration row already exists in a state the
|
|
300
|
+
* write refused. Re-fetch the record:
|
|
301
|
+
* * status === 'applied' → idempotent re-apply, return silently.
|
|
302
|
+
* * other states → MigrationAlreadyAppliedError with the
|
|
303
|
+
* current state, so the caller can decide what to do.
|
|
304
|
+
*/
|
|
305
|
+
async handleMarkAsAppliedCancellation(err, version) {
|
|
306
|
+
const error = err;
|
|
307
|
+
if (error?.name !== 'TransactionCanceledException') {
|
|
308
|
+
throw err;
|
|
309
|
+
}
|
|
310
|
+
const reasons = error.CancellationReasons ?? [];
|
|
311
|
+
const lockReason = reasons[0];
|
|
312
|
+
const migrationReason = reasons[1];
|
|
313
|
+
if (lockReason?.Code === 'ConditionalCheckFailed') {
|
|
314
|
+
throw new errors_1.MigrationLockLostError(version);
|
|
315
|
+
}
|
|
316
|
+
if (migrationReason?.Code === 'ConditionalCheckFailed') {
|
|
317
|
+
const current = await this.getMigration(version);
|
|
318
|
+
if (current?.status === 'applied') {
|
|
319
|
+
// Either we re-tried our own write or another worker applied the same
|
|
320
|
+
// version. Either way, the desired post-state is already satisfied.
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
throw new errors_1.MigrationAlreadyAppliedError(version, current?.status);
|
|
284
324
|
}
|
|
325
|
+
throw err;
|
|
285
326
|
}
|
|
286
327
|
/**
|
|
287
328
|
* Mark migration as rolled back using TransactWrite for atomicity
|
package/dist/core/tracker.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../src/core/tracker.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../src/core/tracker.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export { MigrationLoader } from './core/loader';
|
|
|
8
8
|
export { MigrationRunner, type RunOptions } from './core/runner';
|
|
9
9
|
export { ConfigLoader, loadConfig } from './core/config';
|
|
10
10
|
export { createDynamoDBClient } from './core/client';
|
|
11
|
+
export { MigrationAlreadyAppliedError, MigrationLockLostError } from './core/errors';
|
|
11
12
|
export { generateMigrationTemplate } from './templates/migration';
|
|
12
13
|
export { createMigration } from './commands/create';
|
|
13
14
|
export { runMigrations } from './commands/up';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,SAAS,CAAC;AAGxB,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,SAAS,CAAC;AAGxB,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,4BAA4B,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAGrF,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAGlE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
18
18
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
19
|
};
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.initProject = exports.showStatus = exports.rollbackMigrations = exports.runMigrations = exports.createMigration = exports.generateMigrationTemplate = exports.createDynamoDBClient = exports.loadConfig = exports.ConfigLoader = exports.MigrationRunner = exports.MigrationLoader = exports.DynamoDBMigrationTracker = void 0;
|
|
21
|
+
exports.initProject = exports.showStatus = exports.rollbackMigrations = exports.runMigrations = exports.createMigration = exports.generateMigrationTemplate = exports.MigrationLockLostError = exports.MigrationAlreadyAppliedError = exports.createDynamoDBClient = exports.loadConfig = exports.ConfigLoader = exports.MigrationRunner = exports.MigrationLoader = exports.DynamoDBMigrationTracker = void 0;
|
|
22
22
|
// Types
|
|
23
23
|
__exportStar(require("./types"), exports);
|
|
24
24
|
// Core
|
|
@@ -33,6 +33,9 @@ Object.defineProperty(exports, "ConfigLoader", { enumerable: true, get: function
|
|
|
33
33
|
Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return config_1.loadConfig; } });
|
|
34
34
|
var client_1 = require("./core/client");
|
|
35
35
|
Object.defineProperty(exports, "createDynamoDBClient", { enumerable: true, get: function () { return client_1.createDynamoDBClient; } });
|
|
36
|
+
var errors_1 = require("./core/errors");
|
|
37
|
+
Object.defineProperty(exports, "MigrationAlreadyAppliedError", { enumerable: true, get: function () { return errors_1.MigrationAlreadyAppliedError; } });
|
|
38
|
+
Object.defineProperty(exports, "MigrationLockLostError", { enumerable: true, get: function () { return errors_1.MigrationLockLostError; } });
|
|
36
39
|
// Template
|
|
37
40
|
var migration_1 = require("./templates/migration");
|
|
38
41
|
Object.defineProperty(exports, "generateMigrationTemplate", { enumerable: true, get: function () { return migration_1.generateMigrationTemplate; } });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;AAEH,QAAQ;AACR,0CAAwB;AAExB,OAAO;AACP,0CAA0D;AAAjD,mHAAA,wBAAwB,OAAA;AACjC,wCAAgD;AAAvC,yGAAA,eAAe,OAAA;AACxB,wCAAiE;AAAxD,yGAAA,eAAe,OAAA;AACxB,wCAAyD;AAAhD,sGAAA,YAAY,OAAA;AAAE,oGAAA,UAAU,OAAA;AACjC,wCAAqD;AAA5C,8GAAA,oBAAoB,OAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;AAEH,QAAQ;AACR,0CAAwB;AAExB,OAAO;AACP,0CAA0D;AAAjD,mHAAA,wBAAwB,OAAA;AACjC,wCAAgD;AAAvC,yGAAA,eAAe,OAAA;AACxB,wCAAiE;AAAxD,yGAAA,eAAe,OAAA;AACxB,wCAAyD;AAAhD,sGAAA,YAAY,OAAA;AAAE,oGAAA,UAAU,OAAA;AACjC,wCAAqD;AAA5C,8GAAA,oBAAoB,OAAA;AAC7B,wCAAqF;AAA5E,sHAAA,4BAA4B,OAAA;AAAE,gHAAA,sBAAsB,OAAA;AAE7D,WAAW;AACX,mDAAkE;AAAzD,sHAAA,yBAAyB,OAAA;AAElC,kCAAkC;AAClC,4CAAoD;AAA3C,yGAAA,eAAe,OAAA;AACxB,oCAA8C;AAArC,mGAAA,aAAa,OAAA;AACtB,wCAAqD;AAA5C,0GAAA,kBAAkB,OAAA;AAC3B,4CAA+C;AAAtC,oGAAA,UAAU,OAAA;AACnB,wCAA8C;AAArC,mGAAA,WAAW,OAAA"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown by `markAsApplied` when the version already has a tracking record
|
|
3
|
+
* in a non-applied state (e.g. `failed`, `rolled_back`) and therefore
|
|
4
|
+
* cannot be silently treated as an idempotent re-apply. Surfaces the
|
|
5
|
+
* existing state so the caller can decide whether to retry, recover, or
|
|
6
|
+
* roll back.
|
|
7
|
+
*/
|
|
8
|
+
export class MigrationAlreadyAppliedError extends Error {
|
|
9
|
+
public readonly version: string;
|
|
10
|
+
public readonly currentStatus: string | undefined;
|
|
11
|
+
|
|
12
|
+
constructor(version: string, currentStatus: string | undefined) {
|
|
13
|
+
super(
|
|
14
|
+
`Migration "${version}" already has a tracking record in state ` +
|
|
15
|
+
`"${currentStatus ?? 'unknown'}" — cannot mark as applied. ` +
|
|
16
|
+
`If you want to re-apply this version, roll it back first ` +
|
|
17
|
+
`(or recover the failed run) and try again.`
|
|
18
|
+
);
|
|
19
|
+
this.name = 'MigrationAlreadyAppliedError';
|
|
20
|
+
this.version = version;
|
|
21
|
+
this.currentStatus = currentStatus;
|
|
22
|
+
if (typeof (Error as unknown as { captureStackTrace?: unknown }).captureStackTrace === 'function') {
|
|
23
|
+
(
|
|
24
|
+
Error as unknown as { captureStackTrace: (target: object, ctor: unknown) => void }
|
|
25
|
+
).captureStackTrace(this, MigrationAlreadyAppliedError);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Thrown when a tracker write is cancelled because the migration lock was
|
|
32
|
+
* taken by another process between `acquireLock()` and the write itself
|
|
33
|
+
* (e.g. the original lock TTL expired and a second worker took over).
|
|
34
|
+
*
|
|
35
|
+
* The transaction was rolled back atomically — no partial state was
|
|
36
|
+
* written. The safe action is to stop the current `up()` / `down()` run.
|
|
37
|
+
*/
|
|
38
|
+
export class MigrationLockLostError extends Error {
|
|
39
|
+
public readonly version: string;
|
|
40
|
+
|
|
41
|
+
constructor(version: string) {
|
|
42
|
+
super(
|
|
43
|
+
`Migration lock was lost during markAsApplied("${version}"). ` +
|
|
44
|
+
`Another worker may have taken over. The transaction was rolled ` +
|
|
45
|
+
`back atomically; no partial state was written.`
|
|
46
|
+
);
|
|
47
|
+
this.name = 'MigrationLockLostError';
|
|
48
|
+
this.version = version;
|
|
49
|
+
if (typeof (Error as unknown as { captureStackTrace?: unknown }).captureStackTrace === 'function') {
|
|
50
|
+
(
|
|
51
|
+
Error as unknown as { captureStackTrace: (target: object, ctor: unknown) => void }
|
|
52
|
+
).captureStackTrace(this, MigrationLockLostError);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
package/src/core/tracker.test.ts
CHANGED
|
@@ -148,3 +148,134 @@ describe('DynamoDBMigrationTracker - tracker writes are gated by lock ownership'
|
|
|
148
148
|
expect(put.Put.ConditionExpression).toBe('attribute_not_exists(SK)');
|
|
149
149
|
});
|
|
150
150
|
});
|
|
151
|
+
|
|
152
|
+
describe('DynamoDBMigrationTracker - markAsApplied idempotency (#10)', () => {
|
|
153
|
+
function cancelledTransactError(reasons: Array<{ Code?: string }>) {
|
|
154
|
+
return Object.assign(new Error('Transaction cancelled'), {
|
|
155
|
+
name: 'TransactionCanceledException',
|
|
156
|
+
CancellationReasons: reasons,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
test('returns silently when the cancellation is because the row is already in status=applied', async () => {
|
|
161
|
+
ddbMock.on(PutCommand).resolves({}); // acquireLock
|
|
162
|
+
// First getMigration → no record (so we take the Put branch)
|
|
163
|
+
// Second getMigration (after cancellation) → already applied
|
|
164
|
+
ddbMock
|
|
165
|
+
.on(GetCommand)
|
|
166
|
+
.resolvesOnce({ Item: undefined })
|
|
167
|
+
.resolvesOnce({
|
|
168
|
+
Item: {
|
|
169
|
+
PK: '_SCHEMA#VERSION',
|
|
170
|
+
SK: '0.1.0',
|
|
171
|
+
version: '0.1.0',
|
|
172
|
+
status: 'applied',
|
|
173
|
+
name: 'init',
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Migration row condition fails (reasons[1]); lock check passed (reasons[0] = None)
|
|
178
|
+
ddbMock.on(TransactWriteCommand).rejects(
|
|
179
|
+
cancelledTransactError([{ Code: 'None' }, { Code: 'ConditionalCheckFailed' }])
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
const tracker = makeTracker();
|
|
183
|
+
await tracker.acquireLock();
|
|
184
|
+
|
|
185
|
+
await expect(tracker.markAsApplied('0.1.0', 'init')).resolves.toBeUndefined();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test('throws MigrationAlreadyAppliedError when the row exists in a non-applied state', async () => {
|
|
189
|
+
ddbMock.on(PutCommand).resolves({});
|
|
190
|
+
ddbMock
|
|
191
|
+
.on(GetCommand)
|
|
192
|
+
.resolvesOnce({ Item: undefined })
|
|
193
|
+
.resolvesOnce({
|
|
194
|
+
Item: {
|
|
195
|
+
PK: '_SCHEMA#VERSION',
|
|
196
|
+
SK: '0.1.0',
|
|
197
|
+
version: '0.1.0',
|
|
198
|
+
status: 'failed',
|
|
199
|
+
name: 'init',
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
ddbMock.on(TransactWriteCommand).rejects(
|
|
204
|
+
cancelledTransactError([{ Code: 'None' }, { Code: 'ConditionalCheckFailed' }])
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
const tracker = makeTracker();
|
|
208
|
+
await tracker.acquireLock();
|
|
209
|
+
|
|
210
|
+
await expect(tracker.markAsApplied('0.1.0', 'init')).rejects.toMatchObject({
|
|
211
|
+
name: 'MigrationAlreadyAppliedError',
|
|
212
|
+
version: '0.1.0',
|
|
213
|
+
currentStatus: 'failed',
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
test('throws MigrationLockLostError when the lock-row ConditionCheck is what failed', async () => {
|
|
218
|
+
ddbMock.on(PutCommand).resolves({});
|
|
219
|
+
ddbMock.on(GetCommand).resolves({ Item: undefined });
|
|
220
|
+
|
|
221
|
+
ddbMock.on(TransactWriteCommand).rejects(
|
|
222
|
+
cancelledTransactError([{ Code: 'ConditionalCheckFailed' }, { Code: 'None' }])
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
const tracker = makeTracker();
|
|
226
|
+
await tracker.acquireLock();
|
|
227
|
+
|
|
228
|
+
await expect(tracker.markAsApplied('0.1.0', 'init')).rejects.toMatchObject({
|
|
229
|
+
name: 'MigrationLockLostError',
|
|
230
|
+
version: '0.1.0',
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test('re-throws unexpected errors unchanged', async () => {
|
|
235
|
+
ddbMock.on(PutCommand).resolves({});
|
|
236
|
+
ddbMock.on(GetCommand).resolves({ Item: undefined });
|
|
237
|
+
|
|
238
|
+
const boom = Object.assign(new Error('upstream blew up'), { name: 'InternalServerError' });
|
|
239
|
+
ddbMock.on(TransactWriteCommand).rejects(boom);
|
|
240
|
+
|
|
241
|
+
const tracker = makeTracker();
|
|
242
|
+
await tracker.acquireLock();
|
|
243
|
+
|
|
244
|
+
await expect(tracker.markAsApplied('0.1.0', 'init')).rejects.toBe(boom);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
test('idempotent path also covers the Update branch (existing record was rolled_back, applied by a racing worker)', async () => {
|
|
248
|
+
ddbMock.on(PutCommand).resolves({});
|
|
249
|
+
// First getMigration → existing rolled_back record (so we take the Update branch)
|
|
250
|
+
// Second getMigration (after cancellation) → already applied (race)
|
|
251
|
+
ddbMock
|
|
252
|
+
.on(GetCommand)
|
|
253
|
+
.resolvesOnce({
|
|
254
|
+
Item: {
|
|
255
|
+
PK: '_SCHEMA#VERSION',
|
|
256
|
+
SK: '0.1.0',
|
|
257
|
+
version: '0.1.0',
|
|
258
|
+
status: 'rolled_back',
|
|
259
|
+
name: 'init',
|
|
260
|
+
},
|
|
261
|
+
})
|
|
262
|
+
.resolvesOnce({
|
|
263
|
+
Item: {
|
|
264
|
+
PK: '_SCHEMA#VERSION',
|
|
265
|
+
SK: '0.1.0',
|
|
266
|
+
version: '0.1.0',
|
|
267
|
+
status: 'applied',
|
|
268
|
+
name: 'init',
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
ddbMock.on(TransactWriteCommand).rejects(
|
|
273
|
+
cancelledTransactError([{ Code: 'None' }, { Code: 'ConditionalCheckFailed' }])
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
const tracker = makeTracker();
|
|
277
|
+
await tracker.acquireLock();
|
|
278
|
+
|
|
279
|
+
await expect(tracker.markAsApplied('0.1.0', 'init')).resolves.toBeUndefined();
|
|
280
|
+
});
|
|
281
|
+
});
|
package/src/core/tracker.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
} from '@aws-sdk/lib-dynamodb';
|
|
10
10
|
import { MigrationTracker, MigrationRecord, SchemaChange, MigrationConfig } from '../types';
|
|
11
11
|
import { compareSemver } from './semver';
|
|
12
|
+
import { MigrationAlreadyAppliedError, MigrationLockLostError } from './errors';
|
|
12
13
|
|
|
13
14
|
/** Default lock TTL in seconds. Configurable via MigrationConfig.lockTtlSeconds. */
|
|
14
15
|
export const DEFAULT_LOCK_TTL_SECONDS = 300; // 5 minutes
|
|
@@ -229,116 +230,160 @@ export class DynamoDBMigrationTracker implements MigrationTracker {
|
|
|
229
230
|
// Check if migration record already exists (e.g., rolled back or failed)
|
|
230
231
|
const existing = await this.getMigration(version);
|
|
231
232
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
233
|
+
try {
|
|
234
|
+
if (existing) {
|
|
235
|
+
// Update existing record (re-applying a rolled back or failed migration)
|
|
236
|
+
// Build dynamic update expression - DynamoDB doesn't accept undefined values
|
|
237
|
+
const setParts = ['#status = :status', 'appliedAt = :appliedAt', '#name = :name'];
|
|
238
|
+
const expressionValues: Record<string, any> = {
|
|
239
|
+
':status': 'applied',
|
|
240
|
+
':appliedAt': now,
|
|
241
|
+
':name': name,
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
if (schemaDefinition !== undefined) {
|
|
245
|
+
setParts.push('schemaDefinition = :schemaDef');
|
|
246
|
+
expressionValues[':schemaDef'] = schemaDefinition;
|
|
247
|
+
}
|
|
248
|
+
if (schemaChanges !== undefined) {
|
|
249
|
+
setParts.push('schemaChanges = :schemaChanges');
|
|
250
|
+
expressionValues[':schemaChanges'] = schemaChanges;
|
|
251
|
+
}
|
|
252
|
+
if (checksum !== undefined) {
|
|
253
|
+
setParts.push('checksum = :checksum');
|
|
254
|
+
expressionValues[':checksum'] = checksum;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
await this.client.send(
|
|
258
|
+
new TransactWriteCommand({
|
|
259
|
+
TransactItems: [
|
|
260
|
+
this.lockOwnershipCheck(),
|
|
261
|
+
{
|
|
262
|
+
Update: {
|
|
263
|
+
TableName: this.tableName,
|
|
264
|
+
Key: {
|
|
265
|
+
PK: this.trackingPrefix,
|
|
266
|
+
SK: version,
|
|
267
|
+
},
|
|
268
|
+
UpdateExpression: `SET ${setParts.join(', ')} REMOVE #error, failedAt, rolledBackAt`,
|
|
269
|
+
ExpressionAttributeNames: {
|
|
270
|
+
'#status': 'status',
|
|
271
|
+
'#name': 'name',
|
|
272
|
+
'#error': 'error',
|
|
273
|
+
},
|
|
274
|
+
ExpressionAttributeValues: expressionValues,
|
|
275
|
+
// Only allow re-applying if not currently applied
|
|
276
|
+
ConditionExpression: '#status <> :status',
|
|
271
277
|
},
|
|
272
|
-
ExpressionAttributeValues: expressionValues,
|
|
273
|
-
// Only allow re-applying if not currently applied
|
|
274
|
-
ConditionExpression: '#status <> :status',
|
|
275
278
|
},
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
279
|
+
{
|
|
280
|
+
Update: {
|
|
281
|
+
TableName: this.tableName,
|
|
282
|
+
Key: {
|
|
283
|
+
PK: `${this.trackingPrefix}#CURRENT`,
|
|
284
|
+
SK: `${this.trackingPrefix}#CURRENT`,
|
|
285
|
+
},
|
|
286
|
+
UpdateExpression:
|
|
287
|
+
'SET currentVersion = :version, updatedAt = :updatedAt, GSI1SK = :gsi1sk',
|
|
288
|
+
ExpressionAttributeValues: {
|
|
289
|
+
':version': version,
|
|
290
|
+
':updatedAt': now,
|
|
291
|
+
':gsi1sk': version,
|
|
292
|
+
},
|
|
290
293
|
},
|
|
291
294
|
},
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
ConditionExpression: 'attribute_not_exists(SK)',
|
|
320
|
-
},
|
|
321
|
-
},
|
|
322
|
-
{
|
|
323
|
-
Update: {
|
|
324
|
-
TableName: this.tableName,
|
|
325
|
-
Key: {
|
|
326
|
-
PK: `${this.trackingPrefix}#CURRENT`,
|
|
327
|
-
SK: `${this.trackingPrefix}#CURRENT`,
|
|
295
|
+
],
|
|
296
|
+
})
|
|
297
|
+
);
|
|
298
|
+
} else {
|
|
299
|
+
// Create new migration record
|
|
300
|
+
await this.client.send(
|
|
301
|
+
new TransactWriteCommand({
|
|
302
|
+
TransactItems: [
|
|
303
|
+
this.lockOwnershipCheck(),
|
|
304
|
+
{
|
|
305
|
+
Put: {
|
|
306
|
+
TableName: this.tableName,
|
|
307
|
+
Item: {
|
|
308
|
+
PK: this.trackingPrefix,
|
|
309
|
+
SK: version,
|
|
310
|
+
version,
|
|
311
|
+
name,
|
|
312
|
+
timestamp: now,
|
|
313
|
+
appliedAt: now,
|
|
314
|
+
status: 'applied',
|
|
315
|
+
schemaDefinition,
|
|
316
|
+
schemaChanges,
|
|
317
|
+
checksum,
|
|
318
|
+
} as MigrationRecord,
|
|
319
|
+
// Ensure migration wasn't already applied (uniqueness on
|
|
320
|
+
// SK; PK is shared across all migration rows).
|
|
321
|
+
ConditionExpression: 'attribute_not_exists(SK)',
|
|
328
322
|
},
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
Update: {
|
|
326
|
+
TableName: this.tableName,
|
|
327
|
+
Key: {
|
|
328
|
+
PK: `${this.trackingPrefix}#CURRENT`,
|
|
329
|
+
SK: `${this.trackingPrefix}#CURRENT`,
|
|
330
|
+
},
|
|
331
|
+
UpdateExpression:
|
|
332
|
+
'SET currentVersion = :version, updatedAt = :updatedAt, GSI1SK = :gsi1sk',
|
|
333
|
+
ExpressionAttributeValues: {
|
|
334
|
+
':version': version,
|
|
335
|
+
':updatedAt': now,
|
|
336
|
+
':gsi1sk': version,
|
|
337
|
+
},
|
|
335
338
|
},
|
|
336
339
|
},
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
340
|
+
],
|
|
341
|
+
})
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
} catch (err: unknown) {
|
|
345
|
+
await this.handleMarkAsAppliedCancellation(err, version);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Inspect a `TransactionCanceledException` raised by `markAsApplied` and
|
|
351
|
+
* either swallow it (idempotent re-apply) or re-throw a typed error.
|
|
352
|
+
*
|
|
353
|
+
* The TransactWrite items are: [lockOwnershipCheck, migrationRow, currentPointer].
|
|
354
|
+
* Each item produces an entry in `CancellationReasons`.
|
|
355
|
+
* - reasons[0] failing → the lock was lost → MigrationLockLostError.
|
|
356
|
+
* - reasons[1] failing → the migration row already exists in a state the
|
|
357
|
+
* write refused. Re-fetch the record:
|
|
358
|
+
* * status === 'applied' → idempotent re-apply, return silently.
|
|
359
|
+
* * other states → MigrationAlreadyAppliedError with the
|
|
360
|
+
* current state, so the caller can decide what to do.
|
|
361
|
+
*/
|
|
362
|
+
private async handleMarkAsAppliedCancellation(
|
|
363
|
+
err: unknown,
|
|
364
|
+
version: string
|
|
365
|
+
): Promise<void> {
|
|
366
|
+
const error = err as { name?: string; CancellationReasons?: Array<{ Code?: string }> } | null;
|
|
367
|
+
if (error?.name !== 'TransactionCanceledException') {
|
|
368
|
+
throw err;
|
|
369
|
+
}
|
|
370
|
+
const reasons = error.CancellationReasons ?? [];
|
|
371
|
+
const lockReason = reasons[0];
|
|
372
|
+
const migrationReason = reasons[1];
|
|
373
|
+
|
|
374
|
+
if (lockReason?.Code === 'ConditionalCheckFailed') {
|
|
375
|
+
throw new MigrationLockLostError(version);
|
|
376
|
+
}
|
|
377
|
+
if (migrationReason?.Code === 'ConditionalCheckFailed') {
|
|
378
|
+
const current = await this.getMigration(version);
|
|
379
|
+
if (current?.status === 'applied') {
|
|
380
|
+
// Either we re-tried our own write or another worker applied the same
|
|
381
|
+
// version. Either way, the desired post-state is already satisfied.
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
throw new MigrationAlreadyAppliedError(version, current?.status);
|
|
341
385
|
}
|
|
386
|
+
throw err;
|
|
342
387
|
}
|
|
343
388
|
|
|
344
389
|
/**
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ export { MigrationLoader } from './core/loader';
|
|
|
12
12
|
export { MigrationRunner, type RunOptions } from './core/runner';
|
|
13
13
|
export { ConfigLoader, loadConfig } from './core/config';
|
|
14
14
|
export { createDynamoDBClient } from './core/client';
|
|
15
|
+
export { MigrationAlreadyAppliedError, MigrationLockLostError } from './core/errors';
|
|
15
16
|
|
|
16
17
|
// Template
|
|
17
18
|
export { generateMigrationTemplate } from './templates/migration';
|