feat: persist blocked executor jobs

This commit is contained in:
john
2026-07-24 23:07:46 +08:00
parent d21c4849a9
commit bbb43f97a3
17 changed files with 649 additions and 26 deletions
+42
View File
@@ -1,6 +1,7 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { MemorySaver } from '@langchain/langgraph';
import { createInMemoryExecutorJobStore } from './executor-gateway.mjs';
import { createLangGraphOrchestratorRuntime } from './runtime.mjs';
function runSpec(overrides = {}) {
@@ -35,6 +36,14 @@ test('LangGraph runtime checkpoints a deterministic observe-only code workflow',
assert.equal(state.result.observed, true);
assert.equal(state.result.executed, false);
assert.equal(state.plan.executorAdapter, 'native-agent-run');
assert.deepEqual(state.plan.executorJob, {
kind: 'executor-job',
id: 'run-shadow-1:executor-preview',
executor: 'goosed',
status: 'blocked',
reason: 'executor_dispatch_not_implemented',
durable: false,
});
const restored = await runtime.getState('run-shadow-1');
assert.deepEqual(restored, state);
@@ -66,6 +75,39 @@ test('LangGraph runtime is idempotent by run id', async () => {
assert.equal((await runtime.listEvents('run-shadow-1')).events.length, 3);
});
test('LangGraph runtime persists a durable blocked Executor Job and probes both stores', async () => {
const checkpointProbeCalls = [];
const executorProbeCalls = [];
const executorJobStore = {
...createInMemoryExecutorJobStore(),
kind: 'postgres',
durable: true,
};
const runtime = createLangGraphOrchestratorRuntime({
checkpointer: new MemorySaver(),
checkpointKind: 'postgres',
durable: true,
checkpointProbe: async () => checkpointProbeCalls.push('checkpoint'),
executorJobStore,
executorJobProbe: async () => executorProbeCalls.push('executor-jobs'),
});
const state = await runtime.start(runSpec());
assert.equal(state.plan.executorJob.durable, true);
assert.equal(
(await executorJobStore.getById('run-shadow-1:executor-preview')).status,
'blocked',
);
const ready = await runtime.ready();
assert.equal(ready.ready, true);
assert.equal(ready.executorGateway.store.kind, 'postgres');
assert.equal(ready.executorGateway.store.durable, true);
assert.equal(ready.executorGateway.executionEnabled, false);
assert.deepEqual(checkpointProbeCalls, ['checkpoint']);
assert.deepEqual(executorProbeCalls, ['executor-jobs']);
});
test('LangGraph runtime rejects execution-enabled and unsupported workflows', async () => {
const runtime = createLangGraphOrchestratorRuntime({
checkpointer: new MemorySaver(),