@hotmeshio/hotmesh
Version:
Permanent-Memory Workflows & AI Agents
78 lines (77 loc) • 2.93 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.execHookBatch = void 0;
const hook_1 = require("./hook");
const waitFor_1 = require("./waitFor");
/**
* Executes multiple hooks in parallel and awaits all their signal responses.
* This solves the race condition where Promise.all() with execHook() would prevent
* all waitFor() registrations from completing.
*
* The method ensures all waitFor() registrations happen before any hooks execute,
* preventing signals from being sent before the framework is ready to receive them.
*
* @template T - Object type with keys matching the batch hook keys and values as expected response types
* @param {BatchHookConfig[]} hookConfigs - Array of hook configurations with unique keys
* @returns {Promise<T>} Object with keys from hookConfigs and values as the signal responses
*
* @example
* ```typescript
* // Execute multiple research perspectives in parallel
* const results = await MemFlow.workflow.execHookBatch<{
* optimistic: OptimisticResult;
* skeptical: SkepticalResult;
* }>([
* {
* key: 'optimistic',
* options: {
* taskQueue: 'agents',
* workflowName: 'optimisticPerspective',
* args: [query],
* signalId: 'optimistic-complete'
* }
* },
* {
* key: 'skeptical',
* options: {
* taskQueue: 'agents',
* workflowName: 'skepticalPerspective',
* args: [query],
* signalId: 'skeptical-complete'
* }
* }
* ]);
*
* // results.optimistic contains the OptimisticResult
* // results.skeptical contains the SkepticalResult
* ```
*/
async function execHookBatch(hookConfigs) {
// Generate signal IDs for hooks that don't have them
const processedConfigs = hookConfigs.map(config => ({
...config,
options: {
...config.options,
signalId: config.options.signalId || `memflow-hook-${crypto.randomUUID()}`
}
}));
// STEP 1: Fire off all hooks (but don't await them)
// This registers the hooks/streams with the system immediately
await Promise.all(processedConfigs.map(config => {
const hookOptions = {
...config.options,
args: [...config.options.args, {
signal: config.options.signalId,
$memflow: true
}]
};
return (0, hook_1.hook)(hookOptions);
}));
// STEP 2: Await all waitFor operations
// This ensures all waitFor registrations happen in the same call stack
// before any MemFlowWaitForError is thrown (via setImmediate mechanism)
const results = await Promise.all(processedConfigs.map(config => (0, waitFor_1.waitFor)(config.options.signalId)));
// STEP 3: Return results as a keyed object
return Object.fromEntries(processedConfigs.map((config, i) => [config.key, results[i]]));
}
exports.execHookBatch = execHookBatch;