feat: add shadow LangGraph orchestrator runtime

This commit is contained in:
john
2026-07-24 21:25:40 +08:00
parent 46ea22b342
commit 24336d0178
29 changed files with 3247 additions and 25 deletions
+73 -2
View File
@@ -146,6 +146,72 @@ function engineCatalog(config) {
];
}
async function probeServiceHealth(config, {
fetchImpl = globalThis.fetch,
} = {}) {
const checkedAt = Date.now();
if (!config.serviceUrl) {
return {
checkedAt,
ok: false,
status: 'unconfigured',
latencyMs: 0,
httpStatus: null,
details: null,
};
}
if (typeof fetchImpl !== 'function') {
return {
checkedAt,
ok: false,
status: 'fetch_unavailable',
latencyMs: 0,
httpStatus: null,
details: null,
};
}
const startedAt = Date.now();
const controller = new AbortController();
const timer = setTimeout(
() => controller.abort(),
Math.max(500, Number(config.requestTimeoutMs) || 5000),
);
try {
const response = await fetchImpl(`${config.serviceUrl}/ready`, {
headers: { accept: 'application/json' },
signal: controller.signal,
});
const body = await response.json().catch(() => null);
const healthy = response.ok && body?.status === 'ok';
return {
checkedAt,
ok: healthy,
status: healthy ? 'healthy' : 'unhealthy',
latencyMs: Math.max(0, Date.now() - startedAt),
httpStatus: response.status,
details: body && typeof body === 'object' ? {
service: body.service == null ? null : String(body.service).slice(0, 128),
checkpoint: body.checkpoint && typeof body.checkpoint === 'object' ? {
kind: body.checkpoint.kind == null ? null : String(body.checkpoint.kind).slice(0, 64),
durable: Boolean(body.checkpoint.durable),
} : null,
execution: body.execution == null ? null : String(body.execution).slice(0, 64),
} : null,
};
} catch (error) {
return {
checkedAt,
ok: false,
status: error?.name === 'AbortError' ? 'timeout' : 'unreachable',
latencyMs: Math.max(0, Date.now() - startedAt),
httpStatus: null,
details: null,
};
} finally {
clearTimeout(timer);
}
}
async function ensureConfigTable(pool) {
await pool.query(`
CREATE TABLE IF NOT EXISTS ${CONFIG_TABLE} (
@@ -177,7 +243,10 @@ async function loadStoredState(pool) {
};
}
export function createOrchestratorAdminConfigService(pool, { env = process.env } = {}) {
export function createOrchestratorAdminConfigService(pool, {
env = process.env,
fetchImpl = globalThis.fetch,
} = {}) {
async function loadEffectiveState() {
const stored = await loadStoredState(pool);
if (stored) return { ...stored, source: 'admin-db' };
@@ -232,12 +301,13 @@ export function createOrchestratorAdminConfigService(pool, { env = process.env }
return this.getAdminConfig();
},
async getRuntimeState() {
async getRuntimeState({ probe = false } = {}) {
const state = await loadEffectiveState();
return {
...state,
runtime: runtimeState(state.config, env),
engines: engineCatalog(state.config),
...(probe ? { serviceHealth: await probeServiceHealth(state.config, { fetchImpl }) } : {}),
};
},
@@ -292,5 +362,6 @@ export const orchestratorAdminConfigInternals = {
CONFIG_SCOPE,
CONFIG_TABLE,
engineCatalog,
probeServiceHealth,
runtimeState,
};