mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-11 13:10:49 +08:00
Internalize all IM channel implementations
This commit is contained in:
parent
8996476693
commit
bd469f58f8
95 changed files with 25012 additions and 100 deletions
98
test/channels/feishu/connection-supervisor.test.mjs
Normal file
98
test/channels/feishu/connection-supervisor.test.mjs
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { ConnectionSupervisor } from '../../../plugin-src/host/channels/feishu/connection-supervisor.mjs';
|
||||
|
||||
const flush = () => new Promise((resolve) => setImmediate(resolve));
|
||||
|
||||
function scheduler() {
|
||||
const pending = [];
|
||||
return {
|
||||
pending,
|
||||
setTimeoutImpl(callback, delay) {
|
||||
const handle = { callback, delay, cancelled: false, unref() {} };
|
||||
pending.push(handle);
|
||||
return handle;
|
||||
},
|
||||
clearTimeoutImpl(handle) {
|
||||
handle.cancelled = true;
|
||||
},
|
||||
async runNext() {
|
||||
const handle = pending.shift();
|
||||
assert.ok(handle, 'expected a scheduled supervisor pass');
|
||||
assert.equal(handle.cancelled, false);
|
||||
handle.callback();
|
||||
await flush();
|
||||
await flush();
|
||||
return handle.delay;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
test('supervisor waits for the in-process Harness Host before initializing bots', async () => {
|
||||
const timers = scheduler();
|
||||
const warnings = [];
|
||||
let healthChecks = 0;
|
||||
let initializations = 0;
|
||||
const controller = {
|
||||
async initialize() { initializations += 1; },
|
||||
status() { return { totals: { configured: 1, connected: 1 } }; },
|
||||
};
|
||||
const supervisor = new ConnectionSupervisor({
|
||||
controller,
|
||||
harness: {
|
||||
async ensureRunning() {
|
||||
healthChecks += 1;
|
||||
if (healthChecks < 3) throw new Error('Host is still starting');
|
||||
},
|
||||
},
|
||||
logger: { warn: (...args) => warnings.push(args) },
|
||||
retryDelaysMs: [5, 10],
|
||||
healthyIntervalMs: 100,
|
||||
setTimeoutImpl: timers.setTimeoutImpl,
|
||||
clearTimeoutImpl: timers.clearTimeoutImpl,
|
||||
}).start();
|
||||
|
||||
assert.equal(await timers.runNext(), 0);
|
||||
assert.equal(initializations, 0);
|
||||
assert.equal(timers.pending[0].delay, 5);
|
||||
await timers.runNext();
|
||||
assert.equal(initializations, 0);
|
||||
assert.equal(timers.pending[0].delay, 10);
|
||||
await timers.runNext();
|
||||
assert.equal(await supervisor.ready.then((status) => status.totals.connected), 1);
|
||||
assert.equal(initializations, 1);
|
||||
assert.equal(timers.pending[0].delay, 100);
|
||||
assert.equal(warnings.length, 2);
|
||||
|
||||
await supervisor.close();
|
||||
assert.equal(timers.pending[0].cancelled, true);
|
||||
});
|
||||
|
||||
test('supervisor retries an offline bot and leaves the recovered connection on the health interval', async () => {
|
||||
const timers = scheduler();
|
||||
let initializations = 0;
|
||||
const controller = {
|
||||
async initialize() { initializations += 1; },
|
||||
status() {
|
||||
return { totals: { configured: 1, connected: initializations >= 2 ? 1 : 0 } };
|
||||
},
|
||||
};
|
||||
const supervisor = new ConnectionSupervisor({
|
||||
controller,
|
||||
harness: { async ensureRunning() {} },
|
||||
logger: { warn() {} },
|
||||
retryDelaysMs: [7],
|
||||
healthyIntervalMs: 101,
|
||||
setTimeoutImpl: timers.setTimeoutImpl,
|
||||
clearTimeoutImpl: timers.clearTimeoutImpl,
|
||||
}).start();
|
||||
|
||||
await timers.runNext();
|
||||
assert.equal(initializations, 1);
|
||||
assert.equal(timers.pending[0].delay, 7);
|
||||
await timers.runNext();
|
||||
assert.equal(initializations, 2);
|
||||
assert.equal(timers.pending[0].delay, 101);
|
||||
|
||||
await supervisor.close();
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue