Files
qinglong/test/back/schedule-health.test.cjs
whyour 15d54866a8 feat: migrate SQLite runtime and verify complete upgrade bundles
Use MikroORM's official Node SQLite dialect with bounded database isolation, preserve legacy schema and data for rollback, and require Node 22.17 or newer. Update Debian runtimes and retain ARMv6 musl compatibility without a SQLite addon.

Complete short archive writes, stop orphaned SQL workers after owner death, preserve buffered startup requests, and prestart the archived backend on every platform. Cover real package installation, migration, failure recovery, and legacy database compatibility.

Keep authentication storage failures distinct from expired sessions with a pinned Keyv runtime, propagated cache errors, and retryable HTTP 503 responses. Preserve genuine 401 failures and verify legacy cache bytes, initialization safety, and session recovery.
2026-10-22 13:47:26 +08:00

101 lines
3.6 KiB
JavaScript

const assert = require('node:assert/strict');
const fs = require('node:fs/promises');
const http = require('node:http');
const os = require('node:os');
const path = require('node:path');
const test = require('node:test');
const config = require('../../back/config').default;
const { check } = require('../../back/schedule/health');
function runCheck(service = 'cron') {
return new Promise((resolve) => {
check({ request: { service } }, (error, response) => {
resolve({ error, response });
});
});
}
test('schedule health check uses the HTTP health endpoint and system logs', async (t) => {
const originalBaseUrl = config.baseUrl;
const originalPort = config.port;
const originalSystemLogPath = config.systemLogPath;
const originalContainer = process.env.QL_CONTAINER;
t.after(() => {
config.baseUrl = originalBaseUrl;
config.port = originalPort;
config.systemLogPath = originalSystemLogPath;
if (originalContainer === undefined) {
delete process.env.QL_CONTAINER;
} else {
process.env.QL_CONTAINER = originalContainer;
}
});
await t.test(
'returns serving for a healthy prefixed HTTP service',
async () => {
let requestedUrl = '';
const server = http.createServer((request, response) => {
requestedUrl = request.url;
response.setHeader('Content-Type', 'application/json');
response.end(JSON.stringify({ code: 200, data: { status: 'ok' } }));
});
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
t.after(() => new Promise((resolve) => server.close(resolve)));
config.baseUrl = '/ql';
config.port = server.address().port;
const result = await runCheck();
assert.equal(result.error, null);
assert.deepEqual(result.response, { status: 1 });
assert.equal(requestedUrl, '/ql/api/health');
},
);
await t.test(
'reports recent system logs when HTTP startup fails',
async () => {
const logDir = await fs.mkdtemp(path.join(os.tmpdir(), 'ql-health-'));
t.after(() => fs.rm(logDir, { recursive: true, force: true }));
const lines = Array.from(
{ length: 305 },
(_, index) => `line-${index + 1}`,
);
await fs.writeFile(path.join(logDir, '2026-08-16.log'), 'older-log');
await fs.writeFile(path.join(logDir, '2026-08-17.log'), lines.join('\n'));
config.systemLogPath = logDir;
config.port = 1;
process.env.QL_CONTAINER = 'true';
const result = await runCheck();
assert.equal(result.response, undefined);
assert.match(result.error.message, /ECONNREFUSED|connect/);
assert.match(
result.error.message,
/http:\/\/localhost:1\/ql\/api\/health/,
);
assert.match(result.error.message, /docker logs <container>/);
assert.match(result.error.message, /line-305/);
assert.doesNotMatch(result.error.message, /line-1\n/);
assert.doesNotMatch(result.error.message, /qinglong-error\.log/);
},
);
});
test('scheduler liveness reports a failed database process without calling HTTP', async () => {
const load=require('../helpers/load-security-module.cjs');
const database={healthy:true};
const {check}=load('back/schedule/health.ts',{
'../data':{database},
'../config':{},
undici:{request:()=>assert.fail('local scheduler checks must not call HTTP')},
});
const probe=()=>new Promise(resolve=>check({request:{service:'scheduler'}},(error,response)=>resolve({error,response})));
assert.deepEqual((await probe()).response,{status:1});
database.healthy=false;
assert.deepEqual((await probe()).response,{status:2});
});