feat(migration): add lock heartbeats, predictive dry-run planning, and stricter ledger option validation
This commit is contained in:
@@ -117,6 +117,42 @@ tap.test('run: ctx.startSession works inside a step', async () => {
|
||||
expect(sessionWasUsed).toBeTrue();
|
||||
});
|
||||
|
||||
tap.test('run: lock heartbeat prevents concurrent execution of a slow step', async () => {
|
||||
let activeSteps = 0;
|
||||
let maxActiveSteps = 0;
|
||||
let totalCalls = 0;
|
||||
|
||||
const createRunner = () => {
|
||||
const m = new SmartMigration({
|
||||
targetVersion: '1.1.0',
|
||||
db,
|
||||
ledgerName: 'lock_heartbeat',
|
||||
lockTtlMs: 100,
|
||||
lockWaitMs: 1_500,
|
||||
});
|
||||
|
||||
m.step('slow-step').from('1.0.0').to('1.1.0').up(async () => {
|
||||
totalCalls++;
|
||||
activeSteps++;
|
||||
maxActiveSteps = Math.max(maxActiveSteps, activeSteps);
|
||||
await new Promise((resolve) => setTimeout(resolve, 900));
|
||||
activeSteps--;
|
||||
});
|
||||
|
||||
return m;
|
||||
};
|
||||
|
||||
const firstRun = createRunner().run();
|
||||
await new Promise((resolve) => setTimeout(resolve, 20));
|
||||
const secondRun = createRunner().run();
|
||||
|
||||
const [firstResult, secondResult] = await Promise.all([firstRun, secondRun]);
|
||||
expect(firstResult.stepsApplied).toHaveLength(1);
|
||||
expect(secondResult.wasUpToDate).toBeTrue();
|
||||
expect(totalCalls).toEqual(1);
|
||||
expect(maxActiveSteps).toEqual(1);
|
||||
});
|
||||
|
||||
tap.test('cleanup: close shared db', async () => {
|
||||
await cleanup();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user