feat(runner): /status meldet bekannte Dev-Spezifikationen (known)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-09-30 21:54:01 +00:00
1 parent 96c26fb9b8
commit 19cd8f90ce
4 files changed
+13 -3

No files matched your search

+3 -1
View File
@@ -184,6 +184,8 @@ export function createDev({
await e.promise.catch(() => {});
if (!entries.has(sub)) await rmDir(join(config.workRoot, 'dev', sub)).catch(() => {}); // Arbeitsordner aufräumen
}
// R18: Subdomains mit gemerkter Spezifikation (auch schlafende); das Portal registriert fehlende nach.
const known = () => [...specs.keys()];
const list = () => [...entries.values()].map((e) => ({ sub: e.sub, state: e.state, lastUsed: e.lastUsed, sha: e.sha }));
function status(sub) {
const e = entries.get(sub);
@@ -200,5 +202,5 @@ export function createDev({
}
const idle = () => Promise.all([...entries.values()].map((e) => e.promise)).then(() => {});
return { ensure, register, wake, touch, markDead, stop, list, status, sweep, cleanupOrphans, idle };
return { ensure, register, wake, touch, markDead, known, stop, list, status, sweep, cleanupOrphans, idle };
}
+1 -1
View File
@@ -55,7 +55,7 @@ export function createApiServer({ config, jobs, dev, mem = readMemAvailable }) {
const method = req.method;
if (method === 'GET' && url.pathname === '/status') {
return send(res, 200, { dev: dev.list(), queue: jobs.queueLength(), memAvailable: mem() });
return send(res, 200, { dev: dev.list(), known: dev.known ? dev.known() : [], queue: jobs.queueLength(), memAvailable: mem() });
}
if (method === 'POST' && url.pathname === '/jobs/build') {
const v = validateJob(await readJson(req));
+8
View File
@@ -344,3 +344,11 @@ test('I7: markDead entfernt den Container und setzt sleeping', async () => {
assert.equal(s.dev.list().find((e) => e.sub === 'a').state, 'sleeping');
assert.equal((await s.dev.wake('a')).state, 'starting');
});
test('R18: known liefert Subdomains mit Spezifikation (auch ohne Eintrag), stop vergisst sie', async () => {
const s = setup();
await s.dev.register('a', job('a'));
assert.deepEqual(s.dev.known(), ['a']);
await s.dev.stop('a');
assert.deepEqual(s.dev.known(), []);
});
+1 -1
View File
@@ -64,7 +64,7 @@ test('GET /status', async () => {
await withServer(config, async (base) => {
const r = await fetch(`${base}/status`, { headers: auth });
assert.equal(r.status, 200);
assert.deepEqual(await r.json(), { dev: [], queue: 0, memAvailable: 123 });
assert.deepEqual(await r.json(), { dev: [], known: [], queue: 0, memAvailable: 123 });
});
});