@langchain/langgraph
Version:
LangGraph
548 lines (546 loc) • 25 kB
JavaScript
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
const require_errors = require('../errors.cjs');
const require_base = require('../channels/base.cjs');
const require_constants = require('../constants.cjs');
const require_utils = require('../utils.cjs');
const require_hash = require('../hash.cjs');
const require_io = require('./io.cjs');
const require_index = require('./utils/index.cjs');
const require_algo = require('./algo.cjs');
const require_debug = require('./debug.cjs');
const require_stream = require('./stream.cjs');
const __langchain_langgraph_checkpoint = require_rolldown_runtime.__toESM(require("@langchain/langgraph-checkpoint"));
//#region src/pregel/loop.ts
const INPUT_DONE = Symbol.for("INPUT_DONE");
const INPUT_RESUMING = Symbol.for("INPUT_RESUMING");
const DEFAULT_LOOP_LIMIT = 25;
function createDuplexStream(...streams) {
return new require_stream.IterableReadableWritableStream({
passthroughFn: (value) => {
for (const stream of streams) if (stream.modes.has(value[1])) stream.push(value);
},
modes: new Set(streams.flatMap((s) => Array.from(s.modes)))
});
}
var AsyncBatchedCache = class extends __langchain_langgraph_checkpoint.BaseCache {
cache;
queue = Promise.resolve();
constructor(cache) {
super();
this.cache = cache;
}
async get(keys) {
return this.enqueueOperation("get", keys);
}
async set(pairs) {
return this.enqueueOperation("set", pairs);
}
async clear(namespaces) {
return this.enqueueOperation("clear", namespaces);
}
async stop() {
await this.queue;
}
enqueueOperation(type, ...args) {
const newPromise = this.queue.then(() => {
return this.cache[type](...args);
});
this.queue = newPromise.then(() => void 0, () => void 0);
return newPromise;
}
};
var PregelLoop = class PregelLoop {
input;
output;
config;
checkpointer;
checkpointerGetNextVersion;
channels;
checkpoint;
checkpointIdSaved;
checkpointConfig;
checkpointMetadata;
checkpointNamespace;
checkpointPendingWrites = [];
checkpointPreviousVersions;
step;
stop;
durability;
outputKeys;
streamKeys;
nodes;
skipDoneTasks;
prevCheckpointConfig;
updatedChannels;
status = "pending";
tasks = {};
stream;
checkpointerPromises = [];
isNested;
_checkpointerChainedPromise = Promise.resolve();
store;
cache;
manager;
interruptAfter;
interruptBefore;
toInterrupt = [];
debug = false;
triggerToNodes;
get isResuming() {
let hasChannelVersions = false;
if (require_constants.START in this.checkpoint.channel_versions) hasChannelVersions = true;
else for (const chan in this.checkpoint.channel_versions) if (Object.prototype.hasOwnProperty.call(this.checkpoint.channel_versions, chan)) {
hasChannelVersions = true;
break;
}
const configHasResumingFlag = this.config.configurable?.[require_constants.CONFIG_KEY_RESUMING] !== void 0;
const configIsResuming = configHasResumingFlag && this.config.configurable?.[require_constants.CONFIG_KEY_RESUMING];
const inputIsNullOrUndefined = this.input === null || this.input === void 0;
const inputIsCommandResuming = require_constants.isCommand(this.input) && this.input.resume != null;
const inputIsResuming = this.input === INPUT_RESUMING;
const runIdMatchesPrevious = !this.isNested && this.config.metadata?.run_id !== void 0 && this.checkpointMetadata?.run_id !== void 0 && this.config.metadata.run_id === this.checkpointMetadata?.run_id;
return hasChannelVersions && (configIsResuming || inputIsNullOrUndefined || inputIsCommandResuming || inputIsResuming || runIdMatchesPrevious);
}
constructor(params) {
this.input = params.input;
this.checkpointer = params.checkpointer;
if (this.checkpointer !== void 0) this.checkpointerGetNextVersion = this.checkpointer.getNextVersion.bind(this.checkpointer);
else this.checkpointerGetNextVersion = require_algo.increment;
this.checkpoint = params.checkpoint;
this.checkpointMetadata = params.checkpointMetadata;
this.checkpointPreviousVersions = params.checkpointPreviousVersions;
this.channels = params.channels;
this.checkpointPendingWrites = params.checkpointPendingWrites;
this.step = params.step;
this.stop = params.stop;
this.config = params.config;
this.checkpointConfig = params.checkpointConfig;
this.isNested = params.isNested;
this.manager = params.manager;
this.outputKeys = params.outputKeys;
this.streamKeys = params.streamKeys;
this.nodes = params.nodes;
this.skipDoneTasks = params.skipDoneTasks;
this.store = params.store;
this.cache = params.cache ? new AsyncBatchedCache(params.cache) : void 0;
this.stream = params.stream;
this.checkpointNamespace = params.checkpointNamespace;
this.prevCheckpointConfig = params.prevCheckpointConfig;
this.interruptAfter = params.interruptAfter;
this.interruptBefore = params.interruptBefore;
this.durability = params.durability;
this.debug = params.debug;
this.triggerToNodes = params.triggerToNodes;
}
static async initialize(params) {
let { config, stream } = params;
if (stream !== void 0 && config.configurable?.[require_constants.CONFIG_KEY_STREAM] !== void 0) stream = createDuplexStream(stream, config.configurable[require_constants.CONFIG_KEY_STREAM]);
const skipDoneTasks = config.configurable ? !("checkpoint_id" in config.configurable) : true;
const scratchpad = config.configurable?.[require_constants.CONFIG_KEY_SCRATCHPAD];
if (config.configurable && scratchpad) {
if (scratchpad.subgraphCounter > 0) config = require_index.patchConfigurable(config, { [require_constants.CONFIG_KEY_CHECKPOINT_NS]: [config.configurable[require_constants.CONFIG_KEY_CHECKPOINT_NS], scratchpad.subgraphCounter.toString()].join(require_constants.CHECKPOINT_NAMESPACE_SEPARATOR) });
scratchpad.subgraphCounter += 1;
}
const isNested = require_constants.CONFIG_KEY_READ in (config.configurable ?? {});
if (!isNested && config.configurable?.checkpoint_ns !== void 0 && config.configurable?.checkpoint_ns !== "") config = require_index.patchConfigurable(config, {
checkpoint_ns: "",
checkpoint_id: void 0
});
let checkpointConfig = config;
if (config.configurable?.[require_constants.CONFIG_KEY_CHECKPOINT_MAP] !== void 0 && config.configurable?.[require_constants.CONFIG_KEY_CHECKPOINT_MAP]?.[config.configurable?.checkpoint_ns]) checkpointConfig = require_index.patchConfigurable(config, { checkpoint_id: config.configurable[require_constants.CONFIG_KEY_CHECKPOINT_MAP][config.configurable?.checkpoint_ns] });
const checkpointNamespace = config.configurable?.checkpoint_ns?.split(require_constants.CHECKPOINT_NAMESPACE_SEPARATOR) ?? [];
const saved = await params.checkpointer?.getTuple(checkpointConfig) ?? {
config,
checkpoint: (0, __langchain_langgraph_checkpoint.emptyCheckpoint)(),
metadata: {
source: "input",
step: -2,
parents: {}
},
pendingWrites: []
};
checkpointConfig = {
...config,
...saved.config,
configurable: {
checkpoint_ns: "",
...config.configurable,
...saved.config.configurable
}
};
const prevCheckpointConfig = saved.parentConfig;
const checkpoint = (0, __langchain_langgraph_checkpoint.copyCheckpoint)(saved.checkpoint);
const checkpointMetadata = { ...saved.metadata };
const checkpointPendingWrites = saved.pendingWrites ?? [];
const channels = require_base.emptyChannels(params.channelSpecs, checkpoint);
const step = (checkpointMetadata.step ?? 0) + 1;
const stop = step + (config.recursionLimit ?? DEFAULT_LOOP_LIMIT) + 1;
const checkpointPreviousVersions = { ...checkpoint.channel_versions };
const store = params.store ? new __langchain_langgraph_checkpoint.AsyncBatchedStore(params.store) : void 0;
if (store) await store.start();
return new PregelLoop({
input: params.input,
config,
checkpointer: params.checkpointer,
checkpoint,
checkpointMetadata,
checkpointConfig,
prevCheckpointConfig,
checkpointNamespace,
channels,
isNested,
manager: params.manager,
skipDoneTasks,
step,
stop,
checkpointPreviousVersions,
checkpointPendingWrites,
outputKeys: params.outputKeys ?? [],
streamKeys: params.streamKeys ?? [],
nodes: params.nodes,
stream,
store,
cache: params.cache,
interruptAfter: params.interruptAfter,
interruptBefore: params.interruptBefore,
durability: params.durability,
debug: params.debug,
triggerToNodes: params.triggerToNodes
});
}
_checkpointerPutAfterPrevious(input) {
this._checkpointerChainedPromise = this._checkpointerChainedPromise.then(() => {
return this.checkpointer?.put(input.config, input.checkpoint, input.metadata, input.newVersions);
});
this.checkpointerPromises.push(this._checkpointerChainedPromise);
}
/**
* Put writes for a task, to be read by the next tick.
* @param taskId
* @param writes
*/
putWrites(taskId, writes) {
let writesCopy = writes;
if (writesCopy.length === 0) return;
if (writesCopy.every(([key]) => key in __langchain_langgraph_checkpoint.WRITES_IDX_MAP)) writesCopy = Array.from(new Map(writesCopy.map((w) => [w[0], w])).values());
this.checkpointPendingWrites = this.checkpointPendingWrites.filter((w) => w[0] !== taskId);
for (const [c, v] of writesCopy) this.checkpointPendingWrites.push([
taskId,
c,
v
]);
const config = require_index.patchConfigurable(this.checkpointConfig, {
[require_constants.CONFIG_KEY_CHECKPOINT_NS]: this.config.configurable?.checkpoint_ns ?? "",
[require_constants.CONFIG_KEY_CHECKPOINT_ID]: this.checkpoint.id
});
if (this.durability !== "exit" && this.checkpointer != null) this.checkpointerPromises.push(this.checkpointer.putWrites(config, writesCopy, taskId));
if (this.tasks) this._outputWrites(taskId, writesCopy);
if (!writes.length || !this.cache || !this.tasks) return;
const task = this.tasks[taskId];
if (task == null || task.cache_key == null) return;
if (writes[0][0] === require_constants.ERROR || writes[0][0] === require_constants.INTERRUPT) return;
this.cache.set([{
key: [task.cache_key.ns, task.cache_key.key],
value: task.writes,
ttl: task.cache_key.ttl
}]);
}
_outputWrites(taskId, writes, cached = false) {
const task = this.tasks[taskId];
if (task !== void 0) {
if (task.config !== void 0 && (task.config.tags ?? []).includes(require_constants.TAG_HIDDEN)) return;
if (writes.length > 0) {
if (writes[0][0] === require_constants.INTERRUPT) {
if (task.path?.[0] === require_constants.PUSH && task.path?.at(-1) === true) return;
const interruptWrites = writes.filter((w) => w[0] === require_constants.INTERRUPT).flatMap((w) => w[1]);
this._emit([["updates", { [require_constants.INTERRUPT]: interruptWrites }], ["values", { [require_constants.INTERRUPT]: interruptWrites }]]);
} else if (writes[0][0] !== require_constants.ERROR) this._emit(require_utils.gatherIteratorSync(require_utils.prefixGenerator(require_io.mapOutputUpdates(this.outputKeys, [[task, writes]], cached), "updates")));
}
if (!cached) this._emit(require_utils.gatherIteratorSync(require_utils.prefixGenerator(require_debug.mapDebugTaskResults([[task, writes]], this.streamKeys), "tasks")));
}
}
async _matchCachedWrites() {
if (!this.cache) return [];
const matched = [];
const serializeKey = ([ns, key]) => {
return `ns:${ns.join(",")}|key:${key}`;
};
const keys = [];
const keyMap = {};
for (const task of Object.values(this.tasks)) if (task.cache_key != null && !task.writes.length) {
keys.push([task.cache_key.ns, task.cache_key.key]);
keyMap[serializeKey([task.cache_key.ns, task.cache_key.key])] = task;
}
if (keys.length === 0) return [];
const cache = await this.cache.get(keys);
for (const { key, value } of cache) {
const task = keyMap[serializeKey(key)];
if (task != null) {
task.writes.push(...value);
matched.push({
task,
result: value
});
}
}
return matched;
}
/**
* Execute a single iteration of the Pregel loop.
* Returns true if more iterations are needed.
* @param params
*/
async tick(params) {
if (this.store && !this.store.isRunning) await this.store?.start();
const { inputKeys = [] } = params;
if (this.status !== "pending") throw new Error(`Cannot tick when status is no longer "pending". Current status: "${this.status}"`);
if (![INPUT_DONE, INPUT_RESUMING].includes(this.input)) await this._first(inputKeys);
else if (this.toInterrupt.length > 0) {
this.status = "interrupt_before";
throw new require_errors.GraphInterrupt();
} else if (Object.values(this.tasks).every((task) => task.writes.length > 0)) {
const writes = Object.values(this.tasks).flatMap((t) => t.writes);
this.updatedChannels = require_algo._applyWrites(this.checkpoint, this.channels, Object.values(this.tasks), this.checkpointerGetNextVersion, this.triggerToNodes);
const valuesOutput = await require_utils.gatherIterator(require_utils.prefixGenerator(require_io.mapOutputValues(this.outputKeys, writes, this.channels), "values"));
this._emit(valuesOutput);
this.checkpointPendingWrites = [];
await this._putCheckpoint({ source: "loop" });
if (require_algo.shouldInterrupt(this.checkpoint, this.interruptAfter, Object.values(this.tasks))) {
this.status = "interrupt_after";
throw new require_errors.GraphInterrupt();
}
if (this.config.configurable?.[require_constants.CONFIG_KEY_RESUMING] !== void 0) delete this.config.configurable?.[require_constants.CONFIG_KEY_RESUMING];
} else return false;
if (this.step > this.stop) {
this.status = "out_of_steps";
return false;
}
const nextTasks = require_algo._prepareNextTasks(this.checkpoint, this.checkpointPendingWrites, this.nodes, this.channels, this.config, true, {
step: this.step,
checkpointer: this.checkpointer,
isResuming: this.isResuming,
manager: this.manager,
store: this.store,
stream: this.stream,
triggerToNodes: this.triggerToNodes,
updatedChannels: this.updatedChannels
});
this.tasks = nextTasks;
if (this.checkpointer) this._emit(await require_utils.gatherIterator(require_utils.prefixGenerator(require_debug.mapDebugCheckpoint(this.checkpointConfig, this.channels, this.streamKeys, this.checkpointMetadata, Object.values(this.tasks), this.checkpointPendingWrites, this.prevCheckpointConfig, this.outputKeys), "checkpoints")));
if (Object.values(this.tasks).length === 0) {
this.status = "done";
return false;
}
if (this.skipDoneTasks && this.checkpointPendingWrites.length > 0) {
for (const [tid, k, v] of this.checkpointPendingWrites) {
if (k === require_constants.ERROR || k === require_constants.INTERRUPT || k === require_constants.RESUME) continue;
const task = Object.values(this.tasks).find((t) => t.id === tid);
if (task) task.writes.push([k, v]);
}
for (const task of Object.values(this.tasks)) if (task.writes.length > 0) this._outputWrites(task.id, task.writes, true);
}
if (Object.values(this.tasks).every((task) => task.writes.length > 0)) return this.tick({ inputKeys });
if (require_algo.shouldInterrupt(this.checkpoint, this.interruptBefore, Object.values(this.tasks))) {
this.status = "interrupt_before";
throw new require_errors.GraphInterrupt();
}
const debugOutput = await require_utils.gatherIterator(require_utils.prefixGenerator(require_debug.mapDebugTasks(Object.values(this.tasks)), "tasks"));
this._emit(debugOutput);
return true;
}
async finishAndHandleError(error) {
if (this.durability === "exit" && (!this.isNested || typeof error !== "undefined" || this.checkpointNamespace.every((part) => !part.includes(require_constants.CHECKPOINT_NAMESPACE_END)))) {
this._putCheckpoint(this.checkpointMetadata);
this._flushPendingWrites();
}
const suppress = this._suppressInterrupt(error);
if (suppress || error === void 0) this.output = require_io.readChannels(this.channels, this.outputKeys);
if (suppress) {
if (this.tasks !== void 0 && this.checkpointPendingWrites.length > 0 && Object.values(this.tasks).some((task) => task.writes.length > 0)) {
this.updatedChannels = require_algo._applyWrites(this.checkpoint, this.channels, Object.values(this.tasks), this.checkpointerGetNextVersion, this.triggerToNodes);
this._emit(require_utils.gatherIteratorSync(require_utils.prefixGenerator(require_io.mapOutputValues(this.outputKeys, Object.values(this.tasks).flatMap((t) => t.writes), this.channels), "values")));
}
if (require_errors.isGraphInterrupt(error) && !error.interrupts.length) this._emit([["updates", { [require_constants.INTERRUPT]: [] }], ["values", { [require_constants.INTERRUPT]: [] }]]);
}
return suppress;
}
async acceptPush(task, writeIdx, call) {
if (this.interruptAfter?.length > 0 && require_algo.shouldInterrupt(this.checkpoint, this.interruptAfter, [task])) {
this.toInterrupt.push(task);
return;
}
const pushed = require_algo._prepareSingleTask([
require_constants.PUSH,
task.path ?? [],
writeIdx,
task.id,
call
], this.checkpoint, this.checkpointPendingWrites, this.nodes, this.channels, task.config ?? {}, true, {
step: this.step,
checkpointer: this.checkpointer,
manager: this.manager,
store: this.store,
stream: this.stream
});
if (!pushed) return;
if (this.interruptBefore?.length > 0 && require_algo.shouldInterrupt(this.checkpoint, this.interruptBefore, [pushed])) {
this.toInterrupt.push(pushed);
return;
}
this._emit(require_utils.gatherIteratorSync(require_utils.prefixGenerator(require_debug.mapDebugTasks([pushed]), "tasks")));
if (this.debug) require_debug.printStepTasks(this.step, [pushed]);
this.tasks[pushed.id] = pushed;
if (this.skipDoneTasks) this._matchWrites({ [pushed.id]: pushed });
const tasks = await this._matchCachedWrites();
for (const { task: task$1 } of tasks) this._outputWrites(task$1.id, task$1.writes, true);
return pushed;
}
_suppressInterrupt(e) {
return require_errors.isGraphInterrupt(e) && !this.isNested;
}
async _first(inputKeys) {
const { configurable } = this.config;
const scratchpad = configurable?.[require_constants.CONFIG_KEY_SCRATCHPAD];
if (scratchpad && scratchpad.nullResume !== void 0) this.putWrites(require_constants.NULL_TASK_ID, [[require_constants.RESUME, scratchpad.nullResume]]);
if (require_constants.isCommand(this.input)) {
const hasResume = this.input.resume != null;
if (this.input.resume != null && typeof this.input.resume === "object" && Object.keys(this.input.resume).every(require_hash.isXXH3)) {
this.config.configurable ??= {};
this.config.configurable[require_constants.CONFIG_KEY_RESUME_MAP] = this.input.resume;
}
if (hasResume && this.checkpointer == null) throw new Error("Cannot use Command(resume=...) without checkpointer");
const writes = {};
for (const [tid, key, value] of require_io.mapCommand(this.input, this.checkpointPendingWrites)) {
writes[tid] ??= [];
writes[tid].push([key, value]);
}
if (Object.keys(writes).length === 0) throw new require_errors.EmptyInputError("Received empty Command input");
for (const [tid, ws] of Object.entries(writes)) this.putWrites(tid, ws);
}
const nullWrites = (this.checkpointPendingWrites ?? []).filter((w) => w[0] === require_constants.NULL_TASK_ID).map((w) => w.slice(1));
if (nullWrites.length > 0) require_algo._applyWrites(this.checkpoint, this.channels, [{
name: require_constants.INPUT,
writes: nullWrites,
triggers: []
}], this.checkpointerGetNextVersion, this.triggerToNodes);
const isCommandUpdateOrGoto = require_constants.isCommand(this.input) && nullWrites.length > 0;
if (this.isResuming || isCommandUpdateOrGoto) {
for (const channelName in this.channels) {
if (!Object.prototype.hasOwnProperty.call(this.channels, channelName)) continue;
if (this.checkpoint.channel_versions[channelName] !== void 0) {
const version = this.checkpoint.channel_versions[channelName];
this.checkpoint.versions_seen[require_constants.INTERRUPT] = {
...this.checkpoint.versions_seen[require_constants.INTERRUPT],
[channelName]: version
};
}
}
const valuesOutput = await require_utils.gatherIterator(require_utils.prefixGenerator(require_io.mapOutputValues(this.outputKeys, true, this.channels), "values"));
this._emit(valuesOutput);
}
if (this.isResuming) this.input = INPUT_RESUMING;
else if (isCommandUpdateOrGoto) {
await this._putCheckpoint({ source: "input" });
this.input = INPUT_DONE;
} else {
const inputWrites = await require_utils.gatherIterator(require_io.mapInput(inputKeys, this.input));
if (inputWrites.length > 0) {
const discardTasks = require_algo._prepareNextTasks(this.checkpoint, this.checkpointPendingWrites, this.nodes, this.channels, this.config, true, { step: this.step });
this.updatedChannels = require_algo._applyWrites(this.checkpoint, this.channels, Object.values(discardTasks).concat([{
name: require_constants.INPUT,
writes: inputWrites,
triggers: []
}]), this.checkpointerGetNextVersion, this.triggerToNodes);
await this._putCheckpoint({ source: "input" });
this.input = INPUT_DONE;
} else if (!(require_constants.CONFIG_KEY_RESUMING in (this.config.configurable ?? {}))) throw new require_errors.EmptyInputError(`Received no input writes for ${JSON.stringify(inputKeys, null, 2)}`);
else this.input = INPUT_DONE;
}
if (!this.isNested) this.config = require_index.patchConfigurable(this.config, { [require_constants.CONFIG_KEY_RESUMING]: this.isResuming });
}
_emit(values) {
for (const [mode, payload] of values) {
if (this.stream.modes.has(mode)) this.stream.push([
this.checkpointNamespace,
mode,
payload
]);
if ((mode === "checkpoints" || mode === "tasks") && this.stream.modes.has("debug")) {
const step = mode === "checkpoints" ? this.step - 1 : this.step;
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
const type = (() => {
if (mode === "checkpoints") return "checkpoint";
else if (typeof payload === "object" && payload != null && "result" in payload) return "task_result";
else return "task";
})();
this.stream.push([
this.checkpointNamespace,
"debug",
{
step,
type,
timestamp,
payload
}
]);
}
}
}
_putCheckpoint(inputMetadata) {
const exiting = this.checkpointMetadata === inputMetadata;
const doCheckpoint = this.checkpointer != null && (this.durability !== "exit" || exiting);
const storeCheckpoint = (checkpoint) => {
this.prevCheckpointConfig = this.checkpointConfig?.configurable?.checkpoint_id ? this.checkpointConfig : void 0;
this.checkpointConfig = require_index.patchConfigurable(this.checkpointConfig, { [require_constants.CONFIG_KEY_CHECKPOINT_NS]: this.config.configurable?.checkpoint_ns ?? "" });
const channelVersions = { ...this.checkpoint.channel_versions };
const newVersions = require_index.getNewChannelVersions(this.checkpointPreviousVersions, channelVersions);
this.checkpointPreviousVersions = channelVersions;
this._checkpointerPutAfterPrevious({
config: { ...this.checkpointConfig },
checkpoint: (0, __langchain_langgraph_checkpoint.copyCheckpoint)(checkpoint),
metadata: { ...this.checkpointMetadata },
newVersions
});
this.checkpointConfig = {
...this.checkpointConfig,
configurable: {
...this.checkpointConfig.configurable,
checkpoint_id: this.checkpoint.id
}
};
};
if (!exiting) this.checkpointMetadata = {
...inputMetadata,
step: this.step,
parents: this.config.configurable?.[require_constants.CONFIG_KEY_CHECKPOINT_MAP] ?? {}
};
this.checkpoint = require_base.createCheckpoint(this.checkpoint, doCheckpoint ? this.channels : void 0, this.step, exiting ? { id: this.checkpoint.id } : void 0);
if (doCheckpoint) storeCheckpoint(this.checkpoint);
if (!exiting) this.step += 1;
}
_flushPendingWrites() {
if (this.checkpointer == null) return;
if (this.checkpointPendingWrites.length === 0) return;
const config = require_index.patchConfigurable(this.checkpointConfig, {
[require_constants.CONFIG_KEY_CHECKPOINT_NS]: this.config.configurable?.checkpoint_ns ?? "",
[require_constants.CONFIG_KEY_CHECKPOINT_ID]: this.checkpoint.id
});
const byTask = {};
for (const [tid, key, value] of this.checkpointPendingWrites) {
byTask[tid] ??= [];
byTask[tid].push([key, value]);
}
for (const [tid, ws] of Object.entries(byTask)) this.checkpointerPromises.push(this.checkpointer.putWrites(config, ws, tid));
}
_matchWrites(tasks) {
for (const [tid, k, v] of this.checkpointPendingWrites) {
if (k === require_constants.ERROR || k === require_constants.INTERRUPT || k === require_constants.RESUME) continue;
const task = Object.values(tasks).find((t) => t.id === tid);
if (task) task.writes.push([k, v]);
}
for (const task of Object.values(tasks)) if (task.writes.length > 0) this._outputWrites(task.id, task.writes, true);
}
};
//#endregion
exports.PregelLoop = PregelLoop;
//# sourceMappingURL=loop.cjs.map