mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
feat(ql3): establish 3.0 incubation baseline
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
require('ts-node/register/transpile-only');
|
||||
|
||||
const assert = require('node:assert/strict');
|
||||
const { test } = require('node:test');
|
||||
const {
|
||||
LegacyExecutionRegistry,
|
||||
} = require('../../back/runtime/compatibility/legacyExecutionRegistry');
|
||||
|
||||
function acceptedFact(legacyCronId) {
|
||||
return {
|
||||
origin: 'manual',
|
||||
projectId: 'default',
|
||||
taskId: `legacy-cron:${legacyCronId}`,
|
||||
taskRevision: 'sha256:revision',
|
||||
legacyCronId,
|
||||
triggerType: 'manual',
|
||||
acceptedAtMs: 100,
|
||||
};
|
||||
}
|
||||
|
||||
function recorder(label, calls) {
|
||||
return {
|
||||
spawned: (fact) => calls.push([label, 'spawned', fact]),
|
||||
running: (fact) => calls.push([label, 'running', fact]),
|
||||
startFailed: (fact) => calls.push([label, 'start_failed', fact]),
|
||||
exited: (fact) => calls.push([label, 'exited', fact]),
|
||||
cancelled: (fact) => calls.push([label, 'cancelled', fact]),
|
||||
};
|
||||
}
|
||||
|
||||
test('correlates local callbacks by log, then pid, and removes terminal entries', () => {
|
||||
const calls = [];
|
||||
const registry = new LegacyExecutionRegistry();
|
||||
const first = registry.register(acceptedFact(7), recorder('first', calls));
|
||||
const second = registry.register(acceptedFact(7), recorder('second', calls));
|
||||
first.spawned({ atMs: 101, pid: 11, logArtifactId: 'log-first' });
|
||||
second.spawned({ atMs: 101, pid: 22, logArtifactId: 'log-second' });
|
||||
|
||||
assert.equal(
|
||||
registry.callback({
|
||||
legacyCronId: 7,
|
||||
pid: 999,
|
||||
logArtifactId: 'log-second',
|
||||
atMs: 102,
|
||||
phase: 'running',
|
||||
}),
|
||||
1,
|
||||
);
|
||||
assert.equal(
|
||||
registry.callback({
|
||||
legacyCronId: 7,
|
||||
pid: 11,
|
||||
atMs: 103,
|
||||
phase: 'finished',
|
||||
exitCode: 0,
|
||||
}),
|
||||
1,
|
||||
);
|
||||
assert.equal(registry.size(), 1);
|
||||
assert.equal(
|
||||
registry.cancel({
|
||||
legacyCronId: 7,
|
||||
atMs: 104,
|
||||
scope: 'all',
|
||||
reason: 'user',
|
||||
}),
|
||||
1,
|
||||
);
|
||||
assert.equal(registry.size(), 0);
|
||||
assert.deepEqual(
|
||||
calls.map(([label, operation]) => [label, operation]),
|
||||
[
|
||||
['first', 'spawned'],
|
||||
['second', 'spawned'],
|
||||
['second', 'spawned'],
|
||||
['second', 'running'],
|
||||
['first', 'exited'],
|
||||
['second', 'cancelled'],
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
test('refuses ambiguous one-instance correlation and bounds local memory', () => {
|
||||
const calls = [];
|
||||
let overflows = 0;
|
||||
const registry = new LegacyExecutionRegistry({
|
||||
maxEntries: 1,
|
||||
onOverflow: () => {
|
||||
overflows += 1;
|
||||
},
|
||||
});
|
||||
registry.register(acceptedFact(8), recorder('tracked', calls));
|
||||
const untracked = registry.register(
|
||||
acceptedFact(8),
|
||||
recorder('untracked', calls),
|
||||
);
|
||||
|
||||
assert.equal(overflows, 1);
|
||||
assert.equal(registry.size(), 1);
|
||||
untracked.running({ atMs: 200 });
|
||||
assert.equal(
|
||||
registry.callback({
|
||||
legacyCronId: 8,
|
||||
atMs: 201,
|
||||
phase: 'finished',
|
||||
}),
|
||||
1,
|
||||
);
|
||||
assert.equal(registry.size(), 0);
|
||||
assert.deepEqual(
|
||||
calls.map(([label, operation]) => [label, operation]),
|
||||
[
|
||||
['untracked', 'running'],
|
||||
['tracked', 'exited'],
|
||||
],
|
||||
);
|
||||
|
||||
const ambiguous = new LegacyExecutionRegistry();
|
||||
ambiguous.register(acceptedFact(9), recorder('a', calls));
|
||||
ambiguous.register(acceptedFact(9), recorder('b', calls));
|
||||
assert.equal(
|
||||
ambiguous.callback({
|
||||
legacyCronId: 9,
|
||||
atMs: 300,
|
||||
phase: 'running',
|
||||
}),
|
||||
0,
|
||||
);
|
||||
|
||||
const conflicting = new LegacyExecutionRegistry();
|
||||
const left = conflicting.register(acceptedFact(12), recorder('left', calls));
|
||||
const right = conflicting.register(
|
||||
acceptedFact(12),
|
||||
recorder('right', calls),
|
||||
);
|
||||
left.spawned({ atMs: 1, pid: 1, logArtifactId: 'left-log' });
|
||||
right.spawned({ atMs: 1, pid: 2, logArtifactId: 'right-log' });
|
||||
assert.equal(
|
||||
conflicting.callback({
|
||||
legacyCronId: 12,
|
||||
pid: 1,
|
||||
logArtifactId: 'right-log',
|
||||
atMs: 2,
|
||||
phase: 'finished',
|
||||
}),
|
||||
0,
|
||||
);
|
||||
});
|
||||
|
||||
test('cleans up entries after start failures and direct terminal observations', () => {
|
||||
const calls = [];
|
||||
const registry = new LegacyExecutionRegistry();
|
||||
const failed = registry.register(acceptedFact(10), recorder('failed', calls));
|
||||
failed.startFailed({ atMs: 2, errorCode: 'SPAWN_FAILED' });
|
||||
const exited = registry.register(acceptedFact(11), recorder('exited', calls));
|
||||
exited.exited({ atMs: 3, exitCode: 1 });
|
||||
|
||||
assert.equal(registry.size(), 0);
|
||||
});
|
||||
|
||||
test('swallows local observer failures and reports them out of band', () => {
|
||||
let failures = 0;
|
||||
const registry = new LegacyExecutionRegistry({
|
||||
onDispatchFailure: () => {
|
||||
failures += 1;
|
||||
},
|
||||
});
|
||||
const throwing = {
|
||||
spawned() {
|
||||
throw new Error('spawned failed');
|
||||
},
|
||||
running() {
|
||||
throw new Error('running failed');
|
||||
},
|
||||
startFailed() {
|
||||
throw new Error('start failed');
|
||||
},
|
||||
exited() {
|
||||
throw new Error('exit failed');
|
||||
},
|
||||
cancelled() {
|
||||
throw new Error('cancel failed');
|
||||
},
|
||||
};
|
||||
const observation = registry.register(acceptedFact(13), throwing);
|
||||
|
||||
assert.doesNotThrow(() => {
|
||||
observation.spawned({ atMs: 1, pid: 13 });
|
||||
observation.running({ atMs: 2 });
|
||||
registry.cancel({
|
||||
legacyCronId: 13,
|
||||
pid: 13,
|
||||
atMs: 3,
|
||||
scope: 'one',
|
||||
reason: 'user',
|
||||
});
|
||||
});
|
||||
assert.equal(failures, 3);
|
||||
assert.equal(registry.size(), 0);
|
||||
});
|
||||
Reference in New Issue
Block a user