@convex-dev/workflow
Version:
Convex component for durably executing workflows.
115 lines • 3.88 kB
JavaScript
import { BaseChannel } from "async-channel";
import { parse } from "convex-helpers/validators";
import { safeFunctionName } from "./safeFunctionName.js";
export function createWorkflowCtx(workflowId, sender) {
return {
workflowId,
runQuery: async (query, args, opts) => {
return runFunction(sender, "query", query, args, opts);
},
runMutation: async (mutation, args, opts) => {
return runFunction(sender, "mutation", mutation, args, opts);
},
runAction: async (action, args, opts) => {
return runFunction(sender, "action", action, args, opts);
},
runWorkflow: async (workflow, args, opts) => {
const { name, unstableArgs, ...schedulerOptions } = opts ?? {};
return run(sender, {
name: name ?? safeFunctionName(workflow),
target: {
kind: "workflow",
function: workflow,
args,
},
retry: undefined,
inline: false,
unstableArgs: unstableArgs ?? false,
schedulerOptions,
transactionLimits: undefined,
});
},
sleep: async (duration, opts) => {
await run(sender, {
name: opts?.name ?? "sleep",
target: {
kind: "sleep",
args: {},
},
retry: undefined,
inline: false,
unstableArgs: false,
schedulerOptions: { runAfter: duration },
transactionLimits: undefined,
});
},
awaitEvent: async (event) => {
const result = await run(sender, {
name: event.name ?? event.id ?? "Event",
target: {
kind: "event",
args: { eventId: event.id },
},
retry: undefined,
inline: false,
unstableArgs: false,
schedulerOptions: {},
transactionLimits: undefined,
});
if (event.validator) {
return parse(event.validator, result);
}
return result;
},
};
}
async function runFunction(sender, functionType, f, args, opts) {
const { name, retry, inline, transactionLimits, unstableArgs, ...schedulerOptions } = opts ?? {};
if (inline &&
schedulerOptions &&
(schedulerOptions.runAt || schedulerOptions.runAfter)) {
throw new Error("Cannot combine `inline` with `runAt` or `runAfter`.");
}
if (inline && functionType === "action") {
throw new Error("Cannot run an action inline.");
}
if (!inline && transactionLimits) {
throw new Error("Cannot set transaction limits for non-inline functions.");
}
return run(sender, {
name: name ?? safeFunctionName(f),
target: {
kind: "function",
functionType,
function: f,
args: args ?? {},
},
retry,
inline: inline ?? false,
unstableArgs: unstableArgs ?? false,
transactionLimits,
schedulerOptions,
});
}
async function run(sender, request) {
let send;
const p = new Promise((resolve) => {
send = sender.push({
...request,
resolve,
});
});
await send;
const result = await p;
switch (result.kind) {
case "success":
return result.returnValue;
case "failed":
throw new Error(result.error);
case "canceled":
throw new Error("Canceled");
default:
throw new Error("Unknown result kind: " + result.kind);
}
}
//# sourceMappingURL=workflowContext.js.map