fix(): workflows concurrency (#13645)
This commit is contained in:
@@ -109,10 +109,13 @@ export const completeCartWorkflow = createWorkflow(
|
||||
entity: "order_cart",
|
||||
fields: ["cart_id", "order_id"],
|
||||
filters: { cart_id: input.id },
|
||||
options: {
|
||||
isList: false,
|
||||
},
|
||||
})
|
||||
|
||||
const orderId = transform({ orderCart }, ({ orderCart }) => {
|
||||
return orderCart.data[0]?.order_id
|
||||
return orderCart?.data?.order_id
|
||||
})
|
||||
|
||||
const cart = useRemoteQueryStep({
|
||||
@@ -263,7 +266,7 @@ export const completeCartWorkflow = createWorkflow(
|
||||
const createdOrders = createOrdersStep([cartToOrder])
|
||||
|
||||
const createdOrder = transform({ createdOrders }, ({ createdOrders }) => {
|
||||
return createdOrders?.[0] ?? undefined
|
||||
return createdOrders[0]
|
||||
})
|
||||
|
||||
const reservationItemsData = transform(
|
||||
|
||||
@@ -207,7 +207,6 @@ describe("Transaction Orchestrator", () => {
|
||||
},
|
||||
{
|
||||
action: "three",
|
||||
async: true,
|
||||
maxRetries: 0,
|
||||
next: {
|
||||
action: "five",
|
||||
@@ -228,24 +227,14 @@ describe("Transaction Orchestrator", () => {
|
||||
|
||||
await strategy.resume(transaction)
|
||||
|
||||
expect(transaction.getErrors()).toHaveLength(2)
|
||||
expect(transaction.getErrors()).toHaveLength(1)
|
||||
expect(transaction.getErrors()).toEqual([
|
||||
{
|
||||
action: "three",
|
||||
error: {
|
||||
error: expect.objectContaining({
|
||||
message: "Step 3 failed",
|
||||
name: "Error",
|
||||
stack: expect.any(String),
|
||||
},
|
||||
handlerType: "invoke",
|
||||
},
|
||||
{
|
||||
action: "three",
|
||||
error: expect.objectContaining({
|
||||
message: expect.stringContaining(
|
||||
"Converting circular structure to JSON"
|
||||
),
|
||||
stack: expect.any(String),
|
||||
}),
|
||||
handlerType: "invoke",
|
||||
},
|
||||
@@ -1052,6 +1041,8 @@ describe("Transaction Orchestrator", () => {
|
||||
|
||||
await strategy.resume(transaction)
|
||||
|
||||
await new Promise((resolve) => process.nextTick(resolve))
|
||||
|
||||
expect(mocks.one).toHaveBeenCalledTimes(1)
|
||||
expect(mocks.two).toHaveBeenCalledTimes(0)
|
||||
expect(transaction.getState()).toBe(TransactionState.INVOKING)
|
||||
@@ -1148,6 +1139,8 @@ describe("Transaction Orchestrator", () => {
|
||||
|
||||
await strategy.resume(transaction)
|
||||
|
||||
await new Promise((resolve) => process.nextTick(resolve))
|
||||
|
||||
expect(mocks.one).toHaveBeenCalledTimes(1)
|
||||
expect(mocks.compensateOne).toHaveBeenCalledTimes(0)
|
||||
expect(mocks.two).toHaveBeenCalledTimes(0)
|
||||
@@ -1171,6 +1164,8 @@ describe("Transaction Orchestrator", () => {
|
||||
transaction,
|
||||
})
|
||||
|
||||
await new Promise((resolve) => process.nextTick(resolve))
|
||||
|
||||
expect(resumedTransaction.getState()).toBe(TransactionState.COMPENSATING)
|
||||
expect(mocks.compensateOne).toHaveBeenCalledTimes(1)
|
||||
|
||||
@@ -1263,6 +1258,7 @@ describe("Transaction Orchestrator", () => {
|
||||
})
|
||||
|
||||
await strategy.resume(transaction)
|
||||
await new Promise((resolve) => process.nextTick(resolve))
|
||||
|
||||
expect(mocks.one).toHaveBeenCalledTimes(1)
|
||||
expect(mocks.compensateOne).toHaveBeenCalledTimes(1)
|
||||
@@ -1335,6 +1331,7 @@ describe("Transaction Orchestrator", () => {
|
||||
})
|
||||
|
||||
await strategy.resume(transaction)
|
||||
await new Promise((resolve) => process.nextTick(resolve))
|
||||
|
||||
expect(transaction.getState()).toBe(TransactionState.DONE)
|
||||
expect(mocks.one).toHaveBeenCalledTimes(1)
|
||||
|
||||
@@ -116,6 +116,8 @@ describe("WorkflowManager", () => {
|
||||
it("should continue an asyncronous transaction after reporting a successful step", async () => {
|
||||
const transaction = await flow.run("deliver-product", "t-id")
|
||||
|
||||
await new Promise((resolve) => process.nextTick(resolve))
|
||||
|
||||
expect(handlers.get("foo").invoke).toHaveBeenCalledTimes(1)
|
||||
expect(handlers.get("callExternal").invoke).toHaveBeenCalledTimes(1)
|
||||
expect(handlers.get("bar").invoke).toHaveBeenCalledTimes(0)
|
||||
@@ -135,6 +137,8 @@ describe("WorkflowManager", () => {
|
||||
it("should revert an asyncronous transaction after reporting a failure step", async () => {
|
||||
const transaction = await flow.run("deliver-product", "t-id")
|
||||
|
||||
await new Promise((resolve) => process.nextTick(resolve))
|
||||
|
||||
expect(handlers.get("foo").invoke).toHaveBeenCalledTimes(1)
|
||||
expect(handlers.get("callExternal").invoke).toHaveBeenCalledTimes(1)
|
||||
expect(handlers.get("bar").invoke).toHaveBeenCalledTimes(0)
|
||||
|
||||
@@ -158,6 +158,8 @@ describe("WorkflowManager", () => {
|
||||
const flow = new LocalWorkflow("deliver-product", container)
|
||||
const transaction = await flow.run("t-id")
|
||||
|
||||
await new Promise((resolve) => process.nextTick(resolve))
|
||||
|
||||
expect(handlers.get("foo").invoke).toHaveBeenCalledTimes(1)
|
||||
expect(handlers.get("callExternal").invoke).toHaveBeenCalledTimes(1)
|
||||
expect(handlers.get("bar").invoke).toHaveBeenCalledTimes(0)
|
||||
@@ -177,6 +179,8 @@ describe("WorkflowManager", () => {
|
||||
const flow = new LocalWorkflow("deliver-product", container)
|
||||
const transaction = await flow.run("t-id")
|
||||
|
||||
await new Promise((resolve) => process.nextTick(resolve))
|
||||
|
||||
expect(handlers.get("foo").invoke).toHaveBeenCalledTimes(1)
|
||||
expect(handlers.get("callExternal").invoke).toHaveBeenCalledTimes(1)
|
||||
expect(handlers.get("bar").invoke).toHaveBeenCalledTimes(0)
|
||||
|
||||
@@ -951,8 +951,10 @@ export class TransactionOrchestrator extends EventEmitter {
|
||||
this.executeSyncStep(promise, transaction, step, nextSteps)
|
||||
)
|
||||
} else {
|
||||
// Execute async step in background and continue the execution of the transaction
|
||||
this.executeAsyncStep(promise, transaction, step, nextSteps)
|
||||
// Execute async step in background as part of the next event loop cycle and continue the execution of the transaction
|
||||
process.nextTick(() =>
|
||||
this.executeAsyncStep(promise, transaction, step, nextSteps)
|
||||
)
|
||||
hasAsyncSteps = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +167,10 @@ export function transform(
|
||||
const ret = {
|
||||
__id: uniqId,
|
||||
__type: OrchestrationUtils.SymbolWorkflowStepTransformer,
|
||||
__temporary_storage_key: null as { key: string } | null,
|
||||
} as WorkflowData & {
|
||||
__id: string
|
||||
__type: string
|
||||
__temporary_storage_key: { key: string } | null
|
||||
}
|
||||
|
||||
const returnFn = async function (
|
||||
@@ -176,6 +179,7 @@ export function transform(
|
||||
): Promise<any> {
|
||||
if ("transaction" in transactionContext) {
|
||||
const temporaryDataKey = `${transactionContext.transaction.modelId}_${transactionContext.transaction.transactionId}_${uniqId}`
|
||||
|
||||
ret.__temporary_storage_key ??= { key: temporaryDataKey }
|
||||
|
||||
if (
|
||||
@@ -199,15 +203,14 @@ export function transform(
|
||||
const fn = functions[i]
|
||||
const arg = i === 0 ? stepValue : finalResult
|
||||
|
||||
finalResult = await fn.apply(fn, [arg, transactionContext])
|
||||
finalResult = fn.apply(fn, [arg, transactionContext])
|
||||
if (finalResult instanceof Promise) {
|
||||
finalResult = await finalResult
|
||||
}
|
||||
}
|
||||
|
||||
if ("transaction" in transactionContext) {
|
||||
const temporaryDataKey = ret.__temporary_storage_key!
|
||||
if (!temporaryDataKey) {
|
||||
return finalResult
|
||||
}
|
||||
|
||||
transactionContext.transaction.setTemporaryData(
|
||||
temporaryDataKey,
|
||||
finalResult
|
||||
@@ -217,10 +220,11 @@ export function transform(
|
||||
return finalResult
|
||||
}
|
||||
|
||||
const proxyfiedRet = proxify<WorkflowData & { __resolver: any }>(
|
||||
ret as unknown as WorkflowData
|
||||
)
|
||||
const proxyfiedRet = proxify<
|
||||
WorkflowData & { __resolver: any; __temporary_storage_key: string | null }
|
||||
>(ret as unknown as WorkflowData)
|
||||
proxyfiedRet.__resolver = returnFn as any
|
||||
proxyfiedRet.__temporary_storage_key = null as string | null
|
||||
|
||||
return proxyfiedRet
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user