mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-07-27 16:49:51 -07:00
115 lines
3.5 KiB
TypeScript
115 lines
3.5 KiB
TypeScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import {
|
|
createDefaultSyncHostsState,
|
|
upsertSyncHost,
|
|
recordSyncResult,
|
|
type SyncHostsState,
|
|
} from '../../shared/sync/sync-hosts-store';
|
|
import { createSyncAutoScheduler } from './sync-auto-scheduler';
|
|
|
|
function makeState(): SyncHostsState {
|
|
let state = createDefaultSyncHostsState();
|
|
state = upsertSyncHost(state, { host: 'auto-box', autoSync: true, direction: 'both' }, 0);
|
|
state = upsertSyncHost(state, { host: 'manual-box', autoSync: false }, 0);
|
|
return state;
|
|
}
|
|
|
|
test('tick triggers a due auto-sync host with its saved direction', () => {
|
|
let state = makeState();
|
|
state = upsertSyncHost(state, { host: 'auto-box', autoSync: true, direction: 'pull' }, 0);
|
|
const triggered: Array<{ host: string; direction: string }> = [];
|
|
const scheduler = createSyncAutoScheduler({
|
|
readState: () => state,
|
|
isRunning: () => false,
|
|
canAutoSync: () => true,
|
|
triggerHostSync: (host, direction) => triggered.push({ host, direction }),
|
|
nowMs: () => 100 * 60_000,
|
|
});
|
|
|
|
scheduler.tick();
|
|
assert.deepEqual(triggered, [{ host: 'auto-box', direction: 'pull' }]);
|
|
});
|
|
|
|
test('tick skips hosts synced more recently than the interval', () => {
|
|
let state = makeState();
|
|
state = recordSyncResult(state, 'auto-box', { atMs: 90 * 60_000, status: 'success', detail: null });
|
|
const triggered: string[] = [];
|
|
const scheduler = createSyncAutoScheduler({
|
|
readState: () => state,
|
|
isRunning: () => false,
|
|
canAutoSync: () => true,
|
|
triggerHostSync: (host) => triggered.push(host),
|
|
nowMs: () => 100 * 60_000, // 10 minutes later, default interval 30
|
|
});
|
|
|
|
scheduler.tick();
|
|
assert.deepEqual(triggered, []);
|
|
});
|
|
|
|
test('tick does nothing while a run is active or auto sync is blocked', () => {
|
|
const state = makeState();
|
|
const triggered: string[] = [];
|
|
const running = createSyncAutoScheduler({
|
|
readState: () => state,
|
|
isRunning: () => true,
|
|
canAutoSync: () => true,
|
|
triggerHostSync: (host) => triggered.push(host),
|
|
nowMs: () => 100 * 60_000,
|
|
});
|
|
running.tick();
|
|
|
|
const blocked = createSyncAutoScheduler({
|
|
readState: () => state,
|
|
isRunning: () => false,
|
|
canAutoSync: () => false,
|
|
triggerHostSync: (host) => triggered.push(host),
|
|
nowMs: () => 100 * 60_000,
|
|
});
|
|
blocked.tick();
|
|
|
|
assert.deepEqual(triggered, []);
|
|
});
|
|
|
|
test('tick triggers at most one host per tick', () => {
|
|
let state = makeState();
|
|
state = upsertSyncHost(state, { host: 'second-box', autoSync: true }, 0);
|
|
const triggered: string[] = [];
|
|
const scheduler = createSyncAutoScheduler({
|
|
readState: () => state,
|
|
isRunning: () => false,
|
|
canAutoSync: () => true,
|
|
triggerHostSync: (host) => triggered.push(host),
|
|
nowMs: () => 100 * 60_000,
|
|
});
|
|
|
|
scheduler.tick();
|
|
assert.equal(triggered.length, 1);
|
|
});
|
|
|
|
test('start/stop manage the interval timer', () => {
|
|
const state = makeState();
|
|
let setCalls = 0;
|
|
let clearCalls = 0;
|
|
const scheduler = createSyncAutoScheduler({
|
|
readState: () => state,
|
|
isRunning: () => false,
|
|
canAutoSync: () => true,
|
|
triggerHostSync: () => {},
|
|
nowMs: () => 0,
|
|
setIntervalFn: ((): NodeJS.Timeout => {
|
|
setCalls += 1;
|
|
return 42 as unknown as NodeJS.Timeout;
|
|
}) as unknown as typeof setInterval,
|
|
clearIntervalFn: (() => {
|
|
clearCalls += 1;
|
|
}) as unknown as typeof clearInterval,
|
|
});
|
|
|
|
scheduler.start();
|
|
scheduler.start(); // idempotent
|
|
assert.equal(setCalls, 1);
|
|
scheduler.stop();
|
|
assert.equal(clearCalls, 1);
|
|
});
|