feat: Workflow engine modules (#6128)
This commit is contained in:
committed by
GitHub
parent
d85fee42ee
commit
302323916b
@@ -26,3 +26,16 @@ workflow()
|
||||
.then((res) => {
|
||||
console.log(res.result) // result: { step2: { test: "test", test2: "step1" } }
|
||||
})
|
||||
|
||||
/*type type0 = typeof workflow extends ReturnWorkflow<infer T, infer R, infer X>
|
||||
? T
|
||||
: never
|
||||
|
||||
function run<
|
||||
TWorkflow extends ReturnWorkflow<any, any, any>,
|
||||
TData = TWorkflow extends ReturnWorkflow<infer T, infer R, infer X>
|
||||
? T
|
||||
: never
|
||||
>(name: string, options: FlowRunOptions<TData>) {}
|
||||
|
||||
const test = run<typeof workflow>("workflow", { input: "string" })*/
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
import { resolveValue, StepResponse } from "./helpers"
|
||||
import {
|
||||
TransactionStepsDefinition,
|
||||
WorkflowManager,
|
||||
} from "@medusajs/orchestration"
|
||||
import { OrchestrationUtils, isString } from "@medusajs/utils"
|
||||
import { ulid } from "ulid"
|
||||
import { StepResponse, resolveValue } from "./helpers"
|
||||
import { proxify } from "./helpers/proxy"
|
||||
import {
|
||||
CreateWorkflowComposerContext,
|
||||
StepExecutionContext,
|
||||
@@ -6,9 +13,6 @@ import {
|
||||
StepFunctionResult,
|
||||
WorkflowData,
|
||||
} from "./type"
|
||||
import { proxify } from "./helpers/proxy"
|
||||
import { TransactionStepsDefinition } from "@medusajs/orchestration"
|
||||
import { isString, OrchestrationUtils } from "@medusajs/utils"
|
||||
|
||||
/**
|
||||
* The type of invocation function passed to a step.
|
||||
@@ -166,19 +170,37 @@ function applyStep<
|
||||
: undefined,
|
||||
}
|
||||
|
||||
stepConfig!.noCompensation = !compensateFn
|
||||
stepConfig.uuid = ulid()
|
||||
stepConfig.noCompensation = !compensateFn
|
||||
|
||||
this.flow.addAction(stepName, stepConfig)
|
||||
this.handlers.set(stepName, handler)
|
||||
|
||||
if (!this.handlers.has(stepName)) {
|
||||
this.handlers.set(stepName, handler)
|
||||
}
|
||||
|
||||
const ret = {
|
||||
__type: OrchestrationUtils.SymbolWorkflowStep,
|
||||
__step__: stepName,
|
||||
config: (config: Pick<TransactionStepsDefinition, "maxRetries">) => {
|
||||
this.flow.replaceAction(stepName, stepName, {
|
||||
config: (
|
||||
localConfig: { name?: string } & Omit<
|
||||
TransactionStepsDefinition,
|
||||
"next" | "uuid" | "action"
|
||||
>
|
||||
) => {
|
||||
const newStepName = localConfig.name ?? stepName
|
||||
|
||||
delete localConfig.name
|
||||
|
||||
this.handlers.set(newStepName, handler)
|
||||
|
||||
this.flow.replaceAction(stepConfig.uuid!, newStepName, {
|
||||
...stepConfig,
|
||||
...config,
|
||||
...localConfig,
|
||||
})
|
||||
|
||||
WorkflowManager.update(this.workflowId, this.flow, this.handlers)
|
||||
|
||||
return proxify(ret)
|
||||
},
|
||||
}
|
||||
@@ -241,11 +263,14 @@ export function createStep<
|
||||
TInvokeResultCompensateInput
|
||||
>(
|
||||
/**
|
||||
* The name of the step or its configuration (currently support maxRetries).
|
||||
* The name of the step or its configuration.
|
||||
*/
|
||||
nameOrConfig:
|
||||
| string
|
||||
| ({ name: string } & Pick<TransactionStepsDefinition, "maxRetries">),
|
||||
| ({ name: string } & Omit<
|
||||
TransactionStepsDefinition,
|
||||
"next" | "uuid" | "action"
|
||||
>),
|
||||
/**
|
||||
* An invocation function that will be executed when the workflow is executed. The function must return an instance of {@link StepResponse}. The constructor of {@link StepResponse}
|
||||
* accepts the output of the step as a first argument, and optionally as a second argument the data to be passed to the compensation function as a parameter.
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
WorkflowManager,
|
||||
} from "@medusajs/orchestration"
|
||||
import { LoadedModule, MedusaContainer } from "@medusajs/types"
|
||||
import { OrchestrationUtils } from "@medusajs/utils"
|
||||
import { isString, OrchestrationUtils } from "@medusajs/utils"
|
||||
import { ExportedWorkflow, exportWorkflow } from "../../helper"
|
||||
import { proxify } from "./helpers/proxy"
|
||||
import {
|
||||
@@ -63,7 +63,11 @@ global[OrchestrationUtils.SymbolMedusaWorkflowComposerContext] = null
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
type ReturnWorkflow<TData, TResult, THooks extends Record<string, Function>> = {
|
||||
export type ReturnWorkflow<
|
||||
TData,
|
||||
TResult,
|
||||
THooks extends Record<string, Function>
|
||||
> = {
|
||||
<TDataOverride = undefined, TResultOverride = undefined>(
|
||||
container?: LoadedModule[] | MedusaContainer
|
||||
): Omit<
|
||||
@@ -73,8 +77,20 @@ type ReturnWorkflow<TData, TResult, THooks extends Record<string, Function>> = {
|
||||
ExportedWorkflow<TData, TResult, TDataOverride, TResultOverride>
|
||||
} & THooks & {
|
||||
getName: () => string
|
||||
} & {
|
||||
config: (config: TransactionModelOptions) => void
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the raw type of the expected input data of a workflow.
|
||||
*
|
||||
* @example
|
||||
* type WorkflowInputData = UnwrapWorkflowInputDataType<typeof myWorkflow>
|
||||
*/
|
||||
export type UnwrapWorkflowInputDataType<
|
||||
T extends ReturnWorkflow<any, any, any>
|
||||
> = T extends ReturnWorkflow<infer TData, infer R, infer THooks> ? TData : never
|
||||
|
||||
/**
|
||||
* This function creates a workflow with the provided name and a constructor function.
|
||||
* The constructor function builds the workflow from steps created by the {@link createStep} function.
|
||||
@@ -136,9 +152,9 @@ export function createWorkflow<
|
||||
THooks extends Record<string, Function> = Record<string, Function>
|
||||
>(
|
||||
/**
|
||||
* The name of the workflow.
|
||||
* The name of the workflow or its configuration.
|
||||
*/
|
||||
name: string,
|
||||
nameOrConfig: string | ({ name: string } & TransactionModelOptions),
|
||||
/**
|
||||
* The constructor function that is executed when the `run` method in {@link ReturnWorkflow} is used.
|
||||
* The function can't be an arrow function or an asynchronus function. It also can't directly manipulate data.
|
||||
@@ -151,9 +167,11 @@ export function createWorkflow<
|
||||
[K in keyof TResult]:
|
||||
| WorkflowData<TResult[K]>
|
||||
| WorkflowDataProperties<TResult[K]>
|
||||
},
|
||||
options?: TransactionModelOptions
|
||||
}
|
||||
): ReturnWorkflow<TData, TResult, THooks> {
|
||||
const name = isString(nameOrConfig) ? nameOrConfig : nameOrConfig.name
|
||||
const options = isString(nameOrConfig) ? {} : nameOrConfig
|
||||
|
||||
const handlers: WorkflowHandler = new Map()
|
||||
|
||||
if (WorkflowManager.getWorkflow(name)) {
|
||||
@@ -185,13 +203,17 @@ export function createWorkflow<
|
||||
const inputPlaceHolder = proxify<WorkflowData>({
|
||||
__type: OrchestrationUtils.SymbolInputReference,
|
||||
__step__: "",
|
||||
config: () => {
|
||||
// TODO: config default value?
|
||||
throw new Error("Config is not available for the input object.")
|
||||
},
|
||||
})
|
||||
|
||||
const returnedStep = composer.apply(context, [inputPlaceHolder])
|
||||
|
||||
delete global[OrchestrationUtils.SymbolMedusaWorkflowComposerContext]
|
||||
|
||||
WorkflowManager.update(name, context.flow, handlers)
|
||||
WorkflowManager.update(name, context.flow, handlers, options)
|
||||
|
||||
const workflow = exportWorkflow<TData, TResult>(
|
||||
name,
|
||||
@@ -206,8 +228,12 @@ export function createWorkflow<
|
||||
container?: LoadedModule[] | MedusaContainer
|
||||
) => {
|
||||
const workflow_ = workflow<TDataOverride, TResultOverride>(container)
|
||||
const expandedFlow: any = workflow_
|
||||
expandedFlow.config = (config) => {
|
||||
workflow_.setOptions(config)
|
||||
}
|
||||
|
||||
return workflow_
|
||||
return expandedFlow
|
||||
}
|
||||
|
||||
let shouldRegisterHookHandler = true
|
||||
|
||||
@@ -37,13 +37,8 @@ export type StepFunction<TInput, TOutput = unknown> = (keyof TInput extends []
|
||||
}) &
|
||||
WorkflowDataProperties<{
|
||||
[K in keyof TOutput]: TOutput[K]
|
||||
}> & {
|
||||
config(
|
||||
config: Pick<TransactionStepsDefinition, "maxRetries">
|
||||
): WorkflowData<{
|
||||
[K in keyof TOutput]: TOutput[K]
|
||||
}>
|
||||
} & WorkflowDataProperties<{
|
||||
}> &
|
||||
WorkflowDataProperties<{
|
||||
[K in keyof TOutput]: TOutput[K]
|
||||
}>
|
||||
|
||||
@@ -62,7 +57,22 @@ export type WorkflowData<T = unknown> = (T extends object
|
||||
[Key in keyof T]: WorkflowData<T[Key]>
|
||||
}
|
||||
: WorkflowDataProperties<T>) &
|
||||
WorkflowDataProperties<T>
|
||||
WorkflowDataProperties<T> & {
|
||||
config(
|
||||
config: { name?: string } & Omit<
|
||||
TransactionStepsDefinition,
|
||||
"next" | "uuid" | "action"
|
||||
>
|
||||
): T extends object
|
||||
? WorkflowData<
|
||||
T extends object
|
||||
? {
|
||||
[K in keyof T]: T[K]
|
||||
}
|
||||
: T
|
||||
>
|
||||
: T
|
||||
}
|
||||
|
||||
export type CreateWorkflowComposerContext = {
|
||||
hooks_: string[]
|
||||
|
||||
Reference in New Issue
Block a user