fix(): pipeline missing suites (#13457)
* fix(): pipeline missing suites * fix tax integration tests * fix tax integration tests * fix pipeline * fix link integration tests * remove old tests and move current one * fix workflow execution integration tests * fix tests and orchestrator * Fix missing suites in pipeline Remove integration-tests-modules from patch list.
This commit is contained in:
1 parent
21c6e8600f
commit
ebf33bea43
12 files changed
+384
-313
No files matched your search
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/workflow-engine-inmemory": patch
|
||||||
|
"@medusajs/workflow-engine-redis": patch
|
||||||
|
"@medusajs/orchestration": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix(): pipeline missing suites
|
||||||
@@ -205,13 +205,22 @@ jobs:
|
|||||||
name: Module Integration Tests - Shard ${{ matrix.shard_index }}
|
name: Module Integration Tests - Shard ${{ matrix.shard_index }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
shard_index: [1, 2]
|
shard_index: [1, 2, 3]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
redis:
|
||||||
|
image: redis
|
||||||
|
options: >-
|
||||||
|
--health-cmd "redis-cli ping"
|
||||||
|
--health-interval 1s
|
||||||
|
--health-timeout 10s
|
||||||
|
--health-retries 10
|
||||||
|
ports:
|
||||||
|
- 6379:6379
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres
|
image: postgres
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -103,7 +103,9 @@ medusaIntegrationTestRunner({
|
|||||||
|
|
||||||
const values = await links.linkServiceName.list()
|
const values = await links.linkServiceName.list()
|
||||||
|
|
||||||
expect(values).toEqual([
|
expect(values).toHaveLength(6)
|
||||||
|
expect(values).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
{
|
{
|
||||||
product_id: "modA_id",
|
product_id: "modA_id",
|
||||||
inventory_item_id: "modB_id",
|
inventory_item_id: "modB_id",
|
||||||
@@ -144,6 +146,7 @@ medusaIntegrationTestRunner({
|
|||||||
inventory_item_id: "bbb",
|
inventory_item_id: "bbb",
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("Should dismiss the link of a given pair of keys", async function () {
|
it("Should dismiss the link of a given pair of keys", async function () {
|
||||||
|
|||||||
-2
@@ -176,8 +176,6 @@ medusaIntegrationTestRunner({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(result.items[0].actions)
|
|
||||||
|
|
||||||
let updatedShippingMethod = result.shipping_methods?.find(
|
let updatedShippingMethod = result.shipping_methods?.find(
|
||||||
(sm) => sm.shipping_option_id === shippingOptionId
|
(sm) => sm.shipping_option_id === shippingOptionId
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ medusaIntegrationTestRunner({
|
|||||||
`/admin/tax-regions`,
|
`/admin/tax-regions`,
|
||||||
{
|
{
|
||||||
country_code: "us",
|
country_code: "us",
|
||||||
|
provider_id: "tp_system",
|
||||||
default_tax_rate: {
|
default_tax_rate: {
|
||||||
code: "default",
|
code: "default",
|
||||||
rate: 2,
|
rate: 2,
|
||||||
@@ -131,7 +132,7 @@ medusaIntegrationTestRunner({
|
|||||||
updated_at: expect.any(String),
|
updated_at: expect.any(String),
|
||||||
deleted_at: null,
|
deleted_at: null,
|
||||||
created_by: expect.any(String),
|
created_by: expect.any(String),
|
||||||
provider_id: null,
|
provider_id: "tp_system",
|
||||||
metadata: null,
|
metadata: null,
|
||||||
children: [],
|
children: [],
|
||||||
parent: null,
|
parent: null,
|
||||||
@@ -275,6 +276,7 @@ medusaIntegrationTestRunner({
|
|||||||
`/admin/tax-regions`,
|
`/admin/tax-regions`,
|
||||||
{
|
{
|
||||||
country_code: "us",
|
country_code: "us",
|
||||||
|
provider_id: "tp_system",
|
||||||
default_tax_rate: {
|
default_tax_rate: {
|
||||||
code: "default",
|
code: "default",
|
||||||
rate: 2,
|
rate: 2,
|
||||||
@@ -297,7 +299,7 @@ medusaIntegrationTestRunner({
|
|||||||
updated_at: expect.any(String),
|
updated_at: expect.any(String),
|
||||||
deleted_at: null,
|
deleted_at: null,
|
||||||
created_by: expect.any(String),
|
created_by: expect.any(String),
|
||||||
provider_id: null,
|
provider_id: "tp_system",
|
||||||
metadata: null,
|
metadata: null,
|
||||||
children: [],
|
children: [],
|
||||||
parent: null,
|
parent: null,
|
||||||
@@ -385,6 +387,7 @@ medusaIntegrationTestRunner({
|
|||||||
`/admin/tax-regions`,
|
`/admin/tax-regions`,
|
||||||
{
|
{
|
||||||
country_code: "us",
|
country_code: "us",
|
||||||
|
provider_id: "tp_system",
|
||||||
default_tax_rate: {
|
default_tax_rate: {
|
||||||
code: "default",
|
code: "default",
|
||||||
rate: 2,
|
rate: 2,
|
||||||
@@ -495,6 +498,7 @@ medusaIntegrationTestRunner({
|
|||||||
`/admin/tax-regions`,
|
`/admin/tax-regions`,
|
||||||
{
|
{
|
||||||
country_code: "us",
|
country_code: "us",
|
||||||
|
provider_id: "tp_system",
|
||||||
default_tax_rate: {
|
default_tax_rate: {
|
||||||
code: "default",
|
code: "default",
|
||||||
rate: 2,
|
rate: 2,
|
||||||
@@ -531,6 +535,7 @@ medusaIntegrationTestRunner({
|
|||||||
`/admin/tax-regions`,
|
`/admin/tax-regions`,
|
||||||
{
|
{
|
||||||
country_code: "us",
|
country_code: "us",
|
||||||
|
provider_id: "tp_system",
|
||||||
default_tax_rate: {
|
default_tax_rate: {
|
||||||
code: "default",
|
code: "default",
|
||||||
rate: 2,
|
rate: 2,
|
||||||
|
|||||||
+323
@@ -0,0 +1,323 @@
|
|||||||
|
import {
|
||||||
|
createStep,
|
||||||
|
createWorkflow,
|
||||||
|
StepResponse,
|
||||||
|
WorkflowData,
|
||||||
|
WorkflowResponse,
|
||||||
|
} from "@medusajs/framework/workflows-sdk"
|
||||||
|
import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
|
||||||
|
import { createAdminUser } from "../../../../helpers/create-admin-user"
|
||||||
|
import { setTimeout } from "timers/promises"
|
||||||
|
|
||||||
|
jest.setTimeout(100000)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* finish the workflow to prevent the runner from waiting for the end of the execution permanently
|
||||||
|
*/
|
||||||
|
async function finishWorkflows(
|
||||||
|
api: any,
|
||||||
|
{
|
||||||
|
stepId,
|
||||||
|
response,
|
||||||
|
executions,
|
||||||
|
}: {
|
||||||
|
stepId: string
|
||||||
|
response?: any
|
||||||
|
executions: { transaction_id: string }[]
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
const promises: any[] = []
|
||||||
|
for (const execution of executions) {
|
||||||
|
promises.push(
|
||||||
|
api.post(
|
||||||
|
`/admin/workflows-executions/my-workflow-name/steps/success`,
|
||||||
|
{
|
||||||
|
transaction_id: execution.transaction_id,
|
||||||
|
step_id: stepId,
|
||||||
|
response: response || {
|
||||||
|
all: "good",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(promises)
|
||||||
|
}
|
||||||
|
|
||||||
|
const adminHeaders = {
|
||||||
|
headers: {
|
||||||
|
"x-medusa-access-token": "test_token",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
medusaIntegrationTestRunner({
|
||||||
|
testSuite: ({ dbConnection, getContainer, api }) => {
|
||||||
|
describe("Workflow Engine API", () => {
|
||||||
|
let medusaContainer
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
medusaContainer = getContainer()
|
||||||
|
|
||||||
|
const step1 = createStep(
|
||||||
|
{
|
||||||
|
name: "my-step",
|
||||||
|
},
|
||||||
|
async (input: { initial: string }) => {
|
||||||
|
return new StepResponse({
|
||||||
|
result: input.initial,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
const step2 = createStep(
|
||||||
|
{
|
||||||
|
name: "my-step-async",
|
||||||
|
async: true,
|
||||||
|
},
|
||||||
|
async () => {}
|
||||||
|
)
|
||||||
|
|
||||||
|
createWorkflow(
|
||||||
|
{
|
||||||
|
name: "my-workflow-name",
|
||||||
|
retentionTime: 1000,
|
||||||
|
},
|
||||||
|
function (input: WorkflowData<{ initial: string }>) {
|
||||||
|
step1(input)
|
||||||
|
const res = step2()
|
||||||
|
return new WorkflowResponse(res)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await createAdminUser(dbConnection, adminHeaders, medusaContainer)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Should list all workflows in execution or completed and retrieve them by id", async () => {
|
||||||
|
for (let i = 3; i--; ) {
|
||||||
|
await api.post(
|
||||||
|
`/admin/workflows-executions/my-workflow-name/run`,
|
||||||
|
{
|
||||||
|
input: {
|
||||||
|
initial: "abc",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const executions = await api.get(
|
||||||
|
`/admin/workflows-executions`,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(executions.data.count).toEqual(3)
|
||||||
|
expect(executions.data.workflow_executions.length).toEqual(3)
|
||||||
|
expect(executions.data.workflow_executions[0]).toEqual({
|
||||||
|
workflow_id: "my-workflow-name",
|
||||||
|
transaction_id: expect.any(String),
|
||||||
|
id: expect.any(String),
|
||||||
|
state: "invoking",
|
||||||
|
created_at: expect.any(String),
|
||||||
|
updated_at: expect.any(String),
|
||||||
|
deleted_at: null,
|
||||||
|
})
|
||||||
|
|
||||||
|
const retrivedById = await api.get(
|
||||||
|
`/admin/workflows-executions/` +
|
||||||
|
executions.data.workflow_executions[0].id,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(retrivedById.data.workflow_execution).toEqual(
|
||||||
|
expect.objectContaining(executions.data.workflow_executions[0])
|
||||||
|
)
|
||||||
|
|
||||||
|
await finishWorkflows(api, {
|
||||||
|
stepId: "my-step-async",
|
||||||
|
executions: executions.data.workflow_executions,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Should list all workflows matching the filters", async () => {
|
||||||
|
const promises: any[] = []
|
||||||
|
const transactions: string[] = []
|
||||||
|
|
||||||
|
for (let i = 3; i--; ) {
|
||||||
|
const transactionId = "transaction_" + (i + 1)
|
||||||
|
transactions.push(transactionId)
|
||||||
|
promises.push(
|
||||||
|
api.post(
|
||||||
|
`/admin/workflows-executions/my-workflow-name/run`,
|
||||||
|
{
|
||||||
|
input: {
|
||||||
|
initial: "abc",
|
||||||
|
},
|
||||||
|
transaction_id: transactionId,
|
||||||
|
},
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(promises)
|
||||||
|
|
||||||
|
const executions = await api.get(
|
||||||
|
`/admin/workflows-executions?transaction_id[]=transaction_1&transaction_id[]=transaction_2`,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(executions.data.count).toEqual(2)
|
||||||
|
expect(executions.data.workflow_executions.length).toEqual(2)
|
||||||
|
expect(executions.data.workflow_executions[0]).toEqual({
|
||||||
|
workflow_id: "my-workflow-name",
|
||||||
|
transaction_id: expect.stringMatching(
|
||||||
|
new RegExp(transactions.join("|"))
|
||||||
|
),
|
||||||
|
id: expect.any(String),
|
||||||
|
state: "invoking",
|
||||||
|
created_at: expect.any(String),
|
||||||
|
updated_at: expect.any(String),
|
||||||
|
deleted_at: null,
|
||||||
|
})
|
||||||
|
expect(executions.data.workflow_executions[1]).toEqual({
|
||||||
|
workflow_id: "my-workflow-name",
|
||||||
|
transaction_id: expect.stringMatching(
|
||||||
|
new RegExp(transactions.join("|"))
|
||||||
|
),
|
||||||
|
id: expect.any(String),
|
||||||
|
state: "invoking",
|
||||||
|
created_at: expect.any(String),
|
||||||
|
updated_at: expect.any(String),
|
||||||
|
deleted_at: null,
|
||||||
|
})
|
||||||
|
|
||||||
|
await finishWorkflows(api, {
|
||||||
|
stepId: "my-step-async",
|
||||||
|
executions: transactions.map((transactionId) => ({
|
||||||
|
transaction_id: transactionId,
|
||||||
|
})),
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log("finished")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Should execute a workflow and retrieve its execution while running and when it is completed", async () => {
|
||||||
|
const wf = await api.post(
|
||||||
|
`/admin/workflows-executions/my-workflow-name/run`,
|
||||||
|
{
|
||||||
|
input: {
|
||||||
|
initial: "abc",
|
||||||
|
},
|
||||||
|
transaction_id: "trx_123",
|
||||||
|
},
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(wf.data).toEqual({
|
||||||
|
acknowledgement: {
|
||||||
|
transactionId: "trx_123",
|
||||||
|
workflowId: "my-workflow-name",
|
||||||
|
hasFailed: false,
|
||||||
|
hasFinished: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
await setTimeout(2000)
|
||||||
|
|
||||||
|
const execution = await api.get(
|
||||||
|
`/admin/workflows-executions/my-workflow-name/${wf.data.acknowledgement.transactionId}`,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(execution.data).toEqual({
|
||||||
|
workflow_execution: expect.objectContaining({
|
||||||
|
workflow_id: "my-workflow-name",
|
||||||
|
transaction_id: "trx_123",
|
||||||
|
id: expect.any(String),
|
||||||
|
state: "invoking",
|
||||||
|
execution: expect.objectContaining({
|
||||||
|
hasAsyncSteps: true,
|
||||||
|
hasFailedSteps: false,
|
||||||
|
hasSkippedSteps: false,
|
||||||
|
hasWaitingSteps: true,
|
||||||
|
hasRevertedSteps: false,
|
||||||
|
}),
|
||||||
|
context: expect.objectContaining({
|
||||||
|
data: expect.objectContaining({
|
||||||
|
invoke: {
|
||||||
|
"my-step": {
|
||||||
|
__type: "Symbol(WorkflowWorkflowData)",
|
||||||
|
output: {
|
||||||
|
__type: "Symbol(WorkflowStepResponse)",
|
||||||
|
output: {
|
||||||
|
result: "abc",
|
||||||
|
},
|
||||||
|
compensateInput: {
|
||||||
|
result: "abc",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
payload: {
|
||||||
|
initial: "abc",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
const respondAsync = await api.post(
|
||||||
|
`/admin/workflows-executions/my-workflow-name/steps/success`,
|
||||||
|
{
|
||||||
|
transaction_id: "trx_123",
|
||||||
|
step_id: "my-step-async",
|
||||||
|
response: {
|
||||||
|
all: "good",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(respondAsync.data.success).toEqual(true)
|
||||||
|
|
||||||
|
const completed = await api.get(
|
||||||
|
`/admin/workflows-executions/my-workflow-name/trx_123`,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(completed.data).toEqual({
|
||||||
|
workflow_execution: expect.objectContaining({
|
||||||
|
workflow_id: "my-workflow-name",
|
||||||
|
transaction_id: "trx_123",
|
||||||
|
state: "done",
|
||||||
|
execution: expect.objectContaining({
|
||||||
|
hasAsyncSteps: true,
|
||||||
|
hasFailedSteps: false,
|
||||||
|
hasSkippedSteps: false,
|
||||||
|
hasWaitingSteps: false,
|
||||||
|
hasRevertedSteps: false,
|
||||||
|
}),
|
||||||
|
context: expect.objectContaining({
|
||||||
|
data: expect.objectContaining({
|
||||||
|
invoke: expect.objectContaining({
|
||||||
|
"my-step-async": {
|
||||||
|
__type: "Symbol(WorkflowStepResponse)",
|
||||||
|
output: {
|
||||||
|
all: "good",
|
||||||
|
},
|
||||||
|
compensateInput: {
|
||||||
|
all: "good",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { workflowEngineTestSuite } from "./tests"
|
|
||||||
|
|
||||||
jest.setTimeout(5000000)
|
|
||||||
|
|
||||||
const env = {}
|
|
||||||
|
|
||||||
workflowEngineTestSuite(env)
|
|
||||||
@@ -1,274 +0,0 @@
|
|||||||
import {
|
|
||||||
createStep,
|
|
||||||
createWorkflow,
|
|
||||||
StepResponse,
|
|
||||||
WorkflowData,
|
|
||||||
} from "@medusajs/framework/workflows-sdk"
|
|
||||||
import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
|
|
||||||
import { createAdminUser } from "../../../helpers/create-admin-user"
|
|
||||||
|
|
||||||
export const workflowEngineTestSuite = (
|
|
||||||
env,
|
|
||||||
extraParams: { force_modules_migration?: boolean } = {}
|
|
||||||
) => {
|
|
||||||
const adminHeaders = {
|
|
||||||
headers: {
|
|
||||||
"x-medusa-access-token": "test_token",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return medusaIntegrationTestRunner({
|
|
||||||
env,
|
|
||||||
force_modules_migration: extraParams.force_modules_migration,
|
|
||||||
testSuite: ({ dbConnection, getContainer, api }) => {
|
|
||||||
describe("Workflow Engine API", () => {
|
|
||||||
let medusaContainer
|
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
medusaContainer = getContainer()
|
|
||||||
})
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await createAdminUser(dbConnection, adminHeaders, medusaContainer)
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("running workflows", () => {
|
|
||||||
beforeAll(async () => {
|
|
||||||
const step1 = createStep(
|
|
||||||
{
|
|
||||||
name: "my-step",
|
|
||||||
},
|
|
||||||
async (input: { initial: string }) => {
|
|
||||||
return new StepResponse({
|
|
||||||
result: input.initial,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
const step2 = createStep(
|
|
||||||
{
|
|
||||||
name: "my-step-async",
|
|
||||||
async: true,
|
|
||||||
},
|
|
||||||
async () => {}
|
|
||||||
)
|
|
||||||
|
|
||||||
createWorkflow(
|
|
||||||
{
|
|
||||||
name: "my-workflow-name",
|
|
||||||
retentionTime: 1000,
|
|
||||||
},
|
|
||||||
function (input: WorkflowData<{ initial: string }>) {
|
|
||||||
step1(input)
|
|
||||||
return step2()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Should list all workflows in execution or completed and retrieve them by id", async () => {
|
|
||||||
for (let i = 3; i--; ) {
|
|
||||||
await api.post(
|
|
||||||
`/admin/workflows-executions/my-workflow-name/run`,
|
|
||||||
{
|
|
||||||
input: {
|
|
||||||
initial: "abc",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
adminHeaders
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const executions = await api.get(
|
|
||||||
`/admin/workflows-executions`,
|
|
||||||
adminHeaders
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(executions.data.count).toEqual(3)
|
|
||||||
expect(executions.data.workflow_executions.length).toEqual(3)
|
|
||||||
expect(executions.data.workflow_executions[0]).toEqual({
|
|
||||||
workflow_id: "my-workflow-name",
|
|
||||||
transaction_id: expect.any(String),
|
|
||||||
id: expect.any(String),
|
|
||||||
state: "invoking",
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
})
|
|
||||||
|
|
||||||
const retrivedById = await api.get(
|
|
||||||
`/admin/workflows-executions/` +
|
|
||||||
executions.data.workflow_executions[0].id,
|
|
||||||
adminHeaders
|
|
||||||
)
|
|
||||||
expect(retrivedById.data.workflow_execution).toEqual(
|
|
||||||
expect.objectContaining(executions.data.workflow_executions[0])
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Should list all workflows matching the filters", async () => {
|
|
||||||
for (let i = 3; i--; ) {
|
|
||||||
await api.post(
|
|
||||||
`/admin/workflows-executions/my-workflow-name/run`,
|
|
||||||
{
|
|
||||||
input: {
|
|
||||||
initial: "abc",
|
|
||||||
},
|
|
||||||
transaction_id: "transaction_" + (i + 1),
|
|
||||||
},
|
|
||||||
adminHeaders
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const executions = await api.get(
|
|
||||||
`/admin/workflows-executions?transaction_id[]=transaction_1&transaction_id[]=transaction_2`,
|
|
||||||
adminHeaders
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(executions.data.count).toEqual(2)
|
|
||||||
expect(executions.data.workflow_executions.length).toEqual(2)
|
|
||||||
expect(executions.data.workflow_executions[0]).toEqual({
|
|
||||||
workflow_id: "my-workflow-name",
|
|
||||||
transaction_id: expect.stringMatching(
|
|
||||||
/transaction_1|transaction_2/
|
|
||||||
),
|
|
||||||
id: expect.any(String),
|
|
||||||
state: "invoking",
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
})
|
|
||||||
expect(executions.data.workflow_executions[1]).toEqual({
|
|
||||||
workflow_id: "my-workflow-name",
|
|
||||||
transaction_id: expect.stringMatching(
|
|
||||||
/transaction_1|transaction_2/
|
|
||||||
),
|
|
||||||
id: expect.any(String),
|
|
||||||
state: "invoking",
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Should execute a workflow and retrieve its execution while running and when it is completed", async () => {
|
|
||||||
const wf = await api.post(
|
|
||||||
`/admin/workflows-executions/my-workflow-name/run`,
|
|
||||||
{
|
|
||||||
input: {
|
|
||||||
initial: "abc",
|
|
||||||
},
|
|
||||||
transaction_id: "trx_123",
|
|
||||||
},
|
|
||||||
adminHeaders
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(wf.data).toEqual({
|
|
||||||
acknowledgement: {
|
|
||||||
transactionId: "trx_123",
|
|
||||||
workflowId: "my-workflow-name",
|
|
||||||
hasFailed: false,
|
|
||||||
hasFinished: false,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const execution = await api.get(
|
|
||||||
`/admin/workflows-executions/my-workflow-name/trx_123`,
|
|
||||||
adminHeaders
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(execution.data).toEqual({
|
|
||||||
workflow_execution: expect.objectContaining({
|
|
||||||
workflow_id: "my-workflow-name",
|
|
||||||
transaction_id: "trx_123",
|
|
||||||
id: expect.any(String),
|
|
||||||
state: "invoking",
|
|
||||||
execution: expect.objectContaining({
|
|
||||||
hasAsyncSteps: true,
|
|
||||||
hasFailedSteps: false,
|
|
||||||
hasSkippedSteps: false,
|
|
||||||
hasWaitingSteps: true,
|
|
||||||
hasRevertedSteps: false,
|
|
||||||
}),
|
|
||||||
context: expect.objectContaining({
|
|
||||||
data: expect.objectContaining({
|
|
||||||
invoke: {
|
|
||||||
"my-step": {
|
|
||||||
__type: "Symbol(WorkflowWorkflowData)",
|
|
||||||
output: {
|
|
||||||
__type: "Symbol(WorkflowStepResponse)",
|
|
||||||
output: {
|
|
||||||
result: "abc",
|
|
||||||
},
|
|
||||||
compensateInput: {
|
|
||||||
result: "abc",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
payload: {
|
|
||||||
initial: "abc",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
|
|
||||||
const respondAsync = await api.post(
|
|
||||||
`/admin/workflows-executions/my-workflow-name/steps/success`,
|
|
||||||
{
|
|
||||||
transaction_id: "trx_123",
|
|
||||||
step_id: "my-step-async",
|
|
||||||
response: {
|
|
||||||
all: "good",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
adminHeaders
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(respondAsync.data.success).toEqual(true)
|
|
||||||
|
|
||||||
const completed = await api.get(
|
|
||||||
`/admin/workflows-executions/my-workflow-name/trx_123`,
|
|
||||||
adminHeaders
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(completed.data).toEqual({
|
|
||||||
workflow_execution: expect.objectContaining({
|
|
||||||
workflow_id: "my-workflow-name",
|
|
||||||
transaction_id: "trx_123",
|
|
||||||
state: "done",
|
|
||||||
execution: expect.objectContaining({
|
|
||||||
hasAsyncSteps: true,
|
|
||||||
hasFailedSteps: false,
|
|
||||||
hasSkippedSteps: false,
|
|
||||||
hasWaitingSteps: false,
|
|
||||||
hasRevertedSteps: false,
|
|
||||||
}),
|
|
||||||
context: expect.objectContaining({
|
|
||||||
data: expect.objectContaining({
|
|
||||||
invoke: expect.objectContaining({
|
|
||||||
"my-step-async": {
|
|
||||||
__type: "Symbol(WorkflowStepResponse)",
|
|
||||||
output: {
|
|
||||||
all: "good",
|
|
||||||
},
|
|
||||||
compensateInput: {
|
|
||||||
all: "good",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("Noop test", () => {
|
|
||||||
it("noop check", async () => {
|
|
||||||
expect(true).toBe(true)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
File renamed without changes.
@@ -961,6 +961,13 @@ export class TransactionOrchestrator extends EventEmitter {
|
|||||||
|
|
||||||
if (nextSteps.next.length === 0 || (hasAsyncSteps && !execution.length)) {
|
if (nextSteps.next.length === 0 || (hasAsyncSteps && !execution.length)) {
|
||||||
continueExecution = false
|
continueExecution = false
|
||||||
|
await transaction.saveCheckpoint().catch((error) => {
|
||||||
|
if (TransactionOrchestrator.isExpectedError(error)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-15
@@ -447,7 +447,8 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should not retry steps X times automatically when maxRetries is set and autoRetry is false", async () => {
|
it("should not retry steps X times automatically when maxRetries is set and autoRetry is false", (done) => {
|
||||||
|
;(async () => {
|
||||||
const transactionId = "transaction-auto-retries" + ulid()
|
const transactionId = "transaction-auto-retries" + ulid()
|
||||||
const workflowId = "workflow_1_auto_retries_false"
|
const workflowId = "workflow_1_auto_retries_false"
|
||||||
|
|
||||||
@@ -457,22 +458,20 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
throwOnError: false,
|
throwOnError: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
let lastExepectHaveBeenCalledTimes = 0
|
|
||||||
|
|
||||||
workflowOrcModule.subscribe({
|
workflowOrcModule.subscribe({
|
||||||
workflowId,
|
workflowId,
|
||||||
transactionId,
|
transactionId,
|
||||||
subscriber: async (event) => {
|
subscriber: async (event) => {
|
||||||
if (event.eventType === "onFinish") {
|
if (event.eventType === "onFinish") {
|
||||||
lastExepectHaveBeenCalledTimes = 1
|
|
||||||
expect(step1InvokeMockAutoRetriesFalse).toHaveBeenCalledTimes(1)
|
expect(step1InvokeMockAutoRetriesFalse).toHaveBeenCalledTimes(1)
|
||||||
expect(step2InvokeMockAutoRetriesFalse).toHaveBeenCalledTimes(3)
|
expect(step2InvokeMockAutoRetriesFalse).toHaveBeenCalledTimes(3)
|
||||||
expect(step1CompensateMockAutoRetriesFalse).toHaveBeenCalledTimes(
|
expect(
|
||||||
1
|
step1CompensateMockAutoRetriesFalse
|
||||||
)
|
).toHaveBeenCalledTimes(1)
|
||||||
expect(step2CompensateMockAutoRetriesFalse).toHaveBeenCalledTimes(
|
expect(
|
||||||
1
|
step2CompensateMockAutoRetriesFalse
|
||||||
)
|
).toHaveBeenCalledTimes(1)
|
||||||
|
done()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -482,13 +481,15 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
expect(step1CompensateMockAutoRetriesFalse).toHaveBeenCalledTimes(0)
|
expect(step1CompensateMockAutoRetriesFalse).toHaveBeenCalledTimes(0)
|
||||||
expect(step2CompensateMockAutoRetriesFalse).toHaveBeenCalledTimes(0)
|
expect(step2CompensateMockAutoRetriesFalse).toHaveBeenCalledTimes(0)
|
||||||
|
|
||||||
|
await setTimeoutPromise(2000)
|
||||||
|
|
||||||
await workflowOrcModule.run(workflowId, {
|
await workflowOrcModule.run(workflowId, {
|
||||||
input: {},
|
input: {},
|
||||||
transactionId,
|
transactionId,
|
||||||
throwOnError: false,
|
throwOnError: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
await setTimeoutPromise(1000)
|
await setTimeoutPromise(2000)
|
||||||
|
|
||||||
expect(step1InvokeMockAutoRetriesFalse).toHaveBeenCalledTimes(1)
|
expect(step1InvokeMockAutoRetriesFalse).toHaveBeenCalledTimes(1)
|
||||||
expect(step2InvokeMockAutoRetriesFalse).toHaveBeenCalledTimes(2)
|
expect(step2InvokeMockAutoRetriesFalse).toHaveBeenCalledTimes(2)
|
||||||
@@ -500,10 +501,7 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
transactionId,
|
transactionId,
|
||||||
throwOnError: false,
|
throwOnError: false,
|
||||||
})
|
})
|
||||||
|
})()
|
||||||
await setTimeoutPromise(1000)
|
|
||||||
|
|
||||||
expect(lastExepectHaveBeenCalledTimes).toEqual(1)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should prevent executing twice the same workflow in perfect concurrency with the same transactionId and non idempotent and not async but retention time is set", async () => {
|
it("should prevent executing twice the same workflow in perfect concurrency with the same transactionId and non idempotent and not async but retention time is set", async () => {
|
||||||
|
|||||||
@@ -485,7 +485,8 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should not retry steps X times automatically when maxRetries is set and autoRetry is false", async () => {
|
it("should not retry steps X times automatically when maxRetries is set and autoRetry is false", (done) => {
|
||||||
|
;(async () => {
|
||||||
const transactionId = "transaction-auto-retries" + ulid()
|
const transactionId = "transaction-auto-retries" + ulid()
|
||||||
const workflowId = "workflow_1_auto_retries_false"
|
const workflowId = "workflow_1_auto_retries_false"
|
||||||
|
|
||||||
@@ -495,22 +496,24 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
throwOnError: false,
|
throwOnError: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
let lastExepectHaveBeenCalledTimes = 0
|
|
||||||
|
|
||||||
workflowOrcModule.subscribe({
|
workflowOrcModule.subscribe({
|
||||||
workflowId,
|
workflowId,
|
||||||
transactionId,
|
transactionId,
|
||||||
subscriber: async (event) => {
|
subscriber: async (event) => {
|
||||||
if (event.eventType === "onFinish") {
|
if (event.eventType === "onFinish") {
|
||||||
lastExepectHaveBeenCalledTimes = 1
|
expect(step1InvokeMockAutoRetriesFalse).toHaveBeenCalledTimes(
|
||||||
expect(step1InvokeMockAutoRetriesFalse).toHaveBeenCalledTimes(1)
|
1
|
||||||
expect(step2InvokeMockAutoRetriesFalse).toHaveBeenCalledTimes(3)
|
)
|
||||||
|
expect(step2InvokeMockAutoRetriesFalse).toHaveBeenCalledTimes(
|
||||||
|
3
|
||||||
|
)
|
||||||
expect(
|
expect(
|
||||||
step1CompensateMockAutoRetriesFalse
|
step1CompensateMockAutoRetriesFalse
|
||||||
).toHaveBeenCalledTimes(1)
|
).toHaveBeenCalledTimes(1)
|
||||||
expect(
|
expect(
|
||||||
step2CompensateMockAutoRetriesFalse
|
step2CompensateMockAutoRetriesFalse
|
||||||
).toHaveBeenCalledTimes(1)
|
).toHaveBeenCalledTimes(1)
|
||||||
|
done()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -520,13 +523,15 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
expect(step1CompensateMockAutoRetriesFalse).toHaveBeenCalledTimes(0)
|
expect(step1CompensateMockAutoRetriesFalse).toHaveBeenCalledTimes(0)
|
||||||
expect(step2CompensateMockAutoRetriesFalse).toHaveBeenCalledTimes(0)
|
expect(step2CompensateMockAutoRetriesFalse).toHaveBeenCalledTimes(0)
|
||||||
|
|
||||||
|
await setTimeout(2000)
|
||||||
|
|
||||||
await workflowOrcModule.run(workflowId, {
|
await workflowOrcModule.run(workflowId, {
|
||||||
input: {},
|
input: {},
|
||||||
transactionId,
|
transactionId,
|
||||||
throwOnError: false,
|
throwOnError: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
await setTimeout(4000)
|
await setTimeout(2000)
|
||||||
|
|
||||||
expect(step1InvokeMockAutoRetriesFalse).toHaveBeenCalledTimes(1)
|
expect(step1InvokeMockAutoRetriesFalse).toHaveBeenCalledTimes(1)
|
||||||
expect(step2InvokeMockAutoRetriesFalse).toHaveBeenCalledTimes(2)
|
expect(step2InvokeMockAutoRetriesFalse).toHaveBeenCalledTimes(2)
|
||||||
@@ -538,10 +543,7 @@ moduleIntegrationTestRunner<IWorkflowEngineService>({
|
|||||||
transactionId,
|
transactionId,
|
||||||
throwOnError: false,
|
throwOnError: false,
|
||||||
})
|
})
|
||||||
|
})()
|
||||||
await setTimeout(4000)
|
|
||||||
|
|
||||||
expect(lastExepectHaveBeenCalledTimes).toEqual(1)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should prevent executing twice the same workflow in perfect concurrency with the same transactionId and non idempotent and not async but retention time is set", async () => {
|
it("should prevent executing twice the same workflow in perfect concurrency with the same transactionId and non idempotent and not async but retention time is set", async () => {
|
||||||
|
|||||||
Reference in new issue
Block a user