From a66e3b612a399fb3f61c524f84ebb364cea257b5 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 18 Sep 2025 17:54:37 +0300 Subject: [PATCH 001/124] add job to run tests on v4 cluster --- .github/workflows/pull_request.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index d8549657..8299c42e 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -41,3 +41,28 @@ jobs: name: Test report path: reports/jest-junit.xml reporter: jest-junit + + tests-v4: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: "22" + - name: Install Dependencies + run: npm ci + - name: Run Tests and Add Annotations + run: npm test -- --ci --reporters=default --reporters=github-actions --reporters=jest-junit + env: + CONDUCTOR_SERVER_URL: ${{ vars.SERVER_URL_V4 }} + CONDUCTOR_AUTH_KEY: ${{ secrets.AUTH_KEY_V4 }} + CONDUCTOR_AUTH_SECRET: ${{ secrets.AUTH_SECRET_V4 }} + - name: Publish Dorny Test Results Summary + uses: dorny/test-reporter@v2 + if: ${{ !cancelled() }} + with: + name: Test report + path: reports/jest-junit.xml + reporter: jest-junit From 318f32a8f7f31f759a0aa7dacb197a659aee1259 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 19 Sep 2025 17:44:44 +0300 Subject: [PATCH 002/124] move all the tests to integration-tests folder --- .../DnsCache.test.ts | 2 +- .../DnsResolver.test.ts | 2 +- .../EventResourceService.test.ts | 2 +- .../FetchCatchDns.test.ts | 6 ++-- .../MetadataClient.test.ts | 6 ++-- .../Poller.test.ts | 4 +-- .../ServiceRegistryClient.test.ts | 8 ++--- .../TaskManager.test.ts | 10 +++--- .../TaskRunner.test.ts | 10 +++--- .../TaskRunnerIntTest.test.ts | 6 ++-- .../WorkflowResourceService.test.ts | 8 ++--- .../executor.test.ts | 16 +++++----- .../factory.test.ts | 30 +++++++++--------- .../generators.test.ts | 12 +++---- .../helpers.test.ts | 4 +-- .../readme.test.ts | 8 ++--- .../schedulerExecutor.test.ts | 6 ++-- .../utils}/metadata/compiled.bin | Bin .../metadata/complex_wf_signal_test.json | 0 .../complex_wf_signal_test_subworkflow_1.json | 0 .../complex_wf_signal_test_subworkflow_2.json | 0 .../utils}/metadata/wait_signal_test.json | 0 .../utils}/mockLogger.ts | 2 +- .../utils/test-util.ts | 8 ++--- jest.config.mjs | 3 +- 25 files changed, 76 insertions(+), 77 deletions(-) rename {src/orkes/request/fetchCatchDns/__test__ => integration-tests}/DnsCache.test.ts (90%) rename {src/orkes/request/fetchCatchDns/__test__ => integration-tests}/DnsResolver.test.ts (86%) rename {src/common/open-api/__test__ => integration-tests}/EventResourceService.test.ts (95%) rename {src/orkes/request/fetchCatchDns/__test__ => integration-tests}/FetchCatchDns.test.ts (94%) rename {src/core/__test__ => integration-tests}/MetadataClient.test.ts (97%) rename {src/task/__tests__ => integration-tests}/Poller.test.ts (99%) rename {src/core/__test__ => integration-tests}/ServiceRegistryClient.test.ts (97%) rename {src/task/__tests__ => integration-tests}/TaskManager.test.ts (97%) rename {src/task/__tests__ => integration-tests}/TaskRunner.test.ts (90%) rename {src/task/__tests__ => integration-tests}/TaskRunnerIntTest.test.ts (92%) rename {src/common/open-api/__test__ => integration-tests}/WorkflowResourceService.test.ts (81%) rename {src/core/__test__ => integration-tests}/executor.test.ts (97%) rename {src/core/sdk/__test__ => integration-tests}/factory.test.ts (92%) rename {src/core/generators/__test__ => integration-tests}/generators.test.ts (94%) rename {src/task/__tests__ => integration-tests}/helpers.test.ts (93%) rename {src/__test__ => integration-tests}/readme.test.ts (95%) rename {src/core/__test__ => integration-tests}/schedulerExecutor.test.ts (95%) rename {src/core/__test__ => integration-tests/utils}/metadata/compiled.bin (100%) rename {src/core/__test__ => integration-tests/utils}/metadata/complex_wf_signal_test.json (100%) rename {src/core/__test__ => integration-tests/utils}/metadata/complex_wf_signal_test_subworkflow_1.json (100%) rename {src/core/__test__ => integration-tests/utils}/metadata/complex_wf_signal_test_subworkflow_2.json (100%) rename {src/core/__test__ => integration-tests/utils}/metadata/wait_signal_test.json (100%) rename {src/task/__tests__ => integration-tests/utils}/mockLogger.ts (68%) rename {src/core/__test__ => integration-tests}/utils/test-util.ts (94%) diff --git a/src/orkes/request/fetchCatchDns/__test__/DnsCache.test.ts b/integration-tests/DnsCache.test.ts similarity index 90% rename from src/orkes/request/fetchCatchDns/__test__/DnsCache.test.ts rename to integration-tests/DnsCache.test.ts index 59c3d337..eafc1bbb 100644 --- a/src/orkes/request/fetchCatchDns/__test__/DnsCache.test.ts +++ b/integration-tests/DnsCache.test.ts @@ -1,5 +1,5 @@ import { expect, describe, test } from "@jest/globals"; -import { DnsCacheResolver } from "../DnsCache"; +import { DnsCacheResolver } from "../src/orkes/request/fetchCatchDns/DnsCache"; const sampleDomain = "orkes.io"; const nonExistingDomain = "non-existing-domain.orkesdemo.io"; diff --git a/src/orkes/request/fetchCatchDns/__test__/DnsResolver.test.ts b/integration-tests/DnsResolver.test.ts similarity index 86% rename from src/orkes/request/fetchCatchDns/__test__/DnsResolver.test.ts rename to integration-tests/DnsResolver.test.ts index d9ab9080..4fd5006a 100644 --- a/src/orkes/request/fetchCatchDns/__test__/DnsResolver.test.ts +++ b/integration-tests/DnsResolver.test.ts @@ -1,5 +1,5 @@ import { expect, describe, test } from "@jest/globals"; -import { dnsResolver } from "../DnsResolver"; +import { dnsResolver } from "../src/orkes/request/fetchCatchDns/DnsResolver"; const sampleDomain = "orkes.io"; const nonExistingDomain = "non-existing-domain.orkesdemo.io"; diff --git a/src/common/open-api/__test__/EventResourceService.test.ts b/integration-tests/EventResourceService.test.ts similarity index 95% rename from src/common/open-api/__test__/EventResourceService.test.ts rename to integration-tests/EventResourceService.test.ts index bffe72c5..4131b32a 100644 --- a/src/common/open-api/__test__/EventResourceService.test.ts +++ b/integration-tests/EventResourceService.test.ts @@ -1,5 +1,5 @@ import { expect, describe, test } from "@jest/globals"; -import { orkesConductorClient } from "../../../orkes"; +import { orkesConductorClient } from "../src/orkes"; describe("EventResourceService", () => { test("Should create an event handler with description and tags and then delete it", async () => { diff --git a/src/orkes/request/fetchCatchDns/__test__/FetchCatchDns.test.ts b/integration-tests/FetchCatchDns.test.ts similarity index 94% rename from src/orkes/request/fetchCatchDns/__test__/FetchCatchDns.test.ts rename to integration-tests/FetchCatchDns.test.ts index ac82819b..301926e5 100644 --- a/src/orkes/request/fetchCatchDns/__test__/FetchCatchDns.test.ts +++ b/integration-tests/FetchCatchDns.test.ts @@ -1,7 +1,7 @@ import { expect, describe, test, jest } from "@jest/globals"; -import { fetchCatchDns } from "../fetchCatchDns"; -import { DnsCacheResolver } from "../DnsCache"; -import { FetchFn } from "../../../types"; +import { fetchCatchDns } from "../src/orkes/request/fetchCatchDns/fetchCatchDns"; +import { DnsCacheResolver } from "../src/orkes/request/fetchCatchDns/DnsCache"; +import { FetchFn } from "../src/orkes/types"; describe("fetchCatchDns", () => { test("Should call original fetch if the target is an ip, no param modification", async () => { diff --git a/src/core/__test__/MetadataClient.test.ts b/integration-tests/MetadataClient.test.ts similarity index 97% rename from src/core/__test__/MetadataClient.test.ts rename to integration-tests/MetadataClient.test.ts index f5f6dc74..c85e9303 100644 --- a/src/core/__test__/MetadataClient.test.ts +++ b/integration-tests/MetadataClient.test.ts @@ -1,7 +1,7 @@ import { expect, describe, test, jest } from "@jest/globals"; -import { MetadataClient } from "../metadataClient"; -import { taskDefinition } from "../sdk"; -import { orkesConductorClient } from "../../orkes"; +import { MetadataClient } from "../src/core/metadataClient"; +import { taskDefinition } from "../src/core/sdk"; +import { orkesConductorClient } from "../src/orkes"; describe("MetadataClient", () => { const clientPromise = orkesConductorClient(); diff --git a/src/task/__tests__/Poller.test.ts b/integration-tests/Poller.test.ts similarity index 99% rename from src/task/__tests__/Poller.test.ts rename to integration-tests/Poller.test.ts index d34b2403..f6ecd9d0 100644 --- a/src/task/__tests__/Poller.test.ts +++ b/integration-tests/Poller.test.ts @@ -1,6 +1,6 @@ -import { Poller } from "../Poller"; +import { Poller } from "../src/task/Poller"; import { expect, describe, test, jest } from "@jest/globals"; -import { mockLogger } from "./mockLogger"; +import { mockLogger } from "./utils/mockLogger"; type Task = { description: string; id: number }; diff --git a/src/core/__test__/ServiceRegistryClient.test.ts b/integration-tests/ServiceRegistryClient.test.ts similarity index 97% rename from src/core/__test__/ServiceRegistryClient.test.ts rename to integration-tests/ServiceRegistryClient.test.ts index d2827a2e..1783308c 100644 --- a/src/core/__test__/ServiceRegistryClient.test.ts +++ b/integration-tests/ServiceRegistryClient.test.ts @@ -1,7 +1,7 @@ import {beforeAll, afterEach, describe, expect, jest, test} from "@jest/globals"; -import {ServiceRegistryClient} from "../serviceRegistryClient"; -import {orkesConductorClient} from "../../orkes"; -import {ServiceType} from "../../common/open-api/models/ServiceRegistryModels"; +import {ServiceRegistryClient} from "../src/core/serviceRegistryClient"; +import {orkesConductorClient} from "../src/orkes"; +import {ServiceType} from "../src/common/open-api/models/ServiceRegistryModels"; import * as fs from 'fs'; import * as path from 'path'; @@ -217,7 +217,7 @@ describe("ServiceRegistryClient", () => { // Register the service registry await serviceRegistryClient.addOrUpdateService(testServiceRegistry); - const filePath = path.join(__dirname, 'metadata', 'compiled.bin'); + const filePath = path.join(__dirname, 'utils', 'metadata', 'compiled.bin'); const fileBuffer = fs.readFileSync(filePath); const blob = new Blob([fileBuffer], {type: 'application/octet-stream'}); diff --git a/src/task/__tests__/TaskManager.test.ts b/integration-tests/TaskManager.test.ts similarity index 97% rename from src/task/__tests__/TaskManager.test.ts rename to integration-tests/TaskManager.test.ts index d0fcc2ab..323d14ad 100644 --- a/src/task/__tests__/TaskManager.test.ts +++ b/integration-tests/TaskManager.test.ts @@ -1,9 +1,9 @@ import { expect, describe, test, jest } from "@jest/globals"; -import { simpleTask, taskDefinition, WorkflowExecutor } from "../../core"; -import { orkesConductorClient } from "../../orkes"; -import { TaskManager, ConductorWorker } from "../index"; -import { mockLogger } from "./mockLogger"; -import { TestUtil } from "../../core/__test__/utils/test-util"; +import { simpleTask, taskDefinition, WorkflowExecutor } from "../src/core"; +import { orkesConductorClient } from "../src/orkes"; +import { TaskManager, ConductorWorker } from "../src/task/index"; +import { mockLogger } from "./utils/mockLogger"; +import { TestUtil } from "./utils/test-util"; const BASE_TIME = 500; diff --git a/src/task/__tests__/TaskRunner.test.ts b/integration-tests/TaskRunner.test.ts similarity index 90% rename from src/task/__tests__/TaskRunner.test.ts rename to integration-tests/TaskRunner.test.ts index 29e45cd7..a5db064b 100644 --- a/src/task/__tests__/TaskRunner.test.ts +++ b/integration-tests/TaskRunner.test.ts @@ -1,11 +1,11 @@ import { jest, test, expect } from "@jest/globals"; import type { Mocked } from "jest-mock"; -import { TaskRunner } from "../TaskRunner"; -import { RunnerArgs } from "../types"; -import { mockLogger } from "./mockLogger"; -import { TaskResourceService } from "../../common/open-api"; -import { TaskResultStatusEnum } from "../../common/open-api/models/TaskResultStatusEnum"; +import { TaskRunner } from "../src/task/TaskRunner"; +import { RunnerArgs } from "../src/task/types"; +import { mockLogger } from "./utils/mockLogger"; +import { TaskResourceService } from "../src/common/open-api"; +import { TaskResultStatusEnum } from "../src/common/open-api/models/TaskResultStatusEnum"; test("polls tasks", async () => { const taskClientStub: Mocked< diff --git a/src/task/__tests__/TaskRunnerIntTest.test.ts b/integration-tests/TaskRunnerIntTest.test.ts similarity index 92% rename from src/task/__tests__/TaskRunnerIntTest.test.ts rename to integration-tests/TaskRunnerIntTest.test.ts index 7a42404d..472e9ff5 100644 --- a/src/task/__tests__/TaskRunnerIntTest.test.ts +++ b/integration-tests/TaskRunnerIntTest.test.ts @@ -1,7 +1,7 @@ import { expect, describe, test, jest } from "@jest/globals"; -import { TaskRunner } from "../TaskRunner"; -import { WorkflowExecutor, simpleTask } from "../../core"; -import { orkesConductorClient } from "../../orkes"; +import { TaskRunner } from "../src/task/TaskRunner"; +import { WorkflowExecutor, simpleTask } from "../src/core"; +import { orkesConductorClient } from "../src/orkes"; describe("TaskManager", () => { const clientPromise = orkesConductorClient(); diff --git a/src/common/open-api/__test__/WorkflowResourceService.test.ts b/integration-tests/WorkflowResourceService.test.ts similarity index 81% rename from src/common/open-api/__test__/WorkflowResourceService.test.ts rename to integration-tests/WorkflowResourceService.test.ts index 54235d51..d802195f 100644 --- a/src/common/open-api/__test__/WorkflowResourceService.test.ts +++ b/integration-tests/WorkflowResourceService.test.ts @@ -1,8 +1,8 @@ import { expect, describe, test, jest } from "@jest/globals"; -import { MetadataClient } from "../../../core"; -import { simpleTask, workflow } from "../../../core/sdk"; -import { orkesConductorClient } from "../../../orkes"; -import { TaskDefTypes } from "../../types"; +import { MetadataClient } from "../src/core"; +import { simpleTask, workflow } from "../src/core/sdk"; +import { orkesConductorClient } from "../src/orkes"; +import { TaskDefTypes } from "../src/common/types"; describe("WorkflowResourceService", () => { jest.setTimeout(120000); diff --git a/src/core/__test__/executor.test.ts b/integration-tests/executor.test.ts similarity index 97% rename from src/core/__test__/executor.test.ts rename to integration-tests/executor.test.ts index 2d256353..77cf1154 100644 --- a/src/core/__test__/executor.test.ts +++ b/integration-tests/executor.test.ts @@ -1,14 +1,14 @@ import {expect, describe, test, jest, beforeAll, afterEach, afterAll} from "@jest/globals"; -import {Consistency, ReturnStrategy, SetVariableTaskDef, TaskType, WorkflowDef} from "../../common"; -import { orkesConductorClient } from "../../orkes"; -import { WorkflowExecutor } from "../executor"; +import {Consistency, ReturnStrategy, SetVariableTaskDef, TaskType, WorkflowDef} from "../src/common"; +import { orkesConductorClient } from "../src/orkes"; +import { WorkflowExecutor } from "../src/core/executor"; import { v4 as uuidv4 } from "uuid"; -import {MetadataClient} from "../metadataClient"; +import {MetadataClient} from "../src/core/metadataClient"; import {TestUtil} from "./utils/test-util"; -import {TaskResultStatusEnum} from "../../common/open-api/models/TaskResultStatusEnum"; -import {SignalResponse} from "../../common/open-api/models/SignalResponse"; -import { httpTask } from "../sdk"; -import { TaskClient } from "../taskClient"; +import {TaskResultStatusEnum} from "../src/common/open-api/models/TaskResultStatusEnum"; +import {SignalResponse} from "../src/common/open-api/models/SignalResponse"; +import { httpTask } from "../src/core/sdk"; +import { TaskClient } from "../src/core/taskClient"; describe("Executor", () => { const clientPromise = orkesConductorClient(); diff --git a/src/core/sdk/__test__/factory.test.ts b/integration-tests/factory.test.ts similarity index 92% rename from src/core/sdk/__test__/factory.test.ts rename to integration-tests/factory.test.ts index 3583ad19..0fd660a0 100644 --- a/src/core/sdk/__test__/factory.test.ts +++ b/integration-tests/factory.test.ts @@ -1,19 +1,19 @@ import { expect, describe, it } from "@jest/globals"; -import { doWhileTask, newLoopTask } from "../doWhile"; -import { dynamicForkTask } from "../dynamicFork"; -import { eventTask, sqsEventTask, conductorEventTask } from "../event"; -import { forkTask, forkTaskJoin } from "../forkJoin"; -import { httpTask } from "../http"; -import { inlineTask } from "../inline"; -import { joinTask } from "../join"; -import { jsonJqTask } from "../jsonJq"; -import { kafkaPublishTask } from "../kafkaPublish"; -import { setVariableTask } from "../setVariable"; -import { subWorkflowTask } from "../subWorkflow"; -import { switchTask } from "../switch"; -import { terminateTask } from "../terminate"; -import { waitTaskDuration, waitTaskUntil } from "../wait"; -import { workflow } from "../workflow"; +import { doWhileTask, newLoopTask } from "../src/core/sdk/doWhile"; +import { dynamicForkTask } from "../src/core/sdk/dynamicFork"; +import { eventTask, sqsEventTask, conductorEventTask } from "../src/core/sdk/event"; +import { forkTask, forkTaskJoin } from "../src/core/sdk/forkJoin"; +import { httpTask } from "../src/core/sdk/http"; +import { inlineTask } from "../src/core/sdk/inline"; +import { joinTask } from "../src/core/sdk/join"; +import { jsonJqTask } from "../src/core/sdk/jsonJq"; +import { kafkaPublishTask } from "../src/core/sdk/kafkaPublish"; +import { setVariableTask } from "../src/core/sdk/setVariable"; +import { subWorkflowTask } from "../src/core/sdk/subWorkflow"; +import { switchTask } from "../src/core/sdk/switch"; +import { terminateTask } from "../src/core/sdk/terminate"; +import { waitTaskDuration, waitTaskUntil } from "../src/core/sdk/wait"; +import { workflow } from "../src/core/sdk/workflow"; describe("doWhileTask", () => { it("Should generate a doWhile task ", () => { diff --git a/src/core/generators/__test__/generators.test.ts b/integration-tests/generators.test.ts similarity index 94% rename from src/core/generators/__test__/generators.test.ts rename to integration-tests/generators.test.ts index 336cd185..ec5478ea 100644 --- a/src/core/generators/__test__/generators.test.ts +++ b/integration-tests/generators.test.ts @@ -1,10 +1,10 @@ import { expect, describe, it } from "@jest/globals"; -import { generate, taskGenMapper } from "../generator"; -import { generateSimpleTask } from "../SimpleTask"; -import { TaskType, ForkJoinTaskDef } from "../../../common/types"; -import { generateEvaluationCode, generateInlineTask } from "../InlineTask"; -import { generateDoWhileTask } from "../DoWhileTask"; -import { generateSubWorkflowTask } from "../SubWorkflowTask"; +import { generate, taskGenMapper } from "../src/core/generators/generator"; +import { generateSimpleTask } from "../src/core/generators/SimpleTask"; +import { TaskType, ForkJoinTaskDef } from "../src/common/types"; +import { generateEvaluationCode, generateInlineTask } from "../src/core/generators/InlineTask"; +import { generateDoWhileTask } from "../src/core/generators/DoWhileTask"; +import { generateSubWorkflowTask } from "../src/core/generators/SubWorkflowTask"; describe("Generate", () => { describe("DoWhileTask", () => { diff --git a/src/task/__tests__/helpers.test.ts b/integration-tests/helpers.test.ts similarity index 93% rename from src/task/__tests__/helpers.test.ts rename to integration-tests/helpers.test.ts index 2744210c..2288b74a 100644 --- a/src/task/__tests__/helpers.test.ts +++ b/integration-tests/helpers.test.ts @@ -1,6 +1,6 @@ import { expect, describe, it } from "@jest/globals"; -import { optionEquals } from "../helpers"; -import { TaskRunnerOptions } from "../types"; +import { optionEquals } from "../src/task/helpers"; +import { TaskRunnerOptions } from "../src/task/types"; describe("helpers", () => { it("Should return true if both options are equals", () => { diff --git a/src/__test__/readme.test.ts b/integration-tests/readme.test.ts similarity index 95% rename from src/__test__/readme.test.ts rename to integration-tests/readme.test.ts index 613fab76..d7803756 100644 --- a/src/__test__/readme.test.ts +++ b/integration-tests/readme.test.ts @@ -1,8 +1,8 @@ import { expect, describe, test, jest } from "@jest/globals"; -import { orkesConductorClient } from "../orkes"; -import { WorkflowExecutor, simpleTask, generate } from "../core"; -import { TaskType } from "../common"; -import { TaskRunner } from "../task"; +import { orkesConductorClient } from "../src/orkes"; +import { WorkflowExecutor, simpleTask, generate } from "../src/core"; +import { TaskType } from "../src/common"; +import { TaskRunner } from "../src/task"; describe("TaskManager", () => { const clientPromise = orkesConductorClient(); diff --git a/src/core/__test__/schedulerExecutor.test.ts b/integration-tests/schedulerExecutor.test.ts similarity index 95% rename from src/core/__test__/schedulerExecutor.test.ts rename to integration-tests/schedulerExecutor.test.ts index 4cc5b444..5eb8a228 100644 --- a/src/core/__test__/schedulerExecutor.test.ts +++ b/integration-tests/schedulerExecutor.test.ts @@ -1,7 +1,7 @@ import { expect, describe, test, jest } from "@jest/globals"; -import { orkesConductorClient } from "../../orkes"; -import { SchedulerClient } from "../schedulerClient"; -import { SaveScheduleRequest, TaskType, WorkflowDef } from "../../common"; +import { orkesConductorClient } from "../src/orkes"; +import { SchedulerClient } from "../src/core/schedulerClient"; +import { SaveScheduleRequest, TaskType, WorkflowDef } from "../src/common"; describe("ScheduleExecutor", () => { const clientPromise = orkesConductorClient(); diff --git a/src/core/__test__/metadata/compiled.bin b/integration-tests/utils/metadata/compiled.bin similarity index 100% rename from src/core/__test__/metadata/compiled.bin rename to integration-tests/utils/metadata/compiled.bin diff --git a/src/core/__test__/metadata/complex_wf_signal_test.json b/integration-tests/utils/metadata/complex_wf_signal_test.json similarity index 100% rename from src/core/__test__/metadata/complex_wf_signal_test.json rename to integration-tests/utils/metadata/complex_wf_signal_test.json diff --git a/src/core/__test__/metadata/complex_wf_signal_test_subworkflow_1.json b/integration-tests/utils/metadata/complex_wf_signal_test_subworkflow_1.json similarity index 100% rename from src/core/__test__/metadata/complex_wf_signal_test_subworkflow_1.json rename to integration-tests/utils/metadata/complex_wf_signal_test_subworkflow_1.json diff --git a/src/core/__test__/metadata/complex_wf_signal_test_subworkflow_2.json b/integration-tests/utils/metadata/complex_wf_signal_test_subworkflow_2.json similarity index 100% rename from src/core/__test__/metadata/complex_wf_signal_test_subworkflow_2.json rename to integration-tests/utils/metadata/complex_wf_signal_test_subworkflow_2.json diff --git a/src/core/__test__/metadata/wait_signal_test.json b/integration-tests/utils/metadata/wait_signal_test.json similarity index 100% rename from src/core/__test__/metadata/wait_signal_test.json rename to integration-tests/utils/metadata/wait_signal_test.json diff --git a/src/task/__tests__/mockLogger.ts b/integration-tests/utils/mockLogger.ts similarity index 68% rename from src/task/__tests__/mockLogger.ts rename to integration-tests/utils/mockLogger.ts index e5d8b7d8..c5011ae2 100644 --- a/src/task/__tests__/mockLogger.ts +++ b/integration-tests/utils/mockLogger.ts @@ -1,5 +1,5 @@ import {jest} from "@jest/globals" -import {ConductorLogger} from "../../common/ConductorLogger" +import {ConductorLogger} from "../../src/common/ConductorLogger" export const mockLogger: ConductorLogger = { debug: jest.fn(), diff --git a/src/core/__test__/utils/test-util.ts b/integration-tests/utils/test-util.ts similarity index 94% rename from src/core/__test__/utils/test-util.ts rename to integration-tests/utils/test-util.ts index d0d903a4..3bcefb51 100644 --- a/src/core/__test__/utils/test-util.ts +++ b/integration-tests/utils/test-util.ts @@ -1,8 +1,8 @@ import * as fs from 'fs'; import * as path from 'path'; -import {WorkflowDef} from "../../../common"; -import {MetadataClient} from "../../metadataClient"; -import {WorkflowExecutor} from "../../executor"; +import {WorkflowDef} from "../../src/common"; +import {MetadataClient} from "../../src/core/metadataClient"; +import {WorkflowExecutor} from "../../src/core/executor"; export class TestUtil { private static metadataClient: MetadataClient; @@ -28,7 +28,7 @@ export class TestUtil { */ public static async registerWorkflow(workflowName: string): Promise { try { - const workflowDef = this.getWorkflowDef(`../metadata/${workflowName}.json`); + const workflowDef = this.getWorkflowDef(`./metadata/${workflowName}.json`); await this.metadataClient.registerWorkflowDef(workflowDef, true); console.log(`✓ Registered workflow: ${workflowName}`); } catch (error) { diff --git a/jest.config.mjs b/jest.config.mjs index efcc0ce1..df379202 100644 --- a/jest.config.mjs +++ b/jest.config.mjs @@ -5,8 +5,7 @@ export default { clearMocks: true, coverageProvider: "v8", testMatch: [ - "**/__tests__/**/*.test.[jt]s?(x)", - "**/?(*.)+(spec|test).[tj]s?(x)", + "**/integration-tests/**/*.test.[jt]s?(x)", ], transformIgnorePatterns: ["/node_modules/", "\\.pnp\\.[^\\/]+$"], }; From 089312baf14419b87f22aada64bae24267ca77aa Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 19 Sep 2025 19:18:02 +0300 Subject: [PATCH 003/124] move unit test closer to source files, add seperate jobs during ci/cd --- .github/actions/setup-node-deps/action.yml | 14 ++++ .github/workflows/pull_request.yml | 77 +++++++------------ jest.config.mjs | 1 + package.json | 4 +- .../generators/__tests__}/generators.test.ts | 12 +-- .../core/sdk/__tests__}/factory.test.ts | 30 ++++---- .../fetchCatchDns/__tests__}/DnsCache.test.ts | 2 +- .../__tests__}/DnsResolver.test.ts | 2 +- .../__tests__}/FetchCatchDns.test.ts | 6 +- .../task/__tests__}/Poller.test.ts | 4 +- .../task/__tests__}/TaskRunner.test.ts | 10 +-- .../task/__tests__}/helpers.test.ts | 4 +- 12 files changed, 81 insertions(+), 85 deletions(-) create mode 100644 .github/actions/setup-node-deps/action.yml rename {integration-tests => src/core/generators/__tests__}/generators.test.ts (94%) rename {integration-tests => src/core/sdk/__tests__}/factory.test.ts (92%) rename {integration-tests => src/orkes/request/fetchCatchDns/__tests__}/DnsCache.test.ts (90%) rename {integration-tests => src/orkes/request/fetchCatchDns/__tests__}/DnsResolver.test.ts (86%) rename {integration-tests => src/orkes/request/fetchCatchDns/__tests__}/FetchCatchDns.test.ts (94%) rename {integration-tests => src/task/__tests__}/Poller.test.ts (98%) rename {integration-tests => src/task/__tests__}/TaskRunner.test.ts (90%) rename {integration-tests => src/task/__tests__}/helpers.test.ts (93%) diff --git a/.github/actions/setup-node-deps/action.yml b/.github/actions/setup-node-deps/action.yml new file mode 100644 index 00000000..82147612 --- /dev/null +++ b/.github/actions/setup-node-deps/action.yml @@ -0,0 +1,14 @@ +name: 'Setup Node and Dependencies' +description: 'Checkout code, setup Node, and install dependencies' +runs: + using: 'composite' + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: "22" + - name: Install Dependencies + run: npm ci + shell: bash diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 8299c42e..7dee6270 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -6,63 +6,42 @@ jobs: linter: runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up Node - uses: actions/setup-node@v4 - with: - node-version: "22" - - name: Install Dependencies - run: npm ci + - uses: ./.github/actions/setup-node-deps - name: Run Linter run: npm run lint tests: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + test: + - name: "Unit" + npm_script: "test:unit" + output_file: "unit-test-results.xml" + - name: "Integration-V5" + server_url: ${{ vars.SERVER_URL }} + npm_script: "test:integration" + output_file: "v5-integration-test-results.xml" + cluster: "v5" + - name: "Integration-V4" + server_url: ${{ vars.SERVER_URL_V4 }} + npm_script: "test:integration" + output_file: "v4-integration-test-results.xml" + cluster: "v4" steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up Node - uses: actions/setup-node@v4 - with: - node-version: "22" - - name: Install Dependencies - run: npm ci - - name: Run Tests and Add Annotations - run: npm test -- --ci --reporters=default --reporters=github-actions --reporters=jest-junit - env: - CONDUCTOR_SERVER_URL: ${{ vars.SERVER_URL }} - CONDUCTOR_AUTH_KEY: ${{ secrets.AUTH_KEY }} - CONDUCTOR_AUTH_SECRET: ${{ secrets.AUTH_SECRET }} - - name: Publish Dorny Test Results Summary - uses: dorny/test-reporter@v2 - if: ${{ !cancelled() }} - with: - name: Test report - path: reports/jest-junit.xml - reporter: jest-junit - - tests-v4: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up Node - uses: actions/setup-node@v4 - with: - node-version: "22" - - name: Install Dependencies - run: npm ci - - name: Run Tests and Add Annotations - run: npm test -- --ci --reporters=default --reporters=github-actions --reporters=jest-junit + - uses: ./.github/actions/setup-node-deps + - name: Run ${{ matrix.test.name }} Tests + run: npm run ${{ matrix.test.npm_script }} -- --ci --reporters=default --reporters=github-actions --reporters=jest-junit env: - CONDUCTOR_SERVER_URL: ${{ vars.SERVER_URL_V4 }} - CONDUCTOR_AUTH_KEY: ${{ secrets.AUTH_KEY_V4 }} - CONDUCTOR_AUTH_SECRET: ${{ secrets.AUTH_SECRET_V4 }} - - name: Publish Dorny Test Results Summary + CONDUCTOR_SERVER_URL: ${{ matrix.test.server_url }} + CONDUCTOR_AUTH_KEY: ${{ matrix.test.cluster == 'v5' && secrets.AUTH_KEY || matrix.test.cluster == 'v4' && secrets.AUTH_KEY_V4 || secrets.AUTH_KEY }} + CONDUCTOR_AUTH_SECRET: ${{ matrix.test.cluster == 'v5' && secrets.AUTH_SECRET || matrix.test.cluster == 'v4' && secrets.AUTH_SECRET_V4 || secrets.AUTH_SECRET }} + JEST_JUNIT_OUTPUT_NAME: ${{ matrix.test.output_file }} + - name: Publish ${{ matrix.test.name }} Test Results uses: dorny/test-reporter@v2 if: ${{ !cancelled() }} with: - name: Test report - path: reports/jest-junit.xml + name: ${{ matrix.test.name }} Test Report + path: reports/${{ matrix.test.output_file }} reporter: jest-junit diff --git a/jest.config.mjs b/jest.config.mjs index df379202..82063ee0 100644 --- a/jest.config.mjs +++ b/jest.config.mjs @@ -6,6 +6,7 @@ export default { coverageProvider: "v8", testMatch: [ "**/integration-tests/**/*.test.[jt]s?(x)", + "**/src/**/__tests__/**/*.test.[jt]s?(x)", ], transformIgnorePatterns: ["/node_modules/", "\\.pnp\\.[^\\/]+$"], }; diff --git a/package.json b/package.json index 7f0f7bb1..d3680e6d 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,9 @@ "lint": "npx eslint .", "lint-fix": "npx eslint . --fix", "test": "jest --force-exit --detectOpenHandles", - "ci": "npm run lint && npm run test", + "test:unit": "jest --testMatch='**/src/**/__tests__/**/*.test.[jt]s?(x)' --force-exit", + "test:integration": "jest --testMatch='**/integration-tests/**/*.test.[jt]s?(x)' --force-exit --detectOpenHandles", + "ci": "npm run lint && npm run test:unit && npm run test:integration", "build": "tsup index.ts", "generateClient:models": "npx openapi-typescript-codegen --input http://localhost:8080/api-docs --output src/common/open-api --client node --indent 2 --name ConductorClient --useUnionTypes --exportCore false", "generateClient:core": "npx openapi-typescript-codegen --input http://localhost:8080/api-docs --output src/common/open-api --client node --indent 2 --name ConductorClient --useUnionTypes && find ./src/common/open-api/services/*Service.ts -type f -exec sed -i '' -e 's/api\\///g' {} \\;", diff --git a/integration-tests/generators.test.ts b/src/core/generators/__tests__/generators.test.ts similarity index 94% rename from integration-tests/generators.test.ts rename to src/core/generators/__tests__/generators.test.ts index ec5478ea..336cd185 100644 --- a/integration-tests/generators.test.ts +++ b/src/core/generators/__tests__/generators.test.ts @@ -1,10 +1,10 @@ import { expect, describe, it } from "@jest/globals"; -import { generate, taskGenMapper } from "../src/core/generators/generator"; -import { generateSimpleTask } from "../src/core/generators/SimpleTask"; -import { TaskType, ForkJoinTaskDef } from "../src/common/types"; -import { generateEvaluationCode, generateInlineTask } from "../src/core/generators/InlineTask"; -import { generateDoWhileTask } from "../src/core/generators/DoWhileTask"; -import { generateSubWorkflowTask } from "../src/core/generators/SubWorkflowTask"; +import { generate, taskGenMapper } from "../generator"; +import { generateSimpleTask } from "../SimpleTask"; +import { TaskType, ForkJoinTaskDef } from "../../../common/types"; +import { generateEvaluationCode, generateInlineTask } from "../InlineTask"; +import { generateDoWhileTask } from "../DoWhileTask"; +import { generateSubWorkflowTask } from "../SubWorkflowTask"; describe("Generate", () => { describe("DoWhileTask", () => { diff --git a/integration-tests/factory.test.ts b/src/core/sdk/__tests__/factory.test.ts similarity index 92% rename from integration-tests/factory.test.ts rename to src/core/sdk/__tests__/factory.test.ts index 0fd660a0..3583ad19 100644 --- a/integration-tests/factory.test.ts +++ b/src/core/sdk/__tests__/factory.test.ts @@ -1,19 +1,19 @@ import { expect, describe, it } from "@jest/globals"; -import { doWhileTask, newLoopTask } from "../src/core/sdk/doWhile"; -import { dynamicForkTask } from "../src/core/sdk/dynamicFork"; -import { eventTask, sqsEventTask, conductorEventTask } from "../src/core/sdk/event"; -import { forkTask, forkTaskJoin } from "../src/core/sdk/forkJoin"; -import { httpTask } from "../src/core/sdk/http"; -import { inlineTask } from "../src/core/sdk/inline"; -import { joinTask } from "../src/core/sdk/join"; -import { jsonJqTask } from "../src/core/sdk/jsonJq"; -import { kafkaPublishTask } from "../src/core/sdk/kafkaPublish"; -import { setVariableTask } from "../src/core/sdk/setVariable"; -import { subWorkflowTask } from "../src/core/sdk/subWorkflow"; -import { switchTask } from "../src/core/sdk/switch"; -import { terminateTask } from "../src/core/sdk/terminate"; -import { waitTaskDuration, waitTaskUntil } from "../src/core/sdk/wait"; -import { workflow } from "../src/core/sdk/workflow"; +import { doWhileTask, newLoopTask } from "../doWhile"; +import { dynamicForkTask } from "../dynamicFork"; +import { eventTask, sqsEventTask, conductorEventTask } from "../event"; +import { forkTask, forkTaskJoin } from "../forkJoin"; +import { httpTask } from "../http"; +import { inlineTask } from "../inline"; +import { joinTask } from "../join"; +import { jsonJqTask } from "../jsonJq"; +import { kafkaPublishTask } from "../kafkaPublish"; +import { setVariableTask } from "../setVariable"; +import { subWorkflowTask } from "../subWorkflow"; +import { switchTask } from "../switch"; +import { terminateTask } from "../terminate"; +import { waitTaskDuration, waitTaskUntil } from "../wait"; +import { workflow } from "../workflow"; describe("doWhileTask", () => { it("Should generate a doWhile task ", () => { diff --git a/integration-tests/DnsCache.test.ts b/src/orkes/request/fetchCatchDns/__tests__/DnsCache.test.ts similarity index 90% rename from integration-tests/DnsCache.test.ts rename to src/orkes/request/fetchCatchDns/__tests__/DnsCache.test.ts index eafc1bbb..59c3d337 100644 --- a/integration-tests/DnsCache.test.ts +++ b/src/orkes/request/fetchCatchDns/__tests__/DnsCache.test.ts @@ -1,5 +1,5 @@ import { expect, describe, test } from "@jest/globals"; -import { DnsCacheResolver } from "../src/orkes/request/fetchCatchDns/DnsCache"; +import { DnsCacheResolver } from "../DnsCache"; const sampleDomain = "orkes.io"; const nonExistingDomain = "non-existing-domain.orkesdemo.io"; diff --git a/integration-tests/DnsResolver.test.ts b/src/orkes/request/fetchCatchDns/__tests__/DnsResolver.test.ts similarity index 86% rename from integration-tests/DnsResolver.test.ts rename to src/orkes/request/fetchCatchDns/__tests__/DnsResolver.test.ts index 4fd5006a..d9ab9080 100644 --- a/integration-tests/DnsResolver.test.ts +++ b/src/orkes/request/fetchCatchDns/__tests__/DnsResolver.test.ts @@ -1,5 +1,5 @@ import { expect, describe, test } from "@jest/globals"; -import { dnsResolver } from "../src/orkes/request/fetchCatchDns/DnsResolver"; +import { dnsResolver } from "../DnsResolver"; const sampleDomain = "orkes.io"; const nonExistingDomain = "non-existing-domain.orkesdemo.io"; diff --git a/integration-tests/FetchCatchDns.test.ts b/src/orkes/request/fetchCatchDns/__tests__/FetchCatchDns.test.ts similarity index 94% rename from integration-tests/FetchCatchDns.test.ts rename to src/orkes/request/fetchCatchDns/__tests__/FetchCatchDns.test.ts index 301926e5..ac82819b 100644 --- a/integration-tests/FetchCatchDns.test.ts +++ b/src/orkes/request/fetchCatchDns/__tests__/FetchCatchDns.test.ts @@ -1,7 +1,7 @@ import { expect, describe, test, jest } from "@jest/globals"; -import { fetchCatchDns } from "../src/orkes/request/fetchCatchDns/fetchCatchDns"; -import { DnsCacheResolver } from "../src/orkes/request/fetchCatchDns/DnsCache"; -import { FetchFn } from "../src/orkes/types"; +import { fetchCatchDns } from "../fetchCatchDns"; +import { DnsCacheResolver } from "../DnsCache"; +import { FetchFn } from "../../../types"; describe("fetchCatchDns", () => { test("Should call original fetch if the target is an ip, no param modification", async () => { diff --git a/integration-tests/Poller.test.ts b/src/task/__tests__/Poller.test.ts similarity index 98% rename from integration-tests/Poller.test.ts rename to src/task/__tests__/Poller.test.ts index f6ecd9d0..f42a98c5 100644 --- a/integration-tests/Poller.test.ts +++ b/src/task/__tests__/Poller.test.ts @@ -1,6 +1,6 @@ -import { Poller } from "../src/task/Poller"; +import { Poller } from "../Poller"; import { expect, describe, test, jest } from "@jest/globals"; -import { mockLogger } from "./utils/mockLogger"; +import { mockLogger } from "../../../integration-tests/utils/mockLogger"; type Task = { description: string; id: number }; diff --git a/integration-tests/TaskRunner.test.ts b/src/task/__tests__/TaskRunner.test.ts similarity index 90% rename from integration-tests/TaskRunner.test.ts rename to src/task/__tests__/TaskRunner.test.ts index a5db064b..79aecc4e 100644 --- a/integration-tests/TaskRunner.test.ts +++ b/src/task/__tests__/TaskRunner.test.ts @@ -1,11 +1,11 @@ import { jest, test, expect } from "@jest/globals"; import type { Mocked } from "jest-mock"; -import { TaskRunner } from "../src/task/TaskRunner"; -import { RunnerArgs } from "../src/task/types"; -import { mockLogger } from "./utils/mockLogger"; -import { TaskResourceService } from "../src/common/open-api"; -import { TaskResultStatusEnum } from "../src/common/open-api/models/TaskResultStatusEnum"; +import { TaskRunner } from "../TaskRunner"; +import { RunnerArgs } from "../types"; +import { mockLogger } from "../../../integration-tests/utils/mockLogger"; +import { TaskResourceService } from "../../common/open-api"; +import { TaskResultStatusEnum } from "../../common/open-api/models/TaskResultStatusEnum"; test("polls tasks", async () => { const taskClientStub: Mocked< diff --git a/integration-tests/helpers.test.ts b/src/task/__tests__/helpers.test.ts similarity index 93% rename from integration-tests/helpers.test.ts rename to src/task/__tests__/helpers.test.ts index 2288b74a..2744210c 100644 --- a/integration-tests/helpers.test.ts +++ b/src/task/__tests__/helpers.test.ts @@ -1,6 +1,6 @@ import { expect, describe, it } from "@jest/globals"; -import { optionEquals } from "../src/task/helpers"; -import { TaskRunnerOptions } from "../src/task/types"; +import { optionEquals } from "../helpers"; +import { TaskRunnerOptions } from "../types"; describe("helpers", () => { it("Should return true if both options are equals", () => { From 08d44624469cd0efae05c7ac7ac62752c061dae9 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 19 Sep 2025 19:22:22 +0300 Subject: [PATCH 004/124] fix gh actions --- .github/actions/setup-node-deps/action.yml | 14 -------------- .github/workflows/pull_request.yml | 18 ++++++++++++++++-- 2 files changed, 16 insertions(+), 16 deletions(-) delete mode 100644 .github/actions/setup-node-deps/action.yml diff --git a/.github/actions/setup-node-deps/action.yml b/.github/actions/setup-node-deps/action.yml deleted file mode 100644 index 82147612..00000000 --- a/.github/actions/setup-node-deps/action.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: 'Setup Node and Dependencies' -description: 'Checkout code, setup Node, and install dependencies' -runs: - using: 'composite' - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up Node - uses: actions/setup-node@v4 - with: - node-version: "22" - - name: Install Dependencies - run: npm ci - shell: bash diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 7dee6270..05a03194 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -6,7 +6,14 @@ jobs: linter: runs-on: ubuntu-latest steps: - - uses: ./.github/actions/setup-node-deps + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: "22" + - name: Install Dependencies + run: npm ci - name: Run Linter run: npm run lint @@ -30,7 +37,14 @@ jobs: output_file: "v4-integration-test-results.xml" cluster: "v4" steps: - - uses: ./.github/actions/setup-node-deps + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: "22" + - name: Install Dependencies + run: npm ci - name: Run ${{ matrix.test.name }} Tests run: npm run ${{ matrix.test.npm_script }} -- --ci --reporters=default --reporters=github-actions --reporters=jest-junit env: From 06fd9a0e201b1ad5bfe13342bafca0eb01bd056a Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 19 Sep 2025 19:29:44 +0300 Subject: [PATCH 005/124] simplify gh action --- .github/workflows/pull_request.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 05a03194..84d3a60f 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -49,8 +49,8 @@ jobs: run: npm run ${{ matrix.test.npm_script }} -- --ci --reporters=default --reporters=github-actions --reporters=jest-junit env: CONDUCTOR_SERVER_URL: ${{ matrix.test.server_url }} - CONDUCTOR_AUTH_KEY: ${{ matrix.test.cluster == 'v5' && secrets.AUTH_KEY || matrix.test.cluster == 'v4' && secrets.AUTH_KEY_V4 || secrets.AUTH_KEY }} - CONDUCTOR_AUTH_SECRET: ${{ matrix.test.cluster == 'v5' && secrets.AUTH_SECRET || matrix.test.cluster == 'v4' && secrets.AUTH_SECRET_V4 || secrets.AUTH_SECRET }} + CONDUCTOR_AUTH_KEY: ${{ matrix.test.cluster == 'v4' && secrets.AUTH_KEY_V4 || secrets.AUTH_KEY }} + CONDUCTOR_AUTH_SECRET: ${{ matrix.test.cluster == 'v4' && secrets.AUTH_SECRET_V4 || secrets.AUTH_SECRET }} JEST_JUNIT_OUTPUT_NAME: ${{ matrix.test.output_file }} - name: Publish ${{ matrix.test.name }} Test Results uses: dorny/test-reporter@v2 From 6ffac7b28e2bf68a3502fd9a269463aea0d5b378 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 19 Sep 2025 19:51:19 +0300 Subject: [PATCH 006/124] simplify gh action --- .github/workflows/pull_request.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 84d3a60f..048e20ae 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -27,12 +27,10 @@ jobs: npm_script: "test:unit" output_file: "unit-test-results.xml" - name: "Integration-V5" - server_url: ${{ vars.SERVER_URL }} npm_script: "test:integration" output_file: "v5-integration-test-results.xml" cluster: "v5" - name: "Integration-V4" - server_url: ${{ vars.SERVER_URL_V4 }} npm_script: "test:integration" output_file: "v4-integration-test-results.xml" cluster: "v4" @@ -48,7 +46,7 @@ jobs: - name: Run ${{ matrix.test.name }} Tests run: npm run ${{ matrix.test.npm_script }} -- --ci --reporters=default --reporters=github-actions --reporters=jest-junit env: - CONDUCTOR_SERVER_URL: ${{ matrix.test.server_url }} + CONDUCTOR_SERVER_URL: ${{ matrix.test.cluster == 'v4' && vars.SERVER_URL_V4 || vars.SERVER_URL }} CONDUCTOR_AUTH_KEY: ${{ matrix.test.cluster == 'v4' && secrets.AUTH_KEY_V4 || secrets.AUTH_KEY }} CONDUCTOR_AUTH_SECRET: ${{ matrix.test.cluster == 'v4' && secrets.AUTH_SECRET_V4 || secrets.AUTH_SECRET }} JEST_JUNIT_OUTPUT_NAME: ${{ matrix.test.output_file }} From 29ac67bef10bb0f09827b1a316bbf91ad2f1de84 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 19 Sep 2025 20:01:51 +0300 Subject: [PATCH 007/124] simplify gh action --- .github/workflows/pull_request.yml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 048e20ae..9f06be8e 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -23,16 +23,13 @@ jobs: fail-fast: false matrix: test: - - name: "Unit" + - name: "unit" npm_script: "test:unit" - output_file: "unit-test-results.xml" - - name: "Integration-V5" + - name: "integration-v5" npm_script: "test:integration" - output_file: "v5-integration-test-results.xml" cluster: "v5" - - name: "Integration-V4" + - name: "integration-v4" npm_script: "test:integration" - output_file: "v4-integration-test-results.xml" cluster: "v4" steps: - name: Checkout @@ -49,11 +46,11 @@ jobs: CONDUCTOR_SERVER_URL: ${{ matrix.test.cluster == 'v4' && vars.SERVER_URL_V4 || vars.SERVER_URL }} CONDUCTOR_AUTH_KEY: ${{ matrix.test.cluster == 'v4' && secrets.AUTH_KEY_V4 || secrets.AUTH_KEY }} CONDUCTOR_AUTH_SECRET: ${{ matrix.test.cluster == 'v4' && secrets.AUTH_SECRET_V4 || secrets.AUTH_SECRET }} - JEST_JUNIT_OUTPUT_NAME: ${{ matrix.test.output_file }} + JEST_JUNIT_OUTPUT_NAME: ${{ matrix.test.name }}-test-results.xml - name: Publish ${{ matrix.test.name }} Test Results uses: dorny/test-reporter@v2 if: ${{ !cancelled() }} with: name: ${{ matrix.test.name }} Test Report - path: reports/${{ matrix.test.output_file }} + path: reports/${{ matrix.test.name }}-test-results.xml reporter: jest-junit From a6a34ece78b45d08ce7f522c71be07a6831903a9 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 19 Sep 2025 20:09:23 +0300 Subject: [PATCH 008/124] simplify gh action --- .github/workflows/pull_request.yml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 9f06be8e..d11cb500 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -24,12 +24,9 @@ jobs: matrix: test: - name: "unit" - npm_script: "test:unit" - - name: "integration-v5" - npm_script: "test:integration" + - name: "integration" cluster: "v5" - - name: "integration-v4" - npm_script: "test:integration" + - name: "integration" cluster: "v4" steps: - name: Checkout @@ -41,16 +38,16 @@ jobs: - name: Install Dependencies run: npm ci - name: Run ${{ matrix.test.name }} Tests - run: npm run ${{ matrix.test.npm_script }} -- --ci --reporters=default --reporters=github-actions --reporters=jest-junit + run: npm run test:${{ matrix.test.name }} -- --ci --reporters=default --reporters=github-actions --reporters=jest-junit env: CONDUCTOR_SERVER_URL: ${{ matrix.test.cluster == 'v4' && vars.SERVER_URL_V4 || vars.SERVER_URL }} CONDUCTOR_AUTH_KEY: ${{ matrix.test.cluster == 'v4' && secrets.AUTH_KEY_V4 || secrets.AUTH_KEY }} CONDUCTOR_AUTH_SECRET: ${{ matrix.test.cluster == 'v4' && secrets.AUTH_SECRET_V4 || secrets.AUTH_SECRET }} - JEST_JUNIT_OUTPUT_NAME: ${{ matrix.test.name }}-test-results.xml + JEST_JUNIT_OUTPUT_NAME: ${{ matrix.test.name }}${{ matrix.test.cluster }}-test-results.xml - name: Publish ${{ matrix.test.name }} Test Results uses: dorny/test-reporter@v2 if: ${{ !cancelled() }} with: name: ${{ matrix.test.name }} Test Report - path: reports/${{ matrix.test.name }}-test-results.xml + path: reports/${{ matrix.test.name }}${{ matrix.test.cluster }}-test-results.xml reporter: jest-junit From f45bc55de67e29a3aa81f902b0ce2f853e834fa3 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 19 Sep 2025 20:21:49 +0300 Subject: [PATCH 009/124] cleanup --- .github/workflows/pull_request.yml | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index d11cb500..35a92f4b 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -37,7 +37,7 @@ jobs: node-version: "22" - name: Install Dependencies run: npm ci - - name: Run ${{ matrix.test.name }} Tests + - name: Run ${{ matrix.test.name }}${{ matrix.test.cluster }} Tests and Add Annotations run: npm run test:${{ matrix.test.name }} -- --ci --reporters=default --reporters=github-actions --reporters=jest-junit env: CONDUCTOR_SERVER_URL: ${{ matrix.test.cluster == 'v4' && vars.SERVER_URL_V4 || vars.SERVER_URL }} diff --git a/package.json b/package.json index d3680e6d..330d5030 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "test": "jest --force-exit --detectOpenHandles", "test:unit": "jest --testMatch='**/src/**/__tests__/**/*.test.[jt]s?(x)' --force-exit", "test:integration": "jest --testMatch='**/integration-tests/**/*.test.[jt]s?(x)' --force-exit --detectOpenHandles", - "ci": "npm run lint && npm run test:unit && npm run test:integration", + "ci": "npm run lint && npm run test", "build": "tsup index.ts", "generateClient:models": "npx openapi-typescript-codegen --input http://localhost:8080/api-docs --output src/common/open-api --client node --indent 2 --name ConductorClient --useUnionTypes --exportCore false", "generateClient:core": "npx openapi-typescript-codegen --input http://localhost:8080/api-docs --output src/common/open-api --client node --indent 2 --name ConductorClient --useUnionTypes && find ./src/common/open-api/services/*Service.ts -type f -exec sed -i '' -e 's/api\\///g' {} \\;", From 5bbed6c463d1856e8894ed2725e36843f5647025 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Mon, 22 Sep 2025 01:31:25 +0300 Subject: [PATCH 010/124] separate common and v5 only tests --- .../{ => common}/EventResourceService.test.ts | 2 +- .../{ => common}/MetadataClient.test.ts | 6 +- .../{ => common}/TaskManager.test.ts | 10 +- .../{ => common}/TaskRunnerIntTest.test.ts | 6 +- .../WorkflowResourceService.test.ts | 8 +- integration-tests/common/executor.test.ts | 168 +++++++++++++++++ .../metadata/complex_wf_signal_test.json | 0 .../complex_wf_signal_test_subworkflow_1.json | 0 .../complex_wf_signal_test_subworkflow_2.json | 0 .../metadata/wait_signal_test.json | 0 integration-tests/{ => common}/readme.test.ts | 8 +- .../{ => common}/schedulerExecutor.test.ts | 6 +- integration-tests/utils/test-util.ts | 2 +- .../ServiceRegistryClient.test.ts | 8 +- .../{ => v5-only}/executor.test.ts | 176 +----------------- .../{utils => v5-only}/metadata/compiled.bin | Bin jest.config.mjs | 4 - 17 files changed, 203 insertions(+), 201 deletions(-) rename integration-tests/{ => common}/EventResourceService.test.ts (95%) rename integration-tests/{ => common}/MetadataClient.test.ts (96%) rename integration-tests/{ => common}/TaskManager.test.ts (97%) rename integration-tests/{ => common}/TaskRunnerIntTest.test.ts (91%) rename integration-tests/{ => common}/WorkflowResourceService.test.ts (80%) create mode 100644 integration-tests/common/executor.test.ts rename integration-tests/{utils => common}/metadata/complex_wf_signal_test.json (100%) rename integration-tests/{utils => common}/metadata/complex_wf_signal_test_subworkflow_1.json (100%) rename integration-tests/{utils => common}/metadata/complex_wf_signal_test_subworkflow_2.json (100%) rename integration-tests/{utils => common}/metadata/wait_signal_test.json (100%) rename integration-tests/{ => common}/readme.test.ts (95%) rename integration-tests/{ => common}/schedulerExecutor.test.ts (95%) rename integration-tests/{ => v5-only}/ServiceRegistryClient.test.ts (97%) rename integration-tests/{ => v5-only}/executor.test.ts (70%) rename integration-tests/{utils => v5-only}/metadata/compiled.bin (100%) diff --git a/integration-tests/EventResourceService.test.ts b/integration-tests/common/EventResourceService.test.ts similarity index 95% rename from integration-tests/EventResourceService.test.ts rename to integration-tests/common/EventResourceService.test.ts index 4131b32a..4968b9ba 100644 --- a/integration-tests/EventResourceService.test.ts +++ b/integration-tests/common/EventResourceService.test.ts @@ -1,5 +1,5 @@ import { expect, describe, test } from "@jest/globals"; -import { orkesConductorClient } from "../src/orkes"; +import { orkesConductorClient } from "../../src/orkes"; describe("EventResourceService", () => { test("Should create an event handler with description and tags and then delete it", async () => { diff --git a/integration-tests/MetadataClient.test.ts b/integration-tests/common/MetadataClient.test.ts similarity index 96% rename from integration-tests/MetadataClient.test.ts rename to integration-tests/common/MetadataClient.test.ts index c85e9303..f0b5543c 100644 --- a/integration-tests/MetadataClient.test.ts +++ b/integration-tests/common/MetadataClient.test.ts @@ -1,7 +1,7 @@ import { expect, describe, test, jest } from "@jest/globals"; -import { MetadataClient } from "../src/core/metadataClient"; -import { taskDefinition } from "../src/core/sdk"; -import { orkesConductorClient } from "../src/orkes"; +import { MetadataClient } from "../../src/core/metadataClient"; +import { taskDefinition } from "../../src/core/sdk"; +import { orkesConductorClient } from "../../src/orkes"; describe("MetadataClient", () => { const clientPromise = orkesConductorClient(); diff --git a/integration-tests/TaskManager.test.ts b/integration-tests/common/TaskManager.test.ts similarity index 97% rename from integration-tests/TaskManager.test.ts rename to integration-tests/common/TaskManager.test.ts index 323d14ad..1d05543c 100644 --- a/integration-tests/TaskManager.test.ts +++ b/integration-tests/common/TaskManager.test.ts @@ -1,9 +1,9 @@ import { expect, describe, test, jest } from "@jest/globals"; -import { simpleTask, taskDefinition, WorkflowExecutor } from "../src/core"; -import { orkesConductorClient } from "../src/orkes"; -import { TaskManager, ConductorWorker } from "../src/task/index"; -import { mockLogger } from "./utils/mockLogger"; -import { TestUtil } from "./utils/test-util"; +import { simpleTask, taskDefinition, WorkflowExecutor } from "../../src/core"; +import { orkesConductorClient } from "../../src/orkes"; +import { TaskManager, ConductorWorker } from "../../src/task/index"; +import { mockLogger } from "../utils/mockLogger"; +import { TestUtil } from "../utils/test-util"; const BASE_TIME = 500; diff --git a/integration-tests/TaskRunnerIntTest.test.ts b/integration-tests/common/TaskRunnerIntTest.test.ts similarity index 91% rename from integration-tests/TaskRunnerIntTest.test.ts rename to integration-tests/common/TaskRunnerIntTest.test.ts index 472e9ff5..9eadb449 100644 --- a/integration-tests/TaskRunnerIntTest.test.ts +++ b/integration-tests/common/TaskRunnerIntTest.test.ts @@ -1,7 +1,7 @@ import { expect, describe, test, jest } from "@jest/globals"; -import { TaskRunner } from "../src/task/TaskRunner"; -import { WorkflowExecutor, simpleTask } from "../src/core"; -import { orkesConductorClient } from "../src/orkes"; +import { TaskRunner } from "../../src/task/TaskRunner"; +import { WorkflowExecutor, simpleTask } from "../../src/core"; +import { orkesConductorClient } from "../../src/orkes"; describe("TaskManager", () => { const clientPromise = orkesConductorClient(); diff --git a/integration-tests/WorkflowResourceService.test.ts b/integration-tests/common/WorkflowResourceService.test.ts similarity index 80% rename from integration-tests/WorkflowResourceService.test.ts rename to integration-tests/common/WorkflowResourceService.test.ts index d802195f..a9835086 100644 --- a/integration-tests/WorkflowResourceService.test.ts +++ b/integration-tests/common/WorkflowResourceService.test.ts @@ -1,8 +1,8 @@ import { expect, describe, test, jest } from "@jest/globals"; -import { MetadataClient } from "../src/core"; -import { simpleTask, workflow } from "../src/core/sdk"; -import { orkesConductorClient } from "../src/orkes"; -import { TaskDefTypes } from "../src/common/types"; +import { MetadataClient } from "../../src/core"; +import { simpleTask, workflow } from "../../src/core/sdk"; +import { orkesConductorClient } from "../../src/orkes"; +import { TaskDefTypes } from "../../src/common/types"; describe("WorkflowResourceService", () => { jest.setTimeout(120000); diff --git a/integration-tests/common/executor.test.ts b/integration-tests/common/executor.test.ts new file mode 100644 index 00000000..55f72541 --- /dev/null +++ b/integration-tests/common/executor.test.ts @@ -0,0 +1,168 @@ +import {expect, describe, test, jest} from "@jest/globals"; +import { SetVariableTaskDef, TaskType, WorkflowDef} from "../../src/common"; +import { orkesConductorClient } from "../../src/orkes"; +import { WorkflowExecutor } from "../../src/core/executor"; +import { v4 as uuidv4 } from "uuid"; +import {TestUtil} from "../utils/test-util"; +import { httpTask } from "../../src/core/sdk"; +import { TaskClient } from "../../src/core/taskClient"; + +describe("Executor", () => { + const clientPromise = orkesConductorClient(); + + jest.setTimeout(15000); + const name = `testWorkflow-${Date.now()}`; + const version = 1; + test("Should be able to register a workflow", async () => { + const client = await clientPromise; + const executor = new WorkflowExecutor(client); + + const workflowDefinition: WorkflowDef = { + name, + version, + tasks: [ + { + type: TaskType.SET_VARIABLE, + name: "setVariable", + taskReferenceName: "httpTaskRef", + inputParameters: { + hello: "world", + }, + }, + ], + inputParameters: [], + timeoutSeconds: 15, + }; + + await expect( + executor.registerWorkflow(true, workflowDefinition) + ).resolves.not.toThrow(); + const workflowDefinitionFromApi = await client.metadataResource.get( + name, + version + ); + expect(workflowDefinitionFromApi.name).toEqual(name); + expect(workflowDefinitionFromApi.version).toEqual(version); + expect(workflowDefinitionFromApi.tasks[0].name).toEqual( + workflowDefinition.tasks[0].name + ); + expect(workflowDefinitionFromApi.tasks[0].taskReferenceName).toEqual( + workflowDefinition.tasks[0].taskReferenceName + ); + expect(workflowDefinitionFromApi.tasks[0].inputParameters).toEqual( + (workflowDefinition.tasks[0] as SetVariableTaskDef).inputParameters + ); + }); + + let executionId: string | undefined = undefined; + test("Should be able to start a workflow", async () => { + const client = await clientPromise; + const executor = new WorkflowExecutor(client); + executionId = await executor.startWorkflow({ name, version }); + expect(executionId).toBeTruthy(); + }); + + test("Should be able to execute workflow synchronously", async () => { + const client = await clientPromise; + const executor = new WorkflowExecutor(client); + const workflowRun = await executor.executeWorkflow( + { + name: name, + version: version, + }, + name, + version, + uuidv4() + ); + expect(workflowRun.status).toEqual("COMPLETED"); + }); + + test("Should be able to get workflow execution status ", async () => { + const client = await clientPromise; + const executor = new WorkflowExecutor(client); + const workflowStatus = await executor.getWorkflowStatus( + executionId!, + true, + true + ); + expect(workflowStatus.status).toBeTruthy(); + }); + + test("Should return workflow status detail", async () => { + const client = await clientPromise; + const executor = new WorkflowExecutor(client); + const workflowStatus = await executor.getWorkflow(executionId!, true); + + expect(workflowStatus.status).toBeTruthy(); + expect(workflowStatus.tasks?.length).toBe(1); + }); + test("Should execute a workflow with indempotency key", async () => { + const client = await clientPromise; + const executor = new WorkflowExecutor(client); + const idempotencyKey = uuidv4(); + const executionId = await executor.startWorkflow({ + name: name, + version: version, + idempotencyKey, + idempotencyStrategy: "RETURN_EXISTING", + }); + + const executionDetails = await executor.getWorkflow(executionId!, true); + expect(executionDetails.idempotencyKey).toEqual(idempotencyKey); + }); + + test("Should run workflow with http task with asyncComplete true", async () => { + const client = await clientPromise; + const executor = new WorkflowExecutor(client); + + await executor.registerWorkflow(true, { + name: "test_jssdk_workflow_with_http_task_with_asyncComplete_true", + version: 1, + ownerEmail: "developers@orkes.io", + tasks: [httpTask("test_jssdk_http_task_with_asyncComplete_true", { uri: "http://www.yahoo.com", method: "GET" }, true)], + inputParameters: [], + outputParameters: {}, + timeoutSeconds: 300, + }); + + const executionId = await executor.startWorkflow({ + name: "test_jssdk_workflow_with_http_task_with_asyncComplete_true", + input: {}, + version: 1, + }); + + const workflowStatusBefore = await TestUtil.waitForWorkflowStatus(executor, executionId, "RUNNING"); + + expect(["IN_PROGRESS", "SCHEDULED"]).toContain(workflowStatusBefore.tasks?.[0]?.status); + + const taskClient = new TaskClient(client); + taskClient.updateTaskResult(executionId, "test_jssdk_http_task_with_asyncComplete_true", "COMPLETED", { hello: "From manuall api call updating task result" }); + + const workflowStatusAfter = await TestUtil.waitForWorkflowStatus(executor, executionId, "COMPLETED"); + + expect(workflowStatusAfter.tasks?.[0]?.status).toEqual("COMPLETED"); + }); + + test("Should run workflow with an optional http task", async () => { + const executor = new WorkflowExecutor(await clientPromise); + + await executor.registerWorkflow(true, { + name: "test_jssdk_workflow_with_optional_http_task", + version: 1, + ownerEmail: "developers@orkes.io", + tasks: [httpTask("test_jssdk_optional_http_task", { uri: "uncorrect_uri", method: "GET" }, false, true)], + inputParameters: [], + outputParameters: {}, + timeoutSeconds: 300, + }); + + const executionId = await executor.startWorkflow({ + name: "test_jssdk_workflow_with_optional_http_task", + input: {}, + version: 1, + }); + + const workflowStatus = await TestUtil.waitForWorkflowStatus(executor, executionId, "COMPLETED"); + expect(["FAILED", "COMPLETED_WITH_ERRORS"]).toContain(workflowStatus.tasks?.[0]?.status); + }); +}); diff --git a/integration-tests/utils/metadata/complex_wf_signal_test.json b/integration-tests/common/metadata/complex_wf_signal_test.json similarity index 100% rename from integration-tests/utils/metadata/complex_wf_signal_test.json rename to integration-tests/common/metadata/complex_wf_signal_test.json diff --git a/integration-tests/utils/metadata/complex_wf_signal_test_subworkflow_1.json b/integration-tests/common/metadata/complex_wf_signal_test_subworkflow_1.json similarity index 100% rename from integration-tests/utils/metadata/complex_wf_signal_test_subworkflow_1.json rename to integration-tests/common/metadata/complex_wf_signal_test_subworkflow_1.json diff --git a/integration-tests/utils/metadata/complex_wf_signal_test_subworkflow_2.json b/integration-tests/common/metadata/complex_wf_signal_test_subworkflow_2.json similarity index 100% rename from integration-tests/utils/metadata/complex_wf_signal_test_subworkflow_2.json rename to integration-tests/common/metadata/complex_wf_signal_test_subworkflow_2.json diff --git a/integration-tests/utils/metadata/wait_signal_test.json b/integration-tests/common/metadata/wait_signal_test.json similarity index 100% rename from integration-tests/utils/metadata/wait_signal_test.json rename to integration-tests/common/metadata/wait_signal_test.json diff --git a/integration-tests/readme.test.ts b/integration-tests/common/readme.test.ts similarity index 95% rename from integration-tests/readme.test.ts rename to integration-tests/common/readme.test.ts index d7803756..e8a73621 100644 --- a/integration-tests/readme.test.ts +++ b/integration-tests/common/readme.test.ts @@ -1,8 +1,8 @@ import { expect, describe, test, jest } from "@jest/globals"; -import { orkesConductorClient } from "../src/orkes"; -import { WorkflowExecutor, simpleTask, generate } from "../src/core"; -import { TaskType } from "../src/common"; -import { TaskRunner } from "../src/task"; +import { orkesConductorClient } from "../../src/orkes"; +import { WorkflowExecutor, simpleTask, generate } from "../../src/core"; +import { TaskType } from "../../src/common"; +import { TaskRunner } from "../../src/task"; describe("TaskManager", () => { const clientPromise = orkesConductorClient(); diff --git a/integration-tests/schedulerExecutor.test.ts b/integration-tests/common/schedulerExecutor.test.ts similarity index 95% rename from integration-tests/schedulerExecutor.test.ts rename to integration-tests/common/schedulerExecutor.test.ts index 5eb8a228..d25c9549 100644 --- a/integration-tests/schedulerExecutor.test.ts +++ b/integration-tests/common/schedulerExecutor.test.ts @@ -1,7 +1,7 @@ import { expect, describe, test, jest } from "@jest/globals"; -import { orkesConductorClient } from "../src/orkes"; -import { SchedulerClient } from "../src/core/schedulerClient"; -import { SaveScheduleRequest, TaskType, WorkflowDef } from "../src/common"; +import { orkesConductorClient } from "../../src/orkes"; +import { SchedulerClient } from "../../src/core/schedulerClient"; +import { SaveScheduleRequest, TaskType, WorkflowDef } from "../../src/common"; describe("ScheduleExecutor", () => { const clientPromise = orkesConductorClient(); diff --git a/integration-tests/utils/test-util.ts b/integration-tests/utils/test-util.ts index 3bcefb51..f6246e52 100644 --- a/integration-tests/utils/test-util.ts +++ b/integration-tests/utils/test-util.ts @@ -28,7 +28,7 @@ export class TestUtil { */ public static async registerWorkflow(workflowName: string): Promise { try { - const workflowDef = this.getWorkflowDef(`./metadata/${workflowName}.json`); + const workflowDef = this.getWorkflowDef(`../common/metadata/${workflowName}.json`); await this.metadataClient.registerWorkflowDef(workflowDef, true); console.log(`✓ Registered workflow: ${workflowName}`); } catch (error) { diff --git a/integration-tests/ServiceRegistryClient.test.ts b/integration-tests/v5-only/ServiceRegistryClient.test.ts similarity index 97% rename from integration-tests/ServiceRegistryClient.test.ts rename to integration-tests/v5-only/ServiceRegistryClient.test.ts index 1783308c..b25cf2f8 100644 --- a/integration-tests/ServiceRegistryClient.test.ts +++ b/integration-tests/v5-only/ServiceRegistryClient.test.ts @@ -1,7 +1,7 @@ import {beforeAll, afterEach, describe, expect, jest, test} from "@jest/globals"; -import {ServiceRegistryClient} from "../src/core/serviceRegistryClient"; -import {orkesConductorClient} from "../src/orkes"; -import {ServiceType} from "../src/common/open-api/models/ServiceRegistryModels"; +import {ServiceRegistryClient} from "../../src/core/serviceRegistryClient"; +import {orkesConductorClient} from "../../src/orkes"; +import {ServiceType} from "../../src/common/open-api/models/ServiceRegistryModels"; import * as fs from 'fs'; import * as path from 'path'; @@ -217,7 +217,7 @@ describe("ServiceRegistryClient", () => { // Register the service registry await serviceRegistryClient.addOrUpdateService(testServiceRegistry); - const filePath = path.join(__dirname, 'utils', 'metadata', 'compiled.bin'); + const filePath = path.join(__dirname, 'metadata', 'compiled.bin'); const fileBuffer = fs.readFileSync(filePath); const blob = new Blob([fileBuffer], {type: 'application/octet-stream'}); diff --git a/integration-tests/executor.test.ts b/integration-tests/v5-only/executor.test.ts similarity index 70% rename from integration-tests/executor.test.ts rename to integration-tests/v5-only/executor.test.ts index 77cf1154..ad1b8fcf 100644 --- a/integration-tests/executor.test.ts +++ b/integration-tests/v5-only/executor.test.ts @@ -1,174 +1,12 @@ import {expect, describe, test, jest, beforeAll, afterEach, afterAll} from "@jest/globals"; -import {Consistency, ReturnStrategy, SetVariableTaskDef, TaskType, WorkflowDef} from "../src/common"; -import { orkesConductorClient } from "../src/orkes"; -import { WorkflowExecutor } from "../src/core/executor"; +import {Consistency, ReturnStrategy, SetVariableTaskDef, TaskType, WorkflowDef} from "../../src/common"; +import { orkesConductorClient } from "../../src/orkes"; +import { WorkflowExecutor } from "../../src/core/executor"; import { v4 as uuidv4 } from "uuid"; -import {MetadataClient} from "../src/core/metadataClient"; -import {TestUtil} from "./utils/test-util"; -import {TaskResultStatusEnum} from "../src/common/open-api/models/TaskResultStatusEnum"; -import {SignalResponse} from "../src/common/open-api/models/SignalResponse"; -import { httpTask } from "../src/core/sdk"; -import { TaskClient } from "../src/core/taskClient"; - -describe("Executor", () => { - const clientPromise = orkesConductorClient(); - - jest.setTimeout(15000); - const name = `testWorkflow-${Date.now()}`; - const version = 1; - test("Should be able to register a workflow", async () => { - const client = await clientPromise; - const executor = new WorkflowExecutor(client); - - const workflowDefinition: WorkflowDef = { - name, - version, - tasks: [ - { - type: TaskType.SET_VARIABLE, - name: "setVariable", - taskReferenceName: "httpTaskRef", - inputParameters: { - hello: "world", - }, - }, - ], - inputParameters: [], - timeoutSeconds: 15, - }; - - await expect( - executor.registerWorkflow(true, workflowDefinition) - ).resolves.not.toThrow(); - const workflowDefinitionFromApi = await client.metadataResource.get( - name, - version - ); - expect(workflowDefinitionFromApi.name).toEqual(name); - expect(workflowDefinitionFromApi.version).toEqual(version); - expect(workflowDefinitionFromApi.tasks[0].name).toEqual( - workflowDefinition.tasks[0].name - ); - expect(workflowDefinitionFromApi.tasks[0].taskReferenceName).toEqual( - workflowDefinition.tasks[0].taskReferenceName - ); - expect(workflowDefinitionFromApi.tasks[0].inputParameters).toEqual( - (workflowDefinition.tasks[0] as SetVariableTaskDef).inputParameters - ); - }); - - let executionId: string | undefined = undefined; - test("Should be able to start a workflow", async () => { - const client = await clientPromise; - const executor = new WorkflowExecutor(client); - executionId = await executor.startWorkflow({ name, version }); - expect(executionId).toBeTruthy(); - }); - - test("Should be able to execute workflow synchronously", async () => { - const client = await clientPromise; - const executor = new WorkflowExecutor(client); - const workflowRun = await executor.executeWorkflow( - { - name: name, - version: version, - }, - name, - version, - uuidv4() - ); - expect(workflowRun.status).toEqual("COMPLETED"); - }); - - test("Should be able to get workflow execution status ", async () => { - const client = await clientPromise; - const executor = new WorkflowExecutor(client); - const workflowStatus = await executor.getWorkflowStatus( - executionId!, - true, - true - ); - expect(workflowStatus.status).toBeTruthy(); - }); - - test("Should return workflow status detail", async () => { - const client = await clientPromise; - const executor = new WorkflowExecutor(client); - const workflowStatus = await executor.getWorkflow(executionId!, true); - - expect(workflowStatus.status).toBeTruthy(); - expect(workflowStatus.tasks?.length).toBe(1); - }); - test("Should execute a workflow with indempotency key", async () => { - const client = await clientPromise; - const executor = new WorkflowExecutor(client); - const idempotencyKey = uuidv4(); - const executionId = await executor.startWorkflow({ - name: name, - version: version, - idempotencyKey, - idempotencyStrategy: "RETURN_EXISTING", - }); - - const executionDetails = await executor.getWorkflow(executionId!, true); - expect(executionDetails.idempotencyKey).toEqual(idempotencyKey); - }); - - test("Should run workflow with http task with asyncComplete true", async () => { - const client = await clientPromise; - const executor = new WorkflowExecutor(client); - - await executor.registerWorkflow(true, { - name: "test_jssdk_workflow_with_http_task_with_asyncComplete_true", - version: 1, - ownerEmail: "developers@orkes.io", - tasks: [httpTask("test_jssdk_http_task_with_asyncComplete_true", { uri: "http://www.yahoo.com", method: "GET" }, true)], - inputParameters: [], - outputParameters: {}, - timeoutSeconds: 300, - }); - - const executionId = await executor.startWorkflow({ - name: "test_jssdk_workflow_with_http_task_with_asyncComplete_true", - input: {}, - version: 1, - }); - - const workflowStatusBefore = await TestUtil.waitForWorkflowStatus(executor, executionId, "RUNNING"); - - expect(["IN_PROGRESS", "SCHEDULED"]).toContain(workflowStatusBefore.tasks?.[0]?.status); - - const taskClient = new TaskClient(client); - taskClient.updateTaskResult(executionId, "test_jssdk_http_task_with_asyncComplete_true", "COMPLETED", { hello: "From manuall api call updating task result" }); - - const workflowStatusAfter = await TestUtil.waitForWorkflowStatus(executor, executionId, "COMPLETED"); - - expect(workflowStatusAfter.tasks?.[0]?.status).toEqual("COMPLETED"); - }); - - test("Should run workflow with an optional http task", async () => { - const executor = new WorkflowExecutor(await clientPromise); - - await executor.registerWorkflow(true, { - name: "test_jssdk_workflow_with_optional_http_task", - version: 1, - ownerEmail: "developers@orkes.io", - tasks: [httpTask("test_jssdk_optional_http_task", { uri: "uncorrect_uri", method: "GET" }, false, true)], - inputParameters: [], - outputParameters: {}, - timeoutSeconds: 300, - }); - - const executionId = await executor.startWorkflow({ - name: "test_jssdk_workflow_with_optional_http_task", - input: {}, - version: 1, - }); - - const workflowStatus = await TestUtil.waitForWorkflowStatus(executor, executionId, "COMPLETED"); - expect(["FAILED", "COMPLETED_WITH_ERRORS"]).toContain(workflowStatus.tasks?.[0]?.status); - }); -}); +import {MetadataClient} from "../../src/core/metadataClient"; +import {TestUtil} from "../utils/test-util"; +import {TaskResultStatusEnum} from "../../src/common/open-api/models/TaskResultStatusEnum"; +import {SignalResponse} from "../../src/common/open-api/models/SignalResponse"; describe("Execute with Return Strategy and Consistency", () => { // Constants specific to this test suite diff --git a/integration-tests/utils/metadata/compiled.bin b/integration-tests/v5-only/metadata/compiled.bin similarity index 100% rename from integration-tests/utils/metadata/compiled.bin rename to integration-tests/v5-only/metadata/compiled.bin diff --git a/jest.config.mjs b/jest.config.mjs index 82063ee0..1c06294f 100644 --- a/jest.config.mjs +++ b/jest.config.mjs @@ -4,9 +4,5 @@ export default { preset: "ts-jest", clearMocks: true, coverageProvider: "v8", - testMatch: [ - "**/integration-tests/**/*.test.[jt]s?(x)", - "**/src/**/__tests__/**/*.test.[jt]s?(x)", - ], transformIgnorePatterns: ["/node_modules/", "\\.pnp\\.[^\\/]+$"], }; From fc292271d2b767b6a817b4ca7be33726c813c1af Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Mon, 22 Sep 2025 01:46:44 +0300 Subject: [PATCH 011/124] simplify github action, update npm commands --- .github/workflows/pull_request.yml | 26 ++++++++++++-------------- package.json | 3 ++- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 35a92f4b..9f9e831a 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -24,10 +24,8 @@ jobs: matrix: test: - name: "unit" - - name: "integration" - cluster: "v5" - - name: "integration" - cluster: "v4" + - name: "integration:v5" + - name: "integration:v4" steps: - name: Checkout uses: actions/checkout@v4 @@ -37,17 +35,17 @@ jobs: node-version: "22" - name: Install Dependencies run: npm ci - - name: Run ${{ matrix.test.name }}${{ matrix.test.cluster }} Tests and Add Annotations - run: npm run test:${{ matrix.test.name }} -- --ci --reporters=default --reporters=github-actions --reporters=jest-junit + - name: Run ${{matrix.test.name}} Tests and Add Annotations + run: npm run test:${{matrix.test.name}} -- --ci --reporters=default --reporters=github-actions --reporters=jest-junit env: - CONDUCTOR_SERVER_URL: ${{ matrix.test.cluster == 'v4' && vars.SERVER_URL_V4 || vars.SERVER_URL }} - CONDUCTOR_AUTH_KEY: ${{ matrix.test.cluster == 'v4' && secrets.AUTH_KEY_V4 || secrets.AUTH_KEY }} - CONDUCTOR_AUTH_SECRET: ${{ matrix.test.cluster == 'v4' && secrets.AUTH_SECRET_V4 || secrets.AUTH_SECRET }} - JEST_JUNIT_OUTPUT_NAME: ${{ matrix.test.name }}${{ matrix.test.cluster }}-test-results.xml - - name: Publish ${{ matrix.test.name }} Test Results + CONDUCTOR_SERVER_URL: ${{matrix.test.name == 'integration:v4' && vars.SERVER_URL_V4 || vars.SERVER_URL}} + CONDUCTOR_AUTH_KEY: ${{matrix.test.name == 'integration:v4' && secrets.AUTH_KEY_V4 || secrets.AUTH_KEY}} + CONDUCTOR_AUTH_SECRET: ${{matrix.test.name == 'integration:v4' && secrets.AUTH_SECRET_V4 || secrets.AUTH_SECRET}} + JEST_JUNIT_OUTPUT_NAME: ${{matrix.test.name}}-test-results.xml + - name: Publish ${{matrix.test.name}} Test Results uses: dorny/test-reporter@v2 - if: ${{ !cancelled() }} + if: ${{!cancelled()}} with: - name: ${{ matrix.test.name }} Test Report - path: reports/${{ matrix.test.name }}${{ matrix.test.cluster }}-test-results.xml + name: ${{matrix.test.name}} Test Report + path: reports/${{matrix.test.name}}-test-results.xml reporter: jest-junit diff --git a/package.json b/package.json index 330d5030..027cf57e 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,8 @@ "lint-fix": "npx eslint . --fix", "test": "jest --force-exit --detectOpenHandles", "test:unit": "jest --testMatch='**/src/**/__tests__/**/*.test.[jt]s?(x)' --force-exit", - "test:integration": "jest --testMatch='**/integration-tests/**/*.test.[jt]s?(x)' --force-exit --detectOpenHandles", + "test:integration:v5": "jest --testMatch='**/integration-tests/{common,v5-only}/**/*.test.[jt]s?(x)' --force-exit --detectOpenHandles", + "test:integration:v4": "jest --testMatch='**/integration-tests/common/**/*.test.[jt]s?(x)' --force-exit --detectOpenHandles", "ci": "npm run lint && npm run test", "build": "tsup index.ts", "generateClient:models": "npx openapi-typescript-codegen --input http://localhost:8080/api-docs --output src/common/open-api --client node --indent 2 --name ConductorClient --useUnionTypes --exportCore false", From 251acc30c6c54cc386ca95b7bf7d86da7892ae59 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Mon, 22 Sep 2025 01:52:52 +0300 Subject: [PATCH 012/124] fix linter errors --- integration-tests/v5-only/executor.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/v5-only/executor.test.ts b/integration-tests/v5-only/executor.test.ts index ad1b8fcf..5cb72b5d 100644 --- a/integration-tests/v5-only/executor.test.ts +++ b/integration-tests/v5-only/executor.test.ts @@ -1,5 +1,5 @@ import {expect, describe, test, jest, beforeAll, afterEach, afterAll} from "@jest/globals"; -import {Consistency, ReturnStrategy, SetVariableTaskDef, TaskType, WorkflowDef} from "../../src/common"; +import {Consistency, ReturnStrategy} from "../../src/common"; import { orkesConductorClient } from "../../src/orkes"; import { WorkflowExecutor } from "../../src/core/executor"; import { v4 as uuidv4 } from "uuid"; From 8534375b050d7ba471b895e56337bdcdda6e489e Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Mon, 22 Sep 2025 02:00:10 +0300 Subject: [PATCH 013/124] adjust TaskManager tests timings --- integration-tests/common/TaskManager.test.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/integration-tests/common/TaskManager.test.ts b/integration-tests/common/TaskManager.test.ts index 1d05543c..4b2ba116 100644 --- a/integration-tests/common/TaskManager.test.ts +++ b/integration-tests/common/TaskManager.test.ts @@ -6,11 +6,11 @@ import { mockLogger } from "../utils/mockLogger"; import { TestUtil } from "../utils/test-util"; -const BASE_TIME = 500; +const BASE_TIME = 1000; describe("TaskManager", () => { const clientPromise = orkesConductorClient(); - jest.setTimeout(15000); + jest.setTimeout(30000); test("Should run workflow with worker", async () => { const client = await clientPromise; @@ -49,7 +49,7 @@ describe("TaskManager", () => { version: 1, }); - const workflowStatus = await TestUtil.waitForWorkflowCompletion(executor, executionId, BASE_TIME * 4); + const workflowStatus = await TestUtil.waitForWorkflowCompletion(executor, executionId, BASE_TIME * 30); expect(workflowStatus.status).toEqual("COMPLETED"); @@ -99,7 +99,7 @@ describe("TaskManager", () => { correlationId: "errorHandlerTestIdentifierUnique" }); - const workflowStatus = await TestUtil.waitForWorkflowCompletion(executor, status, BASE_TIME * 6); + const workflowStatus = await TestUtil.waitForWorkflowCompletion(executor, status, BASE_TIME * 30); expect(workflowStatus.status).toEqual("FAILED"); expect(mockErrorHandler).toHaveBeenCalledTimes(1); @@ -146,7 +146,7 @@ describe("TaskManager", () => { correlationId: "noErrorHandlerProvidedIdentifier" }); - const workflowStatus = await TestUtil.waitForWorkflowCompletion(executor, executionId!, BASE_TIME * 10); + const workflowStatus = await TestUtil.waitForWorkflowCompletion(executor, executionId!, BASE_TIME * 30); expect(workflowStatus.status).toEqual("FAILED"); await manager.stopPolling(); }); @@ -211,7 +211,7 @@ describe("TaskManager", () => { // decrease speed again manager.updatePollingOptions({ pollInterval: BASE_TIME, concurrency: 1 }); - const workflowStatus = await TestUtil.waitForWorkflowCompletion(executor, executionId, BASE_TIME * 4); + const workflowStatus = await TestUtil.waitForWorkflowCompletion(executor, executionId, BASE_TIME * 30); expect(workflowStatus.status).toEqual("COMPLETED"); await manager.stopPolling(); @@ -335,7 +335,7 @@ describe("TaskManager", () => { // decrease speed again manager.updatePollingOptions({ pollInterval: BASE_TIME, concurrency: 1 }); - const workflowStatus = await TestUtil.waitForWorkflowCompletion(executor, executionId, BASE_TIME * 10); + const workflowStatus = await TestUtil.waitForWorkflowCompletion(executor, executionId, BASE_TIME * 30); expect(workflowStatus.status).toEqual("COMPLETED"); await manager.stopPolling(); From 1b82930aca3aae36031ebf9004fa8dfbae63bd3c Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Mon, 22 Sep 2025 11:55:42 +0300 Subject: [PATCH 014/124] update gh action to run tests on node 18, 20, 22 --- .github/workflows/pull_request.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 9f9e831a..b42949f0 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -22,6 +22,7 @@ jobs: strategy: fail-fast: false matrix: + node-version: [18, 20, 22] test: - name: "unit" - name: "integration:v5" @@ -32,7 +33,7 @@ jobs: - name: Set up Node uses: actions/setup-node@v4 with: - node-version: "22" + node-version: ${{matrix.node-version}} - name: Install Dependencies run: npm ci - name: Run ${{matrix.test.name}} Tests and Add Annotations From 1c82c1f0819204c5ee160bb96b0868da14f086d3 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Mon, 22 Sep 2025 12:14:29 +0300 Subject: [PATCH 015/124] simplify gh action, add name --- .github/workflows/pull_request.yml | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index b42949f0..deeffa80 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -23,30 +23,28 @@ jobs: fail-fast: false matrix: node-version: [18, 20, 22] - test: - - name: "unit" - - name: "integration:v5" - - name: "integration:v4" + test: ["unit", "integration:v5", "integration:v4"] + name: Node.js v${{ matrix.node-version }} - ${{ matrix.test }} steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Node uses: actions/setup-node@v4 with: - node-version: ${{matrix.node-version}} + node-version: ${{ matrix.node-version }} - name: Install Dependencies run: npm ci - - name: Run ${{matrix.test.name}} Tests and Add Annotations - run: npm run test:${{matrix.test.name}} -- --ci --reporters=default --reporters=github-actions --reporters=jest-junit + - name: Run ${{ matrix.test }} Tests and Add Annotations + run: npm run test:${{ matrix.test }} -- --ci --reporters=default --reporters=github-actions --reporters=jest-junit env: - CONDUCTOR_SERVER_URL: ${{matrix.test.name == 'integration:v4' && vars.SERVER_URL_V4 || vars.SERVER_URL}} - CONDUCTOR_AUTH_KEY: ${{matrix.test.name == 'integration:v4' && secrets.AUTH_KEY_V4 || secrets.AUTH_KEY}} - CONDUCTOR_AUTH_SECRET: ${{matrix.test.name == 'integration:v4' && secrets.AUTH_SECRET_V4 || secrets.AUTH_SECRET}} - JEST_JUNIT_OUTPUT_NAME: ${{matrix.test.name}}-test-results.xml - - name: Publish ${{matrix.test.name}} Test Results + CONDUCTOR_SERVER_URL: ${{ matrix.test == 'integration:v4' && vars.SERVER_URL_V4 || vars.SERVER_URL }} + CONDUCTOR_AUTH_KEY: ${{ matrix.test == 'integration:v4' && secrets.AUTH_KEY_V4 || secrets.AUTH_KEY }} + CONDUCTOR_AUTH_SECRET: ${{ matrix.test == 'integration:v4' && secrets.AUTH_SECRET_V4 || secrets.AUTH_SECRET }} + JEST_JUNIT_OUTPUT_NAME: ${{ matrix.test }}-test-results.xml + - name: Publish ${{ matrix.test }} Test Results uses: dorny/test-reporter@v2 - if: ${{!cancelled()}} + if: ${{ !cancelled() }} with: - name: ${{matrix.test.name}} Test Report - path: reports/${{matrix.test.name}}-test-results.xml + name: ${{ matrix.test }} Test Report + path: reports/${{ matrix.test }}-test-results.xml reporter: jest-junit From 7cf90b96d07db5a3fdc8188f6fc78346c8ba4d05 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Mon, 22 Sep 2025 12:16:22 +0300 Subject: [PATCH 016/124] update gh action name --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index deeffa80..6401f6df 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -24,7 +24,7 @@ jobs: matrix: node-version: [18, 20, 22] test: ["unit", "integration:v5", "integration:v4"] - name: Node.js v${{ matrix.node-version }} - ${{ matrix.test }} + name: Node.js v${{ matrix.node-version }} - ${{ matrix.test }} tests steps: - name: Checkout uses: actions/checkout@v4 From 33ba63cdaa01a5537587e140a35ae775732ca3f5 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Mon, 22 Sep 2025 14:44:03 +0300 Subject: [PATCH 017/124] fix node.js v18 undici type errors --- package-lock.json | 922 +++++++++++++++++----------- src/orkes/helpers/resolveFetchFn.ts | 14 +- 2 files changed, 559 insertions(+), 377 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5262815a..b14a6260 100644 --- a/package-lock.json +++ b/package-lock.json @@ -562,9 +562,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", - "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", + "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", "cpu": [ "ppc64" ], @@ -579,9 +579,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", - "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", + "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", "cpu": [ "arm" ], @@ -596,9 +596,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", - "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", + "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", "cpu": [ "arm64" ], @@ -613,9 +613,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", - "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", + "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", "cpu": [ "x64" ], @@ -630,9 +630,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", - "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz", + "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", "cpu": [ "arm64" ], @@ -647,9 +647,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", - "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", + "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", "cpu": [ "x64" ], @@ -664,9 +664,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", - "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", + "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", "cpu": [ "arm64" ], @@ -681,9 +681,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", - "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", + "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", "cpu": [ "x64" ], @@ -698,9 +698,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", - "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", + "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", "cpu": [ "arm" ], @@ -715,9 +715,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", - "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", + "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", "cpu": [ "arm64" ], @@ -732,9 +732,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", - "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", + "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", "cpu": [ "ia32" ], @@ -749,9 +749,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", - "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", + "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", "cpu": [ "loong64" ], @@ -766,9 +766,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", - "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", + "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", "cpu": [ "mips64el" ], @@ -783,9 +783,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", - "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", + "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", "cpu": [ "ppc64" ], @@ -800,9 +800,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", - "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", + "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", "cpu": [ "riscv64" ], @@ -817,9 +817,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", - "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", + "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", "cpu": [ "s390x" ], @@ -834,9 +834,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", - "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz", + "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", "cpu": [ "x64" ], @@ -851,9 +851,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", - "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", + "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", "cpu": [ "arm64" ], @@ -868,9 +868,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", - "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", + "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", "cpu": [ "x64" ], @@ -885,9 +885,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", - "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", + "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", "cpu": [ "arm64" ], @@ -902,9 +902,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", - "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", + "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", "cpu": [ "x64" ], @@ -919,9 +919,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", - "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", + "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", "cpu": [ "arm64" ], @@ -936,9 +936,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", - "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", + "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", "cpu": [ "x64" ], @@ -953,9 +953,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", - "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", + "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", "cpu": [ "arm64" ], @@ -970,9 +970,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", - "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", + "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", "cpu": [ "ia32" ], @@ -987,9 +987,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", - "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", + "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", "cpu": [ "x64" ], @@ -1108,9 +1108,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.35.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.35.0.tgz", - "integrity": "sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==", + "version": "9.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz", + "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==", "dev": true, "license": "MIT", "engines": { @@ -1145,16 +1145,16 @@ } }, "node_modules/@gerrit0/mini-shiki": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.12.2.tgz", - "integrity": "sha512-HKZPmO8OSSAAo20H2B3xgJdxZaLTwtlMwxg0967scnrDlPwe6j5+ULGHyIqwgTbFCn9yv/ff8CmfWZLE9YKBzA==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.13.0.tgz", + "integrity": "sha512-mCrNvZNYNrwKer5PWLF6cOc0OEe2eKzgy976x+IT2tynwJYl+7UpHTSeXQJGijgTcoOf+f359L946unWlYRnsg==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/engine-oniguruma": "^3.12.2", - "@shikijs/langs": "^3.12.2", - "@shikijs/themes": "^3.12.2", - "@shikijs/types": "^3.12.2", + "@shikijs/engine-oniguruma": "^3.13.0", + "@shikijs/langs": "^3.13.0", + "@shikijs/themes": "^3.13.0", + "@shikijs/types": "^3.13.0", "@shikijs/vscode-textmate": "^10.0.2" } }, @@ -1228,91 +1228,6 @@ "node": ">=12" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1898,9 +1813,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.2.tgz", - "integrity": "sha512-uLN8NAiFVIRKX9ZQha8wy6UUs06UNSZ32xj6giK/rmMXAgKahwExvK6SsmgU5/brh4w/nSgj8e0k3c1HBQpa0A==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.0.tgz", + "integrity": "sha512-VxDYCDqOaR7NXzAtvRx7G1u54d2kEHopb28YH/pKzY6y0qmogP3gG7CSiWsq9WvDFxOQMpNEyjVAHZFXfH3o/A==", "cpu": [ "arm" ], @@ -1912,9 +1827,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.2.tgz", - "integrity": "sha512-oEouqQk2/zxxj22PNcGSskya+3kV0ZKH+nQxuCCOGJ4oTXBdNTbv+f/E3c74cNLeMO1S5wVWacSws10TTSB77g==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.0.tgz", + "integrity": "sha512-pqDirm8koABIKvzL59YI9W9DWbRlTX7RWhN+auR8HXJxo89m4mjqbah7nJZjeKNTNYopqL+yGg+0mhCpf3xZtQ==", "cpu": [ "arm64" ], @@ -1926,9 +1841,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.2.tgz", - "integrity": "sha512-OZuTVTpj3CDSIxmPgGH8en/XtirV5nfljHZ3wrNwvgkT5DQLhIKAeuFSiwtbMto6oVexV0k1F1zqURPKf5rI1Q==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.0.tgz", + "integrity": "sha512-YCdWlY/8ltN6H78HnMsRHYlPiKvqKagBP1r+D7SSylxX+HnsgXGCmLiV3Y4nSyY9hW8qr8U9LDUx/Lo7M6MfmQ==", "cpu": [ "arm64" ], @@ -1940,9 +1855,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.2.tgz", - "integrity": "sha512-Wa/Wn8RFkIkr1vy1k1PB//VYhLnlnn5eaJkfTQKivirOvzu5uVd2It01ukeQstMursuz7S1bU+8WW+1UPXpa8A==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.0.tgz", + "integrity": "sha512-z4nw6y1j+OOSGzuVbSWdIp1IUks9qNw4dc7z7lWuWDKojY38VMWBlEN7F9jk5UXOkUcp97vA1N213DF+Lz8BRg==", "cpu": [ "x64" ], @@ -1954,9 +1869,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.2.tgz", - "integrity": "sha512-QkzxvH3kYN9J1w7D1A+yIMdI1pPekD+pWx7G5rXgnIlQ1TVYVC6hLl7SOV9pi5q9uIDF9AuIGkuzcbF7+fAhow==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.0.tgz", + "integrity": "sha512-Q/dv9Yvyr5rKlK8WQJZVrp5g2SOYeZUs9u/t2f9cQ2E0gJjYB/BWoedXfUT0EcDJefi2zzVfhcOj8drWCzTviw==", "cpu": [ "arm64" ], @@ -1968,9 +1883,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.2.tgz", - "integrity": "sha512-dkYXB0c2XAS3a3jmyDkX4Jk0m7gWLFzq1C3qUnJJ38AyxIF5G/dyS4N9B30nvFseCfgtCEdbYFhk0ChoCGxPog==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.0.tgz", + "integrity": "sha512-kdBsLs4Uile/fbjZVvCRcKB4q64R+1mUq0Yd7oU1CMm1Av336ajIFqNFovByipciuUQjBCPMxwJhCgfG2re3rg==", "cpu": [ "x64" ], @@ -1982,9 +1897,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.2.tgz", - "integrity": "sha512-9VlPY/BN3AgbukfVHAB8zNFWB/lKEuvzRo1NKev0Po8sYFKx0i+AQlCYftgEjcL43F2h9Ui1ZSdVBc4En/sP2w==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.0.tgz", + "integrity": "sha512-aL6hRwu0k7MTUESgkg7QHY6CoqPgr6gdQXRJI1/VbFlUMwsSzPGSR7sG5d+MCbYnJmJwThc2ol3nixj1fvI/zQ==", "cpu": [ "arm" ], @@ -1996,9 +1911,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.2.tgz", - "integrity": "sha512-+GdKWOvsifaYNlIVf07QYan1J5F141+vGm5/Y8b9uCZnG/nxoGqgCmR24mv0koIWWuqvFYnbURRqw1lv7IBINw==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.0.tgz", + "integrity": "sha512-BTs0M5s1EJejgIBJhCeiFo7GZZ2IXWkFGcyZhxX4+8usnIo5Mti57108vjXFIQmmJaRyDwmV59Tw64Ap1dkwMw==", "cpu": [ "arm" ], @@ -2010,9 +1925,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.2.tgz", - "integrity": "sha512-df0Eou14ojtUdLQdPFnymEQteENwSJAdLf5KCDrmZNsy1c3YaCNaJvYsEUHnrg+/DLBH612/R0xd3dD03uz2dg==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.0.tgz", + "integrity": "sha512-uj672IVOU9m08DBGvoPKPi/J8jlVgjh12C9GmjjBxCTQc3XtVmRkRKyeHSmIKQpvJ7fIm1EJieBUcnGSzDVFyw==", "cpu": [ "arm64" ], @@ -2024,9 +1939,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.2.tgz", - "integrity": "sha512-iPeouV0UIDtz8j1YFR4OJ/zf7evjauqv7jQ/EFs0ClIyL+by++hiaDAfFipjOgyz6y6xbDvJuiU4HwpVMpRFDQ==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.0.tgz", + "integrity": "sha512-/+IVbeDMDCtB/HP/wiWsSzduD10SEGzIZX2945KSgZRNi4TSkjHqRJtNTVtVb8IRwhJ65ssI56krlLik+zFWkw==", "cpu": [ "arm64" ], @@ -2038,9 +1953,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.50.2.tgz", - "integrity": "sha512-OL6KaNvBopLlj5fTa5D5bau4W82f+1TyTZRr2BdnfsrnQnmdxh4okMxR2DcDkJuh4KeoQZVuvHvzuD/lyLn2Kw==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.0.tgz", + "integrity": "sha512-U1vVzvSWtSMWKKrGoROPBXMh3Vwn93TA9V35PldokHGqiUbF6erSzox/5qrSMKp6SzakvyjcPiVF8yB1xKr9Pg==", "cpu": [ "loong64" ], @@ -2052,9 +1967,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.2.tgz", - "integrity": "sha512-I21VJl1w6z/K5OTRl6aS9DDsqezEZ/yKpbqlvfHbW0CEF5IL8ATBMuUx6/mp683rKTK8thjs/0BaNrZLXetLag==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.0.tgz", + "integrity": "sha512-X/4WfuBAdQRH8cK3DYl8zC00XEE6aM472W+QCycpQJeLWVnHfkv7RyBFVaTqNUMsTgIX8ihMjCvFF9OUgeABzw==", "cpu": [ "ppc64" ], @@ -2066,9 +1981,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.2.tgz", - "integrity": "sha512-Hq6aQJT/qFFHrYMjS20nV+9SKrXL2lvFBENZoKfoTH2kKDOJqff5OSJr4x72ZaG/uUn+XmBnGhfr4lwMRrmqCQ==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.0.tgz", + "integrity": "sha512-xIRYc58HfWDBZoLmWfWXg2Sq8VCa2iJ32B7mqfWnkx5mekekl0tMe7FHpY8I72RXEcUkaWawRvl3qA55og+cwQ==", "cpu": [ "riscv64" ], @@ -2080,9 +1995,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.2.tgz", - "integrity": "sha512-82rBSEXRv5qtKyr0xZ/YMF531oj2AIpLZkeNYxmKNN6I2sVE9PGegN99tYDLK2fYHJITL1P2Lgb4ZXnv0PjQvw==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.0.tgz", + "integrity": "sha512-mbsoUey05WJIOz8U1WzNdf+6UMYGwE3fZZnQqsM22FZ3wh1N887HT6jAOjXs6CNEK3Ntu2OBsyQDXfIjouI4dw==", "cpu": [ "riscv64" ], @@ -2094,9 +2009,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.2.tgz", - "integrity": "sha512-4Q3S3Hy7pC6uaRo9gtXUTJ+EKo9AKs3BXKc2jYypEcMQ49gDPFU2P1ariX9SEtBzE5egIX6fSUmbmGazwBVF9w==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.0.tgz", + "integrity": "sha512-qP6aP970bucEi5KKKR4AuPFd8aTx9EF6BvutvYxmZuWLJHmnq4LvBfp0U+yFDMGwJ+AIJEH5sIP+SNypauMWzg==", "cpu": [ "s390x" ], @@ -2108,9 +2023,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.2.tgz", - "integrity": "sha512-9Jie/At6qk70dNIcopcL4p+1UirusEtznpNtcq/u/C5cC4HBX7qSGsYIcG6bdxj15EYWhHiu02YvmdPzylIZlA==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.0.tgz", + "integrity": "sha512-nmSVN+F2i1yKZ7rJNKO3G7ZzmxJgoQBQZ/6c4MuS553Grmr7WqR7LLDcYG53Z2m9409z3JLt4sCOhLdbKQ3HmA==", "cpu": [ "x64" ], @@ -2122,9 +2037,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.2.tgz", - "integrity": "sha512-HPNJwxPL3EmhzeAnsWQCM3DcoqOz3/IC6de9rWfGR8ZCuEHETi9km66bH/wG3YH0V3nyzyFEGUZeL5PKyy4xvw==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.0.tgz", + "integrity": "sha512-2d0qRo33G6TfQVjaMR71P+yJVGODrt5V6+T0BDYH4EMfGgdC/2HWDVjSSFw888GSzAZUwuska3+zxNUCDco6rQ==", "cpu": [ "x64" ], @@ -2136,9 +2051,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.2.tgz", - "integrity": "sha512-nMKvq6FRHSzYfKLHZ+cChowlEkR2lj/V0jYj9JnGUVPL2/mIeFGmVM2mLaFeNa5Jev7W7TovXqXIG2d39y1KYA==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.0.tgz", + "integrity": "sha512-A1JalX4MOaFAAyGgpO7XP5khquv/7xKzLIyLmhNrbiCxWpMlnsTYr8dnsWM7sEeotNmxvSOEL7F65j0HXFcFsw==", "cpu": [ "arm64" ], @@ -2150,9 +2065,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.2.tgz", - "integrity": "sha512-eFUvvnTYEKeTyHEijQKz81bLrUQOXKZqECeiWH6tb8eXXbZk+CXSG2aFrig2BQ/pjiVRj36zysjgILkqarS2YA==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.0.tgz", + "integrity": "sha512-YQugafP/rH0eOOHGjmNgDURrpYHrIX0yuojOI8bwCyXwxC9ZdTd3vYkmddPX0oHONLXu9Rb1dDmT0VNpjkzGGw==", "cpu": [ "arm64" ], @@ -2164,9 +2079,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.2.tgz", - "integrity": "sha512-cBaWmXqyfRhH8zmUxK3d3sAhEWLrtMjWBRwdMMHJIXSjvjLKvv49adxiEz+FJ8AP90apSDDBx2Tyd/WylV6ikA==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.0.tgz", + "integrity": "sha512-zYdUYhi3Qe2fndujBqL5FjAFzvNeLxtIqfzNEVKD1I7C37/chv1VxhscWSQHTNfjPCrBFQMnynwA3kpZpZ8w4A==", "cpu": [ "ia32" ], @@ -2177,10 +2092,24 @@ "win32" ] }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.0.tgz", + "integrity": "sha512-fGk03kQylNaCOQ96HDMeT7E2n91EqvCDd3RwvT5k+xNdFCeMGnj5b5hEgTGrQuyidqSsD3zJDQ21QIaxXqTBJw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.2.tgz", - "integrity": "sha512-APwKy6YUhvZaEoHyM+9xqmTpviEI+9eL7LoCH+aLcvWYHJ663qG5zx7WzWZY+a9qkg5JtzcMyJ9z0WtQBMDmgA==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.0.tgz", + "integrity": "sha512-6iKDCVSIUQ8jPMoIV0OytRKniaYyy5EbY/RRydmLW8ZR3cEBhxbWl5ro0rkUNe0ef6sScvhbY79HrjRm8i3vDQ==", "cpu": [ "x64" ], @@ -2192,40 +2121,40 @@ ] }, "node_modules/@shikijs/engine-oniguruma": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.12.2.tgz", - "integrity": "sha512-hozwnFHsLvujK4/CPVHNo3Bcg2EsnG8krI/ZQ2FlBlCRpPZW4XAEQmEwqegJsypsTAN9ehu2tEYe30lYKSZW/w==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.13.0.tgz", + "integrity": "sha512-O42rBGr4UDSlhT2ZFMxqM7QzIU+IcpoTMzb3W7AlziI1ZF7R8eS2M0yt5Ry35nnnTX/LTLXFPUjRFCIW+Operg==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.12.2", + "@shikijs/types": "3.13.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "node_modules/@shikijs/langs": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.12.2.tgz", - "integrity": "sha512-bVx5PfuZHDSHoBal+KzJZGheFuyH4qwwcwG/n+MsWno5cTlKmaNtTsGzJpHYQ8YPbB5BdEdKU1rga5/6JGY8ww==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.13.0.tgz", + "integrity": "sha512-672c3WAETDYHwrRP0yLy3W1QYB89Hbpj+pO4KhxK6FzIrDI2FoEXNiNCut6BQmEApYLfuYfpgOZaqbY+E9b8wQ==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.12.2" + "@shikijs/types": "3.13.0" } }, "node_modules/@shikijs/themes": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.12.2.tgz", - "integrity": "sha512-fTR3QAgnwYpfGczpIbzPjlRnxyONJOerguQv1iwpyQZ9QXX4qy/XFQqXlf17XTsorxnHoJGbH/LXBvwtqDsF5A==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.13.0.tgz", + "integrity": "sha512-Vxw1Nm1/Od8jyA7QuAenaV78BG2nSr3/gCGdBkLpfLscddCkzkL36Q5b67SrLLfvAJTOUzW39x4FHVCFriPVgg==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.12.2" + "@shikijs/types": "3.13.0" } }, "node_modules/@shikijs/types": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.12.2.tgz", - "integrity": "sha512-K5UIBzxCyv0YoxN3LMrKB9zuhp1bV+LgewxuVwHdl4Gz5oePoUFrr9EfgJlGlDeXCU1b/yhdnXeuRvAnz8HN8Q==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.13.0.tgz", + "integrity": "sha512-oM9P+NCFri/mmQ8LoFGVfVyemm5Hi27330zuOBp0annwJdKH1kOLndw3zCtAVDehPLg9fKqoEx3Ht/wNZxolfw==", "dev": true, "license": "MIT", "dependencies": { @@ -2382,9 +2311,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.18.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.5.tgz", - "integrity": "sha512-g9BpPfJvxYBXUWI9bV37j6d6LTMNQ88hPwdWWUeYZnMhlo66FIg9gCc1/DZb15QylJSKwOZjwrckvOTWpOiChg==", + "version": "22.18.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.6.tgz", + "integrity": "sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3033,13 +2962,16 @@ } }, "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ansi-styles": { @@ -3195,9 +3127,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.4.tgz", - "integrity": "sha512-L+YvJwGAgwJBV1p6ffpSTa2KRc69EeeYGYjRVWKs0GKrK+LON0GC0gV+rKSNtALEDvMDqkvCFq9r1r94/Gjwxw==", + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.6.tgz", + "integrity": "sha512-wrH5NNqren/QMtKUEEJf7z86YjfqW/2uw3IL3/xpqZUC95SSVIFXYQeeGjL6FT/X68IROu6RMehZQS5foy2BXw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3440,6 +3372,69 @@ "node": ">=12" } }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -3615,9 +3610,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.220", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.220.tgz", - "integrity": "sha512-TWXijEwR1ggr4BdAKrb1nMNqYLTx1/4aD1fkeZU+FVJGTKu53/T7UyHKXlqEX3Ub02csyHePbHmkvnrjcaYzMA==", + "version": "1.5.222", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.222.tgz", + "integrity": "sha512-gA7psSwSwQRE60CEoLz6JBCQPIxNeuzB2nL8vE03GK/OHxlvykbLyeiumQy1iH5C2f3YbRAZpGCMT12a/9ih9w==", "dev": true, "license": "ISC" }, @@ -3635,9 +3630,9 @@ } }, "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true, "license": "MIT" }, @@ -3665,9 +3660,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", - "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz", + "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -3678,32 +3673,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.9", - "@esbuild/android-arm": "0.25.9", - "@esbuild/android-arm64": "0.25.9", - "@esbuild/android-x64": "0.25.9", - "@esbuild/darwin-arm64": "0.25.9", - "@esbuild/darwin-x64": "0.25.9", - "@esbuild/freebsd-arm64": "0.25.9", - "@esbuild/freebsd-x64": "0.25.9", - "@esbuild/linux-arm": "0.25.9", - "@esbuild/linux-arm64": "0.25.9", - "@esbuild/linux-ia32": "0.25.9", - "@esbuild/linux-loong64": "0.25.9", - "@esbuild/linux-mips64el": "0.25.9", - "@esbuild/linux-ppc64": "0.25.9", - "@esbuild/linux-riscv64": "0.25.9", - "@esbuild/linux-s390x": "0.25.9", - "@esbuild/linux-x64": "0.25.9", - "@esbuild/netbsd-arm64": "0.25.9", - "@esbuild/netbsd-x64": "0.25.9", - "@esbuild/openbsd-arm64": "0.25.9", - "@esbuild/openbsd-x64": "0.25.9", - "@esbuild/openharmony-arm64": "0.25.9", - "@esbuild/sunos-x64": "0.25.9", - "@esbuild/win32-arm64": "0.25.9", - "@esbuild/win32-ia32": "0.25.9", - "@esbuild/win32-x64": "0.25.9" + "@esbuild/aix-ppc64": "0.25.10", + "@esbuild/android-arm": "0.25.10", + "@esbuild/android-arm64": "0.25.10", + "@esbuild/android-x64": "0.25.10", + "@esbuild/darwin-arm64": "0.25.10", + "@esbuild/darwin-x64": "0.25.10", + "@esbuild/freebsd-arm64": "0.25.10", + "@esbuild/freebsd-x64": "0.25.10", + "@esbuild/linux-arm": "0.25.10", + "@esbuild/linux-arm64": "0.25.10", + "@esbuild/linux-ia32": "0.25.10", + "@esbuild/linux-loong64": "0.25.10", + "@esbuild/linux-mips64el": "0.25.10", + "@esbuild/linux-ppc64": "0.25.10", + "@esbuild/linux-riscv64": "0.25.10", + "@esbuild/linux-s390x": "0.25.10", + "@esbuild/linux-x64": "0.25.10", + "@esbuild/netbsd-arm64": "0.25.10", + "@esbuild/netbsd-x64": "0.25.10", + "@esbuild/openbsd-arm64": "0.25.10", + "@esbuild/openbsd-x64": "0.25.10", + "@esbuild/openharmony-arm64": "0.25.10", + "@esbuild/sunos-x64": "0.25.10", + "@esbuild/win32-arm64": "0.25.10", + "@esbuild/win32-ia32": "0.25.10", + "@esbuild/win32-x64": "0.25.10" } }, "node_modules/escalade": { @@ -3730,9 +3725,9 @@ } }, "node_modules/eslint": { - "version": "9.35.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.35.0.tgz", - "integrity": "sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==", + "version": "9.36.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.36.0.tgz", + "integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3742,7 +3737,7 @@ "@eslint/config-helpers": "^0.3.1", "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.35.0", + "@eslint/js": "9.36.0", "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -3922,6 +3917,13 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/execa/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, "node_modules/exit-x": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", @@ -4114,19 +4116,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4849,6 +4838,29 @@ "node": ">=10.12.0" } }, + "node_modules/jest-junit/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-junit/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jest-junit/node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -6217,9 +6229,9 @@ } }, "node_modules/rollup": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.2.tgz", - "integrity": "sha512-BgLRGy7tNS9H66aIMASq1qSYbAAJV6Z6WR4QYTvj5FgF15rZ/ympT1uixHXwzbZUBDbkvqUI1KR0fH1FhMaQ9w==", + "version": "4.52.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.0.tgz", + "integrity": "sha512-+IuescNkTJQgX7AkIDtITipZdIGcWF0pnVvZTWStiazUmcGA2ag8dfg0urest2XlXUi9kuhfQ+qmdc5Stc3z7g==", "dev": true, "license": "MIT", "dependencies": { @@ -6233,27 +6245,28 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.50.2", - "@rollup/rollup-android-arm64": "4.50.2", - "@rollup/rollup-darwin-arm64": "4.50.2", - "@rollup/rollup-darwin-x64": "4.50.2", - "@rollup/rollup-freebsd-arm64": "4.50.2", - "@rollup/rollup-freebsd-x64": "4.50.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.50.2", - "@rollup/rollup-linux-arm-musleabihf": "4.50.2", - "@rollup/rollup-linux-arm64-gnu": "4.50.2", - "@rollup/rollup-linux-arm64-musl": "4.50.2", - "@rollup/rollup-linux-loong64-gnu": "4.50.2", - "@rollup/rollup-linux-ppc64-gnu": "4.50.2", - "@rollup/rollup-linux-riscv64-gnu": "4.50.2", - "@rollup/rollup-linux-riscv64-musl": "4.50.2", - "@rollup/rollup-linux-s390x-gnu": "4.50.2", - "@rollup/rollup-linux-x64-gnu": "4.50.2", - "@rollup/rollup-linux-x64-musl": "4.50.2", - "@rollup/rollup-openharmony-arm64": "4.50.2", - "@rollup/rollup-win32-arm64-msvc": "4.50.2", - "@rollup/rollup-win32-ia32-msvc": "4.50.2", - "@rollup/rollup-win32-x64-msvc": "4.50.2", + "@rollup/rollup-android-arm-eabi": "4.52.0", + "@rollup/rollup-android-arm64": "4.52.0", + "@rollup/rollup-darwin-arm64": "4.52.0", + "@rollup/rollup-darwin-x64": "4.52.0", + "@rollup/rollup-freebsd-arm64": "4.52.0", + "@rollup/rollup-freebsd-x64": "4.52.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.52.0", + "@rollup/rollup-linux-arm-musleabihf": "4.52.0", + "@rollup/rollup-linux-arm64-gnu": "4.52.0", + "@rollup/rollup-linux-arm64-musl": "4.52.0", + "@rollup/rollup-linux-loong64-gnu": "4.52.0", + "@rollup/rollup-linux-ppc64-gnu": "4.52.0", + "@rollup/rollup-linux-riscv64-gnu": "4.52.0", + "@rollup/rollup-linux-riscv64-musl": "4.52.0", + "@rollup/rollup-linux-s390x-gnu": "4.52.0", + "@rollup/rollup-linux-x64-gnu": "4.52.0", + "@rollup/rollup-linux-x64-musl": "4.52.0", + "@rollup/rollup-openharmony-arm64": "4.52.0", + "@rollup/rollup-win32-arm64-msvc": "4.52.0", + "@rollup/rollup-win32-ia32-msvc": "4.52.0", + "@rollup/rollup-win32-x64-gnu": "4.52.0", + "@rollup/rollup-win32-x64-msvc": "4.52.0", "fsevents": "~2.3.2" } }, @@ -6315,11 +6328,17 @@ } }, "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/slash": { "version": "3.0.0", @@ -6396,21 +6415,47 @@ "node": ">=10" } }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/string-length/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-length/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/string-width-cjs": { "name": "string-width", "version": "4.2.3", @@ -6427,7 +6472,24 @@ "node": ">=8" } }, - "node_modules/strip-ansi": { + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", @@ -6440,6 +6502,22 @@ "node": ">=8" } }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/strip-ansi-cjs": { "name": "strip-ansi", "version": "6.0.1", @@ -6454,6 +6532,16 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -6715,9 +6803,9 @@ "license": "Apache-2.0" }, "node_modules/ts-jest": { - "version": "29.4.2", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.2.tgz", - "integrity": "sha512-pBNOkn4HtuLpNrXTMVRC9b642CBaDnKqWXny4OzuoULT9S7Kf8MMlaRe2veKax12rjf5WcpMBhVPbQurlWGNxA==", + "version": "29.4.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.4.tgz", + "integrity": "sha512-ccVcRABct5ZELCT5U0+DZwkXMCcOCLi2doHRrKy1nK/s7J7bch6TzJMsrY09WxgUUIP/ITfmcDS8D2yl63rnXw==", "dev": true, "license": "MIT", "dependencies": { @@ -7215,18 +7303,18 @@ "license": "MIT" }, "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" @@ -7251,6 +7339,64 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -7272,19 +7418,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/write-file-atomic/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/xml": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", @@ -7351,6 +7484,51 @@ "node": ">=12" } }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index 5052aa55..b977b1ea 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -1,5 +1,7 @@ import { FetchFn } from "../types"; -import type { ResponseInit, RequestInfo } from "undici"; +// eslint-disable-next-line +// @ts-ignore since undici is an optional dependency and it's types could me missing on node18 +import type { RequestInfo, RequestInit } from "undici"; export const resolveFetchFn = async ( customFetch?: FetchFn @@ -8,11 +10,13 @@ export const resolveFetchFn = async ( if (process?.release?.name !== "node") return fetch; try { - const undici = await import("undici"); - const agent = new undici.Agent({ allowH2: true }); + // eslint-disable-next-line + // @ts-ignore since undici is an optional dependency and it's types could me missing on node18 + const { fetch: undiciFetch, Agent } = await import("undici"); + const undiciAgent = new Agent({ allowH2: true }); - return ((input: RequestInfo, init: ResponseInit) => - undici.fetch(input, { ...init, dispatcher: agent })) as FetchFn; + return ((input: RequestInfo, init?: RequestInit) => + undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; } catch { return fetch; } From 52ff0728bd2486cc8bf111441ba1066e74055f26 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Mon, 22 Sep 2025 15:29:41 +0300 Subject: [PATCH 018/124] update ts ignore comments --- src/orkes/helpers/resolveFetchFn.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index b977b1ea..5f5f5261 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -1,6 +1,6 @@ import { FetchFn } from "../types"; // eslint-disable-next-line -// @ts-ignore since undici is an optional dependency and it's types could me missing on node18 +// @ts-ignore since undici is an optional dependency and could me missing import type { RequestInfo, RequestInit } from "undici"; export const resolveFetchFn = async ( @@ -11,7 +11,7 @@ export const resolveFetchFn = async ( try { // eslint-disable-next-line - // @ts-ignore since undici is an optional dependency and it's types could me missing on node18 + // @ts-ignore since undici is an optional dependency and could me missing const { fetch: undiciFetch, Agent } = await import("undici"); const undiciAgent = new Agent({ allowH2: true }); From bc4e64f0a00a92514ec1cc3f2a1b91a381b33d56 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Mon, 22 Sep 2025 15:36:41 +0300 Subject: [PATCH 019/124] fix jest warnings --- src/common/index.ts | 29 ++++++++++++++++------------- tsconfig.json | 1 + 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/common/index.ts b/src/common/index.ts index cdaf9d0c..f6b42c46 100644 --- a/src/common/index.ts +++ b/src/common/index.ts @@ -4,14 +4,25 @@ export * from "./types"; export { ConductorClient, - ApiRequestOptions, - ApiResult, - OpenAPIConfig, - OnCancel, ApiError, BaseHttpRequest, CancelablePromise, CancelError, + EventResourceService, + HealthCheckResourceService, + MetadataResourceService, + SchedulerResourceService, + TaskResourceService, + TokenResourceService, + WorkflowBulkResourceService, + WorkflowResourceService, +} from "./open-api"; + +export type { + ApiRequestOptions, + ApiResult, + OpenAPIConfig, + OnCancel, Action, EventHandler, ExternalStorageLocation, @@ -42,14 +53,6 @@ export { WorkflowStatus, WorkflowSummary, WorkflowTask, - EventResourceService, - HealthCheckResourceService, - MetadataResourceService, - SchedulerResourceService, - TaskResourceService, - TokenResourceService, - WorkflowBulkResourceService, - WorkflowResourceService, HTScrollableSearchResultHumanTaskEntry, Terminate, TimeoutPolicy, @@ -61,5 +64,5 @@ export { HumanTaskTemplate, HumanTaskSearchResult, HumanTaskSearch, - HumanTaskEntry + HumanTaskEntry, } from "./open-api"; diff --git a/tsconfig.json b/tsconfig.json index 2bf5ba0a..ad39ceaf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,5 +6,6 @@ "dom" ], "noEmit": true, + "isolatedModules": true } } \ No newline at end of file From 1ddd9fa20d847c6a22bfd93c261d284244ee4d51 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Tue, 23 Sep 2025 02:04:45 +0300 Subject: [PATCH 020/124] add max-parallel: 3 --- .github/workflows/pull_request.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 6401f6df..d271108c 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -21,6 +21,7 @@ jobs: runs-on: ubuntu-latest strategy: fail-fast: false + max-parallel: 3 matrix: node-version: [18, 20, 22] test: ["unit", "integration:v5", "integration:v4"] From 7f9275d700762f5e0e62d67292c32bd620582568 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Tue, 23 Sep 2025 02:09:16 +0300 Subject: [PATCH 021/124] max-parallel: 1 --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index d271108c..1f4a65dc 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest strategy: fail-fast: false - max-parallel: 3 + max-parallel: 1 matrix: node-version: [18, 20, 22] test: ["unit", "integration:v5", "integration:v4"] From 3403c8ebae560c353ce95082cc1eacad5643276d Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Tue, 23 Sep 2025 12:29:17 +0300 Subject: [PATCH 022/124] test with updated h2 config --- src/orkes/helpers/resolveFetchFn.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index 5f5f5261..b3363d69 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -13,7 +13,12 @@ export const resolveFetchFn = async ( // eslint-disable-next-line // @ts-ignore since undici is an optional dependency and could me missing const { fetch: undiciFetch, Agent } = await import("undici"); - const undiciAgent = new Agent({ allowH2: true }); + const undiciAgent = new Agent({ + allowH2: true, + connections: 1, + //keepAliveTimeout: 4000, + //keepAliveMaxTimeout: 1000 * 60 * 10, + }); return ((input: RequestInfo, init?: RequestInit) => undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; From 9377975e04d79022f2b28735809b9f94af647227 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Tue, 23 Sep 2025 12:45:48 +0300 Subject: [PATCH 023/124] test with updated h2 config --- src/orkes/helpers/resolveFetchFn.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index b3363d69..1cd724b8 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -16,7 +16,7 @@ export const resolveFetchFn = async ( const undiciAgent = new Agent({ allowH2: true, connections: 1, - //keepAliveTimeout: 4000, + keepAliveTimeout: 500, //keepAliveMaxTimeout: 1000 * 60 * 10, }); From 7b44e9ebe4a47c42078877f03b2be4913ef39b1b Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Tue, 23 Sep 2025 18:16:23 +0300 Subject: [PATCH 024/124] add retry interceptor --- src/orkes/helpers/resolveFetchFn.ts | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index 1cd724b8..77e76100 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -12,13 +12,25 @@ export const resolveFetchFn = async ( try { // eslint-disable-next-line // @ts-ignore since undici is an optional dependency and could me missing - const { fetch: undiciFetch, Agent } = await import("undici"); + const { fetch: undiciFetch, Agent, interceptors } = await import("undici"); const undiciAgent = new Agent({ allowH2: true, - connections: 1, - keepAliveTimeout: 500, - //keepAliveMaxTimeout: 1000 * 60 * 10, - }); + // connections: 1, + // keepAliveTimeout: 500, + // clientTtl: 500, + // keepAliveMaxTimeout: 1000 * 60 * 10, + }).compose( + interceptors.retry({ + //maxRetries: 3, // Maximum number of retries (default: 5) + //minTimeout: 1000, // Minimum time to wait before retrying (default: 500ms) + //maxTimeout: 60000, // Maximum time to wait before retrying (default: 30000ms) + //timeoutFactor: 2, // Factor to multiply the timeout by for each retry (default: 2) + //retryAfter: true, // Automatically retry if Retry-After header is present (default: true) + methods: ["GET", "PUT", "HEAD", "POST", "DELETE", "PATCH", "OPTIONS"], // HTTP methods to retry (default includes GET, PUT, HEAD, OPTIONS, DELETE) + //statusCodes: [429, 500, 502], // HTTP status codes to retry (default includes 429, 500, 502, 503, 504) + errorCodes: ["ECONNRESET"], // Error codes to retry (default includes common network errors) + }) + ); return ((input: RequestInfo, init?: RequestInit) => undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; From c55fa7deac8f7e655467650381db51b1ec936bf8 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Wed, 24 Sep 2025 12:25:59 +0300 Subject: [PATCH 025/124] try to run tests on skdev cluster --- .github/workflows/pull_request.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 1f4a65dc..6df26267 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -38,9 +38,9 @@ jobs: - name: Run ${{ matrix.test }} Tests and Add Annotations run: npm run test:${{ matrix.test }} -- --ci --reporters=default --reporters=github-actions --reporters=jest-junit env: - CONDUCTOR_SERVER_URL: ${{ matrix.test == 'integration:v4' && vars.SERVER_URL_V4 || vars.SERVER_URL }} - CONDUCTOR_AUTH_KEY: ${{ matrix.test == 'integration:v4' && secrets.AUTH_KEY_V4 || secrets.AUTH_KEY }} - CONDUCTOR_AUTH_SECRET: ${{ matrix.test == 'integration:v4' && secrets.AUTH_SECRET_V4 || secrets.AUTH_SECRET }} + CONDUCTOR_SERVER_URL: ${{ matrix.test == 'integration:v4' && vars.SERVER_URL_V4 || vars.SERVER_URL_SKDEV }} + CONDUCTOR_AUTH_KEY: ${{ matrix.test == 'integration:v4' && secrets.AUTH_KEY_V4 || secrets.AUTH_KEY_SKDEV }} + CONDUCTOR_AUTH_SECRET: ${{ matrix.test == 'integration:v4' && secrets.AUTH_SECRET_V4 || secrets.AUTH_SECRET_SKDEV }} JEST_JUNIT_OUTPUT_NAME: ${{ matrix.test }}-test-results.xml - name: Publish ${{ matrix.test }} Test Results uses: dorny/test-reporter@v2 From 14e5b871e82d8b606e9c7e336575a0f0c4f69f29 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Wed, 24 Sep 2025 12:36:35 +0300 Subject: [PATCH 026/124] remove prev commit changes --- .github/workflows/pull_request.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 6df26267..1f4a65dc 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -38,9 +38,9 @@ jobs: - name: Run ${{ matrix.test }} Tests and Add Annotations run: npm run test:${{ matrix.test }} -- --ci --reporters=default --reporters=github-actions --reporters=jest-junit env: - CONDUCTOR_SERVER_URL: ${{ matrix.test == 'integration:v4' && vars.SERVER_URL_V4 || vars.SERVER_URL_SKDEV }} - CONDUCTOR_AUTH_KEY: ${{ matrix.test == 'integration:v4' && secrets.AUTH_KEY_V4 || secrets.AUTH_KEY_SKDEV }} - CONDUCTOR_AUTH_SECRET: ${{ matrix.test == 'integration:v4' && secrets.AUTH_SECRET_V4 || secrets.AUTH_SECRET_SKDEV }} + CONDUCTOR_SERVER_URL: ${{ matrix.test == 'integration:v4' && vars.SERVER_URL_V4 || vars.SERVER_URL }} + CONDUCTOR_AUTH_KEY: ${{ matrix.test == 'integration:v4' && secrets.AUTH_KEY_V4 || secrets.AUTH_KEY }} + CONDUCTOR_AUTH_SECRET: ${{ matrix.test == 'integration:v4' && secrets.AUTH_SECRET_V4 || secrets.AUTH_SECRET }} JEST_JUNIT_OUTPUT_NAME: ${{ matrix.test }}-test-results.xml - name: Publish ${{ matrix.test }} Test Results uses: dorny/test-reporter@v2 From 0e26df3e98592bc51dd9aa63a7ffbf1c89572031 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Wed, 24 Sep 2025 14:13:35 +0300 Subject: [PATCH 027/124] update undici retry interceptor config --- src/orkes/helpers/resolveFetchFn.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index 77e76100..8a223f2b 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -21,14 +21,14 @@ export const resolveFetchFn = async ( // keepAliveMaxTimeout: 1000 * 60 * 10, }).compose( interceptors.retry({ - //maxRetries: 3, // Maximum number of retries (default: 5) - //minTimeout: 1000, // Minimum time to wait before retrying (default: 500ms) - //maxTimeout: 60000, // Maximum time to wait before retrying (default: 30000ms) - //timeoutFactor: 2, // Factor to multiply the timeout by for each retry (default: 2) + maxRetries: 10, // Maximum number of retries (default: 5) + minTimeout: 2000, // Minimum time to wait before retrying (default: 500ms) + maxTimeout: 60000, // Maximum time to wait before retrying (default: 30000ms) + timeoutFactor: 2, // Factor to multiply the timeout by for each retry (default: 2) //retryAfter: true, // Automatically retry if Retry-After header is present (default: true) methods: ["GET", "PUT", "HEAD", "POST", "DELETE", "PATCH", "OPTIONS"], // HTTP methods to retry (default includes GET, PUT, HEAD, OPTIONS, DELETE) //statusCodes: [429, 500, 502], // HTTP status codes to retry (default includes 429, 500, 502, 503, 504) - errorCodes: ["ECONNRESET"], // Error codes to retry (default includes common network errors) + errorCodes: ["ECONNRESET", "read ECONNRESET"], // Error codes to retry (default includes common network errors) }) ); From 80160a2b4bdedb14d8e187106ffd66e2ae914ff0 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Wed, 24 Sep 2025 18:20:34 +0300 Subject: [PATCH 028/124] try with clientTtl: 500 --- src/orkes/helpers/resolveFetchFn.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index 8a223f2b..53cbd3e2 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -17,7 +17,7 @@ export const resolveFetchFn = async ( allowH2: true, // connections: 1, // keepAliveTimeout: 500, - // clientTtl: 500, + clientTtl: 500, // keepAliveMaxTimeout: 1000 * 60 * 10, }).compose( interceptors.retry({ From 967cedca58a791285b1e610a21e6179d3d63794a Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Wed, 24 Sep 2025 18:57:01 +0300 Subject: [PATCH 029/124] try to remove AbortController --- src/orkes/helpers/resolveFetchFn.ts | 8 ++++---- src/orkes/request/request.ts | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index 53cbd3e2..f153ec39 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -15,10 +15,10 @@ export const resolveFetchFn = async ( const { fetch: undiciFetch, Agent, interceptors } = await import("undici"); const undiciAgent = new Agent({ allowH2: true, - // connections: 1, - // keepAliveTimeout: 500, - clientTtl: 500, - // keepAliveMaxTimeout: 1000 * 60 * 10, + //connections: 1, + //keepAliveTimeout: 500, + //clientTtl: 500, + //keepAliveMaxTimeout: 1000 * 60 * 10, }).compose( interceptors.retry({ maxRetries: 10, // Maximum number of retries (default: 5) diff --git a/src/orkes/request/request.ts b/src/orkes/request/request.ts index 3288df82..c5603b17 100644 --- a/src/orkes/request/request.ts +++ b/src/orkes/request/request.ts @@ -216,16 +216,16 @@ const sendRequest = async ( onCancel: OnCancel, fetchFn: FetchFn = fetch ): Promise => { - const controller = new AbortController(); + //const controller = new AbortController(); const request: RequestInit = { headers, method: options.method, body: body ?? formData, - signal: controller.signal as AbortSignal, + //signal: controller.signal as AbortSignal, }; - onCancel(() => controller.abort()); + onCancel(() => console.log("Aborting request")); //controller.abort()); return await fetchFn(url, request); }; From 34bc5f5a9ca5b406996326a1282fb61aff4151e2 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Wed, 24 Sep 2025 19:09:35 +0300 Subject: [PATCH 030/124] try with modified undici agent tls config --- src/orkes/helpers/resolveFetchFn.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index f153ec39..b26f44e2 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -19,6 +19,11 @@ export const resolveFetchFn = async ( //keepAliveTimeout: 500, //clientTtl: 500, //keepAliveMaxTimeout: 1000 * 60 * 10, + //pipelining: 1, + connect: { + rejectUnauthorized: true, // Ensure TLS validation + secureProtocol: "TLSv1_2_method", // Use TLS 1.2 + }, }).compose( interceptors.retry({ maxRetries: 10, // Maximum number of retries (default: 5) From d250fcb8891bd980924c92e65ced5a15ed57ec74 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Wed, 24 Sep 2025 19:16:18 +0300 Subject: [PATCH 031/124] try without !onCancel.isCancelled condition --- src/orkes/request/request.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/orkes/request/request.ts b/src/orkes/request/request.ts index c5603b17..81bb7210 100644 --- a/src/orkes/request/request.ts +++ b/src/orkes/request/request.ts @@ -306,7 +306,7 @@ export const request = ( const body = getRequestBody(options); const headers = await getHeaders(config, options); - if (!onCancel.isCancelled) { + //if (!onCancel.isCancelled) { const response = await sendRequest( options, url, @@ -333,7 +333,7 @@ export const request = ( catchErrorCodes(options, result); resolve(result.body); - } + //} } catch (error) { reject(error); } From ca9bc0c7117e7dbd8d48b480c13ec2495d7fbbd4 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Wed, 24 Sep 2025 19:21:47 +0300 Subject: [PATCH 032/124] try without CancelablePromise --- src/orkes/request/request.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/orkes/request/request.ts b/src/orkes/request/request.ts index 81bb7210..54837bb3 100644 --- a/src/orkes/request/request.ts +++ b/src/orkes/request/request.ts @@ -213,7 +213,7 @@ const sendRequest = async ( body: any, formData: FormData | undefined, headers: Headers, - onCancel: OnCancel, + //onCancel: OnCancel, fetchFn: FetchFn = fetch ): Promise => { //const controller = new AbortController(); @@ -225,7 +225,7 @@ const sendRequest = async ( //signal: controller.signal as AbortSignal, }; - onCancel(() => console.log("Aborting request")); //controller.abort()); + //onCancel(() => console.log("Aborting request")); //controller.abort()); return await fetchFn(url, request); }; @@ -298,8 +298,8 @@ export const request = ( config: OpenAPIConfig, options: ApiRequestOptions, fetchFn: FetchFn = fetch -): CancelablePromise => { - return new CancelablePromise(async (resolve, reject, onCancel) => { +): Promise => { //CancelablePromise => { + return new Promise(async (resolve, reject) => {//return new CancelablePromise(async (resolve, reject, onCancel) => { try { const url = getUrl(config, options); const formData = getFormData(options); @@ -313,7 +313,7 @@ export const request = ( body, formData, headers, - onCancel, + //onCancel, fetchFn ); const responseBody = await getResponseBody(response); From eaafcda41e60bf3d19f43fb28032572691002c90 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Wed, 24 Sep 2025 21:11:58 +0300 Subject: [PATCH 033/124] revert request changes --- src/orkes/request/request.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/orkes/request/request.ts b/src/orkes/request/request.ts index 54837bb3..3288df82 100644 --- a/src/orkes/request/request.ts +++ b/src/orkes/request/request.ts @@ -213,19 +213,19 @@ const sendRequest = async ( body: any, formData: FormData | undefined, headers: Headers, - //onCancel: OnCancel, + onCancel: OnCancel, fetchFn: FetchFn = fetch ): Promise => { - //const controller = new AbortController(); + const controller = new AbortController(); const request: RequestInit = { headers, method: options.method, body: body ?? formData, - //signal: controller.signal as AbortSignal, + signal: controller.signal as AbortSignal, }; - //onCancel(() => console.log("Aborting request")); //controller.abort()); + onCancel(() => controller.abort()); return await fetchFn(url, request); }; @@ -298,22 +298,22 @@ export const request = ( config: OpenAPIConfig, options: ApiRequestOptions, fetchFn: FetchFn = fetch -): Promise => { //CancelablePromise => { - return new Promise(async (resolve, reject) => {//return new CancelablePromise(async (resolve, reject, onCancel) => { +): CancelablePromise => { + return new CancelablePromise(async (resolve, reject, onCancel) => { try { const url = getUrl(config, options); const formData = getFormData(options); const body = getRequestBody(options); const headers = await getHeaders(config, options); - //if (!onCancel.isCancelled) { + if (!onCancel.isCancelled) { const response = await sendRequest( options, url, body, formData, headers, - //onCancel, + onCancel, fetchFn ); const responseBody = await getResponseBody(response); @@ -333,7 +333,7 @@ export const request = ( catchErrorCodes(options, result); resolve(result.body); - //} + } } catch (error) { reject(error); } From 538ff0839031785475519fbd1763f19f8afa5432 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Wed, 24 Sep 2025 22:11:19 +0300 Subject: [PATCH 034/124] remove undici interceptor, add fetchWithRetry --- src/orkes/helpers/resolveFetchFn.ts | 26 ++------------------------ src/orkes/request/request.ts | 25 ++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index b26f44e2..5f5f5261 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -12,30 +12,8 @@ export const resolveFetchFn = async ( try { // eslint-disable-next-line // @ts-ignore since undici is an optional dependency and could me missing - const { fetch: undiciFetch, Agent, interceptors } = await import("undici"); - const undiciAgent = new Agent({ - allowH2: true, - //connections: 1, - //keepAliveTimeout: 500, - //clientTtl: 500, - //keepAliveMaxTimeout: 1000 * 60 * 10, - //pipelining: 1, - connect: { - rejectUnauthorized: true, // Ensure TLS validation - secureProtocol: "TLSv1_2_method", // Use TLS 1.2 - }, - }).compose( - interceptors.retry({ - maxRetries: 10, // Maximum number of retries (default: 5) - minTimeout: 2000, // Minimum time to wait before retrying (default: 500ms) - maxTimeout: 60000, // Maximum time to wait before retrying (default: 30000ms) - timeoutFactor: 2, // Factor to multiply the timeout by for each retry (default: 2) - //retryAfter: true, // Automatically retry if Retry-After header is present (default: true) - methods: ["GET", "PUT", "HEAD", "POST", "DELETE", "PATCH", "OPTIONS"], // HTTP methods to retry (default includes GET, PUT, HEAD, OPTIONS, DELETE) - //statusCodes: [429, 500, 502], // HTTP status codes to retry (default includes 429, 500, 502, 503, 504) - errorCodes: ["ECONNRESET", "read ECONNRESET"], // Error codes to retry (default includes common network errors) - }) - ); + const { fetch: undiciFetch, Agent } = await import("undici"); + const undiciAgent = new Agent({ allowH2: true }); return ((input: RequestInfo, init?: RequestInit) => undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; diff --git a/src/orkes/request/request.ts b/src/orkes/request/request.ts index 3288df82..00703535 100644 --- a/src/orkes/request/request.ts +++ b/src/orkes/request/request.ts @@ -207,6 +207,29 @@ const getRequestBody = (options: ApiRequestOptions): any => { return undefined; }; +const fetchWithRetry = async ( + url: string, + request: RequestInit, + fetchFn: FetchFn, + retries: number = 5, + delay: number = 1000 +): Promise => { + try { + const response = await fetchFn(url, request); + if (response.status == 429) { + throw new Error(`Request failed with status ${response.status}`); + } + return response; + } catch (error: unknown) { + if (retries > 0) { + console.warn(`Fetch error encountered. Retrying request in ${delay}ms...`); + await new Promise(resolve => setTimeout(resolve, delay)); + return await fetchWithRetry(url, request, fetchFn, retries - 1, delay * 2); + } + throw error; + } +}; + const sendRequest = async ( options: ApiRequestOptions, url: string, @@ -227,7 +250,7 @@ const sendRequest = async ( onCancel(() => controller.abort()); - return await fetchFn(url, request); + return await fetchWithRetry(url, request, fetchFn); }; const getResponseHeader = ( From d2844a7010f095e5d7393f588c2772371fb7ce2a Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Wed, 24 Sep 2025 22:27:13 +0300 Subject: [PATCH 035/124] add description for network error --- src/orkes/request/request.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/orkes/request/request.ts b/src/orkes/request/request.ts index 00703535..cbe1acaf 100644 --- a/src/orkes/request/request.ts +++ b/src/orkes/request/request.ts @@ -222,9 +222,12 @@ const fetchWithRetry = async ( return response; } catch (error: unknown) { if (retries > 0) { - console.warn(`Fetch error encountered. Retrying request in ${delay}ms...`); - await new Promise(resolve => setTimeout(resolve, delay)); - return await fetchWithRetry(url, request, fetchFn, retries - 1, delay * 2); + console.log( + `[${request.method} ${url}] Fetch error encountered. Retrying request in ${delay}ms...`, + error + ); + await new Promise((resolve) => setTimeout(resolve, delay)); + return fetchWithRetry(url, request, fetchFn, retries - 1, delay * 2); } throw error; } From bea31b9b7e39b09a170a70a97f4ed815b90f2c83 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Wed, 24 Sep 2025 22:40:59 +0300 Subject: [PATCH 036/124] update error message --- src/orkes/request/request.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/orkes/request/request.ts b/src/orkes/request/request.ts index cbe1acaf..d37ce53a 100644 --- a/src/orkes/request/request.ts +++ b/src/orkes/request/request.ts @@ -223,8 +223,9 @@ const fetchWithRetry = async ( } catch (error: unknown) { if (retries > 0) { console.log( - `[${request.method} ${url}] Fetch error encountered. Retrying request in ${delay}ms...`, - error + `[${request.method} ${url}] fetch error caught. + ${error} + Retrying request in ${delay}ms...` ); await new Promise((resolve) => setTimeout(resolve, delay)); return fetchWithRetry(url, request, fetchFn, retries - 1, delay * 2); From f0b8bbfb1af061aa147d155cc06f94c40d3f0f82 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Wed, 24 Sep 2025 22:48:24 +0300 Subject: [PATCH 037/124] update error message --- src/orkes/request/request.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/orkes/request/request.ts b/src/orkes/request/request.ts index d37ce53a..fc1fa9fb 100644 --- a/src/orkes/request/request.ts +++ b/src/orkes/request/request.ts @@ -222,10 +222,8 @@ const fetchWithRetry = async ( return response; } catch (error: unknown) { if (retries > 0) { - console.log( - `[${request.method} ${url}] fetch error caught. - ${error} - Retrying request in ${delay}ms...` + console.warn( + `${request.method} ${url} fetch error occurred. ERROR:\n${error}\nRetrying request in ${delay}ms...` ); await new Promise((resolve) => setTimeout(resolve, delay)); return fetchWithRetry(url, request, fetchFn, retries - 1, delay * 2); From ced9a99747900e373fe9115fc835ee124435e59a Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Wed, 24 Sep 2025 22:50:03 +0300 Subject: [PATCH 038/124] try without max-parallel --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 1f4a65dc..7c86b5d9 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest strategy: fail-fast: false - max-parallel: 1 + # max-parallel: 1 matrix: node-version: [18, 20, 22] test: ["unit", "integration:v5", "integration:v4"] From fb9ade367b45f31089bddf5f24003b5a7397eb8d Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Wed, 24 Sep 2025 22:51:31 +0300 Subject: [PATCH 039/124] restore max-parallel: 1 --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 7c86b5d9..1f4a65dc 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest strategy: fail-fast: false - # max-parallel: 1 + max-parallel: 1 matrix: node-version: [18, 20, 22] test: ["unit", "integration:v5", "integration:v4"] From 11145b61fbd6570041f60738a4e5be567e6fd25f Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 14:56:03 +0300 Subject: [PATCH 040/124] try with keepAliveTimeout: 1 --- src/orkes/helpers/resolveFetchFn.ts | 2 +- src/orkes/request/request.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index 5f5f5261..4af7075f 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -13,7 +13,7 @@ export const resolveFetchFn = async ( // eslint-disable-next-line // @ts-ignore since undici is an optional dependency and could me missing const { fetch: undiciFetch, Agent } = await import("undici"); - const undiciAgent = new Agent({ allowH2: true }); + const undiciAgent = new Agent({ allowH2: true, keepAliveTimeout: 1 }); return ((input: RequestInfo, init?: RequestInit) => undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; diff --git a/src/orkes/request/request.ts b/src/orkes/request/request.ts index fc1fa9fb..df1b7602 100644 --- a/src/orkes/request/request.ts +++ b/src/orkes/request/request.ts @@ -211,7 +211,7 @@ const fetchWithRetry = async ( url: string, request: RequestInit, fetchFn: FetchFn, - retries: number = 5, + retries: number = 0, delay: number = 1000 ): Promise => { try { From bb222719d70e95c4ddfdd24f3ccb640a9bd41e19 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 15:17:47 +0300 Subject: [PATCH 041/124] try with new agent on each request --- src/orkes/helpers/resolveFetchFn.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index 4af7075f..68a1822b 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -13,10 +13,10 @@ export const resolveFetchFn = async ( // eslint-disable-next-line // @ts-ignore since undici is an optional dependency and could me missing const { fetch: undiciFetch, Agent } = await import("undici"); - const undiciAgent = new Agent({ allowH2: true, keepAliveTimeout: 1 }); + //const undiciAgent = new Agent({ allowH2: true, keepAliveTimeout: 1}); return ((input: RequestInfo, init?: RequestInit) => - undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; + undiciFetch(input, { ...init, dispatcher: new Agent({ allowH2: true }) })) as FetchFn; } catch { return fetch; } From d05a7576a50171fd9307a1f4e6ca5bdceef48f86 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 16:26:09 +0300 Subject: [PATCH 042/124] try with connect: { timeout: 60000 } --- integration-tests/common/LoadTest.test.ts | 108 ++++++++++++++++++++++ src/orkes/helpers/resolveFetchFn.ts | 2 +- 2 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 integration-tests/common/LoadTest.test.ts diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts new file mode 100644 index 00000000..7bc0be54 --- /dev/null +++ b/integration-tests/common/LoadTest.test.ts @@ -0,0 +1,108 @@ +import { describe, test, expect, jest } from "@jest/globals"; +import { orkesConductorClient } from "../../src/orkes"; +import { WorkflowExecutor } from "../../src/core"; +import { TaskType } from "../../src/common"; + +// --- Configuration for the Load Test --- +// The number of requests to send in parallel. +// Adjust this number to find the breaking point of your load balancer. +const CONCURRENT_REQUESTS = 5000; +const TEST_TIMEOUT = 60000; // 60 seconds + +describe("Load Test for ECONNRESET", () => { + jest.setTimeout(TEST_TIMEOUT); + + test(`should handle ${CONCURRENT_REQUESTS} concurrent GET requests without ECONNRESET`, async () => { + const client = await orkesConductorClient(); + const executor = new WorkflowExecutor(client); + + // To ensure we are making valid API calls, we first create a simple + // workflow and start one execution. We will then query this execution's status. + const workflowName = "load_test_workflow"; + await executor.registerWorkflow(true, { + name: workflowName, + version: 1, + tasks: [ + { + name: "simple_task", + taskReferenceName: "simple_task_ref", + type: TaskType.SIMPLE, + }, + ], + timeoutSeconds: 0, + inputParameters: [], + }); + const executionId = await executor.startWorkflow({ + name: workflowName, + version: 1, + }); + + console.log( + `Starting load test with workflow execution ID: ${executionId}` + ); + console.log(`Sending ${CONCURRENT_REQUESTS} concurrent requests...`); + + // Create an array of promises. Each promise represents a GET request. + const requestPromises = []; + for (let i = 0; i < CONCURRENT_REQUESTS; i++) { + requestPromises.push(executor.getWorkflow(executionId, false)); + } + + // Use Promise.allSettled to wait for all requests to complete, + // regardless of whether they succeed or fail. + const results = await Promise.allSettled(requestPromises); + + // Analyze the results to find ECONNRESET errors + let successCount = 0; + const econnresetErrors: any[] = []; + const http429Errors: any[] = []; + const otherErrors: any[] = []; + + results.forEach((result, index) => { + if (result.status === "fulfilled") { + successCount++; + } else { + const reason = result.reason; + // Check if the rejection reason is the specific ECONNRESET error + if (reason?.code === "ECONNRESET") { + econnresetErrors.push({ requestIndex: index, reason }); + } else if (reason?.body?.status === 429) { + http429Errors.push({ requestIndex: index, reason }); + } else { + otherErrors.push({ requestIndex: index, reason }); + } + } + }); + + console.log("--- Load Test Results ---"); + console.log( + `Successful Requests: ${successCount} / ${CONCURRENT_REQUESTS}` + ); + console.log(`ECONNRESET Failures: ${econnresetErrors.length}`); + console.log(`HTTP 429 Failures: ${http429Errors.length}`); + console.log(`Other Failures: ${otherErrors.length}`); + console.log("-------------------------"); + + if (econnresetErrors.length > 0) { + console.error("ECONNRESET errors detected:", econnresetErrors); + } + if (http429Errors.length > 0) { + console.error("HTTP 429 (Too Many Requests) errors detected:", http429Errors); + } + if (otherErrors.length > 0) { + console.error(`\n--- Other Errors (${otherErrors.length}) ---`); + for (const error of otherErrors) { + console.error( + `Request Index ${error.requestIndex} failed. Reason:`, + error.reason + ); + } + console.error("--------------------------\n"); + } + + // The test assertion: Fail if we encounter any ECONNRESET errors. + expect(econnresetErrors.length).toBe(0); + expect(http429Errors.length).toBe(0); + expect(otherErrors.length).toBe(0); + }); +}); diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index 68a1822b..e98bc59f 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -16,7 +16,7 @@ export const resolveFetchFn = async ( //const undiciAgent = new Agent({ allowH2: true, keepAliveTimeout: 1}); return ((input: RequestInfo, init?: RequestInit) => - undiciFetch(input, { ...init, dispatcher: new Agent({ allowH2: true }) })) as FetchFn; + undiciFetch(input, { ...init, dispatcher: new Agent({ allowH2: true, connect: { timeout: 60000 } }) })) as FetchFn; } catch { return fetch; } From 2020864914852affbd1eccf93cf3150990516fae Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 16:29:33 +0300 Subject: [PATCH 043/124] tweak LoadTest --- integration-tests/common/LoadTest.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 7bc0be54..3b84d54a 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -6,8 +6,8 @@ import { TaskType } from "../../src/common"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. // Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 5000; -const TEST_TIMEOUT = 60000; // 60 seconds +const CONCURRENT_REQUESTS = 2000; +const TEST_TIMEOUT = 60000 * 10; // 60 seconds describe("Load Test for ECONNRESET", () => { jest.setTimeout(TEST_TIMEOUT); From d8b893ad3bc4b6859f3272116b1af52cbc796d3e Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 16:40:21 +0300 Subject: [PATCH 044/124] retry with CONCURRENT_REQUESTS = 300 --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 3b84d54a..9b1eb153 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -6,7 +6,7 @@ import { TaskType } from "../../src/common"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. // Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 2000; +const CONCURRENT_REQUESTS = 300; const TEST_TIMEOUT = 60000 * 10; // 60 seconds describe("Load Test for ECONNRESET", () => { From bab839cd6b3bd3552ddf06c0d6d6f1bdbe122eec Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 16:52:46 +0300 Subject: [PATCH 045/124] try sending 1 req each 100ms --- integration-tests/common/LoadTest.test.ts | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 9b1eb153..8b3d2e05 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -6,13 +6,13 @@ import { TaskType } from "../../src/common"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. // Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 300; +const CONCURRENT_REQUESTS = 50; const TEST_TIMEOUT = 60000 * 10; // 60 seconds describe("Load Test for ECONNRESET", () => { jest.setTimeout(TEST_TIMEOUT); - test(`should handle ${CONCURRENT_REQUESTS} concurrent GET requests without ECONNRESET`, async () => { + test(`should handle ${CONCURRENT_REQUESTS} staggered GET requests (1 every 100ms) without ECONNRESET`, async () => { const client = await orkesConductorClient(); const executor = new WorkflowExecutor(client); @@ -40,19 +40,26 @@ describe("Load Test for ECONNRESET", () => { console.log( `Starting load test with workflow execution ID: ${executionId}` ); - console.log(`Sending ${CONCURRENT_REQUESTS} concurrent requests...`); + console.log( + `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 100ms)...` + ); - // Create an array of promises. Each promise represents a GET request. - const requestPromises = []; + // Create an array to hold all the request promises. + const requestPromises: Promise[] = []; for (let i = 0; i < CONCURRENT_REQUESTS; i++) { + // Start the request but don't wait for it to finish here. requestPromises.push(executor.getWorkflow(executionId, false)); + + if (i < CONCURRENT_REQUESTS - 1) { + // Wait 100ms before starting the next request. + await new Promise((resolve) => setTimeout(resolve, 100)); + } } - // Use Promise.allSettled to wait for all requests to complete, - // regardless of whether they succeed or fail. + // Now, wait for all the in-flight requests to complete. const results = await Promise.allSettled(requestPromises); - // Analyze the results to find ECONNRESET errors + // Analyze the results to find specific errors let successCount = 0; const econnresetErrors: any[] = []; const http429Errors: any[] = []; From ddc768b21c6c6e6e574c91ad0b8f064623b54a52 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 16:55:45 +0300 Subject: [PATCH 046/124] try with 200 requests --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 8b3d2e05..d9f74047 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -6,7 +6,7 @@ import { TaskType } from "../../src/common"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. // Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 50; +const CONCURRENT_REQUESTS = 200; const TEST_TIMEOUT = 60000 * 10; // 60 seconds describe("Load Test for ECONNRESET", () => { From fd980eea8d3142bcf6112df277014e1de957f4d3 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 16:59:23 +0300 Subject: [PATCH 047/124] try with 50ms --- integration-tests/common/LoadTest.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index d9f74047..1d07481b 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -41,7 +41,7 @@ describe("Load Test for ECONNRESET", () => { `Starting load test with workflow execution ID: ${executionId}` ); console.log( - `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 100ms)...` + `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 50ms)...` ); // Create an array to hold all the request promises. @@ -52,7 +52,7 @@ describe("Load Test for ECONNRESET", () => { if (i < CONCURRENT_REQUESTS - 1) { // Wait 100ms before starting the next request. - await new Promise((resolve) => setTimeout(resolve, 100)); + await new Promise((resolve) => setTimeout(resolve, 50)); } } From 589ca95efaf040e776857479c83d6d6e9d4a82fe Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 17:01:53 +0300 Subject: [PATCH 048/124] try with 1ms --- integration-tests/common/LoadTest.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 1d07481b..240a63c0 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -41,7 +41,7 @@ describe("Load Test for ECONNRESET", () => { `Starting load test with workflow execution ID: ${executionId}` ); console.log( - `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 50ms)...` + `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 1ms)...` ); // Create an array to hold all the request promises. @@ -52,7 +52,7 @@ describe("Load Test for ECONNRESET", () => { if (i < CONCURRENT_REQUESTS - 1) { // Wait 100ms before starting the next request. - await new Promise((resolve) => setTimeout(resolve, 50)); + await new Promise((resolve) => setTimeout(resolve, 1)); } } From 32a3787a0f0c2a7cc71139b648c167d4fa6eda14 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 17:03:47 +0300 Subject: [PATCH 049/124] retry with 10ms --- integration-tests/common/LoadTest.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 240a63c0..5e0f1179 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -41,7 +41,7 @@ describe("Load Test for ECONNRESET", () => { `Starting load test with workflow execution ID: ${executionId}` ); console.log( - `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 1ms)...` + `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 10ms)...` ); // Create an array to hold all the request promises. @@ -52,7 +52,7 @@ describe("Load Test for ECONNRESET", () => { if (i < CONCURRENT_REQUESTS - 1) { // Wait 100ms before starting the next request. - await new Promise((resolve) => setTimeout(resolve, 1)); + await new Promise((resolve) => setTimeout(resolve, 10)); } } From c4aa5a2950af9debbdf05597dacf3067d0def86d Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 17:05:53 +0300 Subject: [PATCH 050/124] retry with 0ms --- integration-tests/common/LoadTest.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 5e0f1179..297b01b6 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -6,7 +6,7 @@ import { TaskType } from "../../src/common"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. // Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 200; +const CONCURRENT_REQUESTS = 500; const TEST_TIMEOUT = 60000 * 10; // 60 seconds describe("Load Test for ECONNRESET", () => { @@ -41,7 +41,7 @@ describe("Load Test for ECONNRESET", () => { `Starting load test with workflow execution ID: ${executionId}` ); console.log( - `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 10ms)...` + `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 0ms)...` ); // Create an array to hold all the request promises. @@ -52,7 +52,7 @@ describe("Load Test for ECONNRESET", () => { if (i < CONCURRENT_REQUESTS - 1) { // Wait 100ms before starting the next request. - await new Promise((resolve) => setTimeout(resolve, 10)); + await new Promise((resolve) => setTimeout(resolve, 0)); } } From ad4289502386f2735d29bd7aa994e6f44d127bd3 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 17:08:56 +0300 Subject: [PATCH 051/124] retry with 1ms --- integration-tests/common/LoadTest.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 297b01b6..c7e8c6b9 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -12,7 +12,7 @@ const TEST_TIMEOUT = 60000 * 10; // 60 seconds describe("Load Test for ECONNRESET", () => { jest.setTimeout(TEST_TIMEOUT); - test(`should handle ${CONCURRENT_REQUESTS} staggered GET requests (1 every 100ms) without ECONNRESET`, async () => { + test(`should handle ${CONCURRENT_REQUESTS} staggered GET requests (1 every 1ms) without ECONNRESET`, async () => { const client = await orkesConductorClient(); const executor = new WorkflowExecutor(client); @@ -41,7 +41,7 @@ describe("Load Test for ECONNRESET", () => { `Starting load test with workflow execution ID: ${executionId}` ); console.log( - `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 0ms)...` + `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 1ms)...` ); // Create an array to hold all the request promises. @@ -52,7 +52,7 @@ describe("Load Test for ECONNRESET", () => { if (i < CONCURRENT_REQUESTS - 1) { // Wait 100ms before starting the next request. - await new Promise((resolve) => setTimeout(resolve, 0)); + await new Promise((resolve) => setTimeout(resolve, 1)); } } From 91eed9e43228897428246541258b2ee3d056a3c1 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 17:11:32 +0300 Subject: [PATCH 052/124] retry with 5ms --- integration-tests/common/LoadTest.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index c7e8c6b9..37bb6dc5 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -12,7 +12,7 @@ const TEST_TIMEOUT = 60000 * 10; // 60 seconds describe("Load Test for ECONNRESET", () => { jest.setTimeout(TEST_TIMEOUT); - test(`should handle ${CONCURRENT_REQUESTS} staggered GET requests (1 every 1ms) without ECONNRESET`, async () => { + test(`should handle ${CONCURRENT_REQUESTS} staggered GET requests (1 every 5ms) without ECONNRESET`, async () => { const client = await orkesConductorClient(); const executor = new WorkflowExecutor(client); @@ -41,7 +41,7 @@ describe("Load Test for ECONNRESET", () => { `Starting load test with workflow execution ID: ${executionId}` ); console.log( - `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 1ms)...` + `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 5ms)...` ); // Create an array to hold all the request promises. @@ -52,7 +52,7 @@ describe("Load Test for ECONNRESET", () => { if (i < CONCURRENT_REQUESTS - 1) { // Wait 100ms before starting the next request. - await new Promise((resolve) => setTimeout(resolve, 1)); + await new Promise((resolve) => setTimeout(resolve, 5)); } } From ef2a83e40f5a5398514537ebdfda72179a30f95e Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 17:14:46 +0300 Subject: [PATCH 053/124] retry with 10ms --- integration-tests/common/LoadTest.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 37bb6dc5..e1eb9f6c 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -12,7 +12,7 @@ const TEST_TIMEOUT = 60000 * 10; // 60 seconds describe("Load Test for ECONNRESET", () => { jest.setTimeout(TEST_TIMEOUT); - test(`should handle ${CONCURRENT_REQUESTS} staggered GET requests (1 every 5ms) without ECONNRESET`, async () => { + test(`should handle ${CONCURRENT_REQUESTS} staggered GET requests (1 every 10ms) without ECONNRESET`, async () => { const client = await orkesConductorClient(); const executor = new WorkflowExecutor(client); @@ -41,7 +41,7 @@ describe("Load Test for ECONNRESET", () => { `Starting load test with workflow execution ID: ${executionId}` ); console.log( - `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 5ms)...` + `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 10ms)...` ); // Create an array to hold all the request promises. @@ -52,7 +52,7 @@ describe("Load Test for ECONNRESET", () => { if (i < CONCURRENT_REQUESTS - 1) { // Wait 100ms before starting the next request. - await new Promise((resolve) => setTimeout(resolve, 5)); + await new Promise((resolve) => setTimeout(resolve, 10)); } } From 7f13858b082882b1bf14a747c8b3dd5098379e01 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 17:17:23 +0300 Subject: [PATCH 054/124] restore undici agent --- src/orkes/helpers/resolveFetchFn.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index e98bc59f..4af7075f 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -13,10 +13,10 @@ export const resolveFetchFn = async ( // eslint-disable-next-line // @ts-ignore since undici is an optional dependency and could me missing const { fetch: undiciFetch, Agent } = await import("undici"); - //const undiciAgent = new Agent({ allowH2: true, keepAliveTimeout: 1}); + const undiciAgent = new Agent({ allowH2: true, keepAliveTimeout: 1 }); return ((input: RequestInfo, init?: RequestInit) => - undiciFetch(input, { ...init, dispatcher: new Agent({ allowH2: true, connect: { timeout: 60000 } }) })) as FetchFn; + undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; } catch { return fetch; } From d48a4d3f0b9328f8365e8265b8d5be15f0dee66a Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 18:12:38 +0300 Subject: [PATCH 055/124] remove undici keepAliveTimeout --- src/orkes/helpers/resolveFetchFn.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index 4af7075f..5f5f5261 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -13,7 +13,7 @@ export const resolveFetchFn = async ( // eslint-disable-next-line // @ts-ignore since undici is an optional dependency and could me missing const { fetch: undiciFetch, Agent } = await import("undici"); - const undiciAgent = new Agent({ allowH2: true, keepAliveTimeout: 1 }); + const undiciAgent = new Agent({ allowH2: true }); return ((input: RequestInfo, init?: RequestInit) => undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; From 31df6704a12a495d9c47beb3677b619bb4f8be2e Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 18:21:26 +0300 Subject: [PATCH 056/124] update fetchWithRetry to trigger only on 429 error --- src/orkes/request/request.ts | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/orkes/request/request.ts b/src/orkes/request/request.ts index df1b7602..998fdddd 100644 --- a/src/orkes/request/request.ts +++ b/src/orkes/request/request.ts @@ -211,25 +211,15 @@ const fetchWithRetry = async ( url: string, request: RequestInit, fetchFn: FetchFn, - retries: number = 0, + retries: number = 5, delay: number = 1000 ): Promise => { - try { - const response = await fetchFn(url, request); - if (response.status == 429) { - throw new Error(`Request failed with status ${response.status}`); - } - return response; - } catch (error: unknown) { - if (retries > 0) { - console.warn( - `${request.method} ${url} fetch error occurred. ERROR:\n${error}\nRetrying request in ${delay}ms...` - ); - await new Promise((resolve) => setTimeout(resolve, delay)); - return fetchWithRetry(url, request, fetchFn, retries - 1, delay * 2); - } - throw error; + const response = await fetchFn(url, request); + if (response.status == 429 && retries > 0) { + await new Promise((resolve) => setTimeout(resolve, delay)); + return fetchWithRetry(url, request, fetchFn, retries - 1, delay * 2); } + return response; }; const sendRequest = async ( From 21d8c53d516d76ca2877408c391dfcef3fe24ba9 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 19:41:52 +0300 Subject: [PATCH 057/124] retry without AbortController, with new agent on each req --- integration-tests/common/LoadTest.test.ts | 6 +++--- src/orkes/helpers/resolveFetchFn.ts | 4 ++-- src/orkes/request/request.ts | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index e1eb9f6c..782309c1 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -12,7 +12,7 @@ const TEST_TIMEOUT = 60000 * 10; // 60 seconds describe("Load Test for ECONNRESET", () => { jest.setTimeout(TEST_TIMEOUT); - test(`should handle ${CONCURRENT_REQUESTS} staggered GET requests (1 every 10ms) without ECONNRESET`, async () => { + test(`should handle ${CONCURRENT_REQUESTS} staggered GET requests (1 every 0ms) without ECONNRESET`, async () => { const client = await orkesConductorClient(); const executor = new WorkflowExecutor(client); @@ -41,7 +41,7 @@ describe("Load Test for ECONNRESET", () => { `Starting load test with workflow execution ID: ${executionId}` ); console.log( - `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 10ms)...` + `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 0ms)...` ); // Create an array to hold all the request promises. @@ -52,7 +52,7 @@ describe("Load Test for ECONNRESET", () => { if (i < CONCURRENT_REQUESTS - 1) { // Wait 100ms before starting the next request. - await new Promise((resolve) => setTimeout(resolve, 10)); + await new Promise((resolve) => setTimeout(resolve, 0)); } } diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index 5f5f5261..b817ac09 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -13,10 +13,10 @@ export const resolveFetchFn = async ( // eslint-disable-next-line // @ts-ignore since undici is an optional dependency and could me missing const { fetch: undiciFetch, Agent } = await import("undici"); - const undiciAgent = new Agent({ allowH2: true }); + //const undiciAgent = new Agent({ allowH2: true }); return ((input: RequestInfo, init?: RequestInit) => - undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; + undiciFetch(input, { ...init, dispatcher: new Agent({ allowH2: true }) })) as FetchFn; } catch { return fetch; } diff --git a/src/orkes/request/request.ts b/src/orkes/request/request.ts index 998fdddd..663b2217 100644 --- a/src/orkes/request/request.ts +++ b/src/orkes/request/request.ts @@ -228,19 +228,19 @@ const sendRequest = async ( body: any, formData: FormData | undefined, headers: Headers, - onCancel: OnCancel, + //onCancel: OnCancel, fetchFn: FetchFn = fetch ): Promise => { - const controller = new AbortController(); + //const controller = new AbortController(); const request: RequestInit = { headers, method: options.method, body: body ?? formData, - signal: controller.signal as AbortSignal, + //signal: controller.signal as AbortSignal, }; - onCancel(() => controller.abort()); + //onCancel(() => controller.abort()); return await fetchWithRetry(url, request, fetchFn); }; @@ -328,7 +328,7 @@ export const request = ( body, formData, headers, - onCancel, + //onCancel, fetchFn ); const responseBody = await getResponseBody(response); From a4dcf0e703d00048648640f93fc76d21a5eda556 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 19:45:40 +0300 Subject: [PATCH 058/124] restore changes from prev commit --- src/orkes/helpers/resolveFetchFn.ts | 4 ++-- src/orkes/request/request.ts | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index b817ac09..5f5f5261 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -13,10 +13,10 @@ export const resolveFetchFn = async ( // eslint-disable-next-line // @ts-ignore since undici is an optional dependency and could me missing const { fetch: undiciFetch, Agent } = await import("undici"); - //const undiciAgent = new Agent({ allowH2: true }); + const undiciAgent = new Agent({ allowH2: true }); return ((input: RequestInfo, init?: RequestInit) => - undiciFetch(input, { ...init, dispatcher: new Agent({ allowH2: true }) })) as FetchFn; + undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; } catch { return fetch; } diff --git a/src/orkes/request/request.ts b/src/orkes/request/request.ts index 663b2217..998fdddd 100644 --- a/src/orkes/request/request.ts +++ b/src/orkes/request/request.ts @@ -228,19 +228,19 @@ const sendRequest = async ( body: any, formData: FormData | undefined, headers: Headers, - //onCancel: OnCancel, + onCancel: OnCancel, fetchFn: FetchFn = fetch ): Promise => { - //const controller = new AbortController(); + const controller = new AbortController(); const request: RequestInit = { headers, method: options.method, body: body ?? formData, - //signal: controller.signal as AbortSignal, + signal: controller.signal as AbortSignal, }; - //onCancel(() => controller.abort()); + onCancel(() => controller.abort()); return await fetchWithRetry(url, request, fetchFn); }; @@ -328,7 +328,7 @@ export const request = ( body, formData, headers, - //onCancel, + onCancel, fetchFn ); const responseBody = await getResponseBody(response); From 5ba1531a676f4647097d1a4e33f0939c504cc352 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 20:35:17 +0300 Subject: [PATCH 059/124] retry on node 20, 22, 24 with built-in fetch --- .github/workflows/pull_request.yml | 2 +- src/orkes/helpers/resolveFetchFn.ts | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 1f4a65dc..bb7103ab 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -23,7 +23,7 @@ jobs: fail-fast: false max-parallel: 1 matrix: - node-version: [18, 20, 22] + node-version: [18, 20, 22, 24] test: ["unit", "integration:v5", "integration:v4"] name: Node.js v${{ matrix.node-version }} - ${{ matrix.test }} tests steps: diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index 5f5f5261..c46769a6 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -8,16 +8,17 @@ export const resolveFetchFn = async ( ): Promise => { if (customFetch) return customFetch; if (process?.release?.name !== "node") return fetch; + return fetch; - try { - // eslint-disable-next-line - // @ts-ignore since undici is an optional dependency and could me missing - const { fetch: undiciFetch, Agent } = await import("undici"); - const undiciAgent = new Agent({ allowH2: true }); + // try { + // // eslint-disable-next-line + // // @ts-ignore since undici is an optional dependency and could me missing + // const { fetch: undiciFetch, Agent } = await import("undici"); + // const undiciAgent = new Agent({ allowH2: true }); - return ((input: RequestInfo, init?: RequestInit) => - undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; - } catch { - return fetch; - } + // return ((input: RequestInfo, init?: RequestInit) => + // undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; + // } catch { + // return fetch; + // } }; From 4712f825c6237554dabf9103d577d97d92090d00 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 20:43:17 +0300 Subject: [PATCH 060/124] restore undici fetch --- src/orkes/helpers/resolveFetchFn.ts | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index c46769a6..5f5f5261 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -8,17 +8,16 @@ export const resolveFetchFn = async ( ): Promise => { if (customFetch) return customFetch; if (process?.release?.name !== "node") return fetch; - return fetch; - // try { - // // eslint-disable-next-line - // // @ts-ignore since undici is an optional dependency and could me missing - // const { fetch: undiciFetch, Agent } = await import("undici"); - // const undiciAgent = new Agent({ allowH2: true }); + try { + // eslint-disable-next-line + // @ts-ignore since undici is an optional dependency and could me missing + const { fetch: undiciFetch, Agent } = await import("undici"); + const undiciAgent = new Agent({ allowH2: true }); - // return ((input: RequestInfo, init?: RequestInit) => - // undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; - // } catch { - // return fetch; - // } + return ((input: RequestInfo, init?: RequestInit) => + undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; + } catch { + return fetch; + } }; From 53b905a50ad9a1f57050181a31e9d1285ae86a3f Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 20:47:18 +0300 Subject: [PATCH 061/124] retry fetching https://google.com --- integration-tests/common/LoadTest.test.ts | 53 ++++++++++++----------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 782309c1..d2825a48 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -13,33 +13,33 @@ describe("Load Test for ECONNRESET", () => { jest.setTimeout(TEST_TIMEOUT); test(`should handle ${CONCURRENT_REQUESTS} staggered GET requests (1 every 0ms) without ECONNRESET`, async () => { - const client = await orkesConductorClient(); - const executor = new WorkflowExecutor(client); + // const client = await orkesConductorClient(); + // const executor = new WorkflowExecutor(client); - // To ensure we are making valid API calls, we first create a simple - // workflow and start one execution. We will then query this execution's status. - const workflowName = "load_test_workflow"; - await executor.registerWorkflow(true, { - name: workflowName, - version: 1, - tasks: [ - { - name: "simple_task", - taskReferenceName: "simple_task_ref", - type: TaskType.SIMPLE, - }, - ], - timeoutSeconds: 0, - inputParameters: [], - }); - const executionId = await executor.startWorkflow({ - name: workflowName, - version: 1, - }); + // // To ensure we are making valid API calls, we first create a simple + // // workflow and start one execution. We will then query this execution's status. + // const workflowName = "load_test_workflow"; + // await executor.registerWorkflow(true, { + // name: workflowName, + // version: 1, + // tasks: [ + // { + // name: "simple_task", + // taskReferenceName: "simple_task_ref", + // type: TaskType.SIMPLE, + // }, + // ], + // timeoutSeconds: 0, + // inputParameters: [], + // }); + // const executionId = await executor.startWorkflow({ + // name: workflowName, + // version: 1, + // }); - console.log( - `Starting load test with workflow execution ID: ${executionId}` - ); + // console.log( + // `Starting load test with workflow execution ID: ${executionId}` + // ); console.log( `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 0ms)...` ); @@ -48,7 +48,8 @@ describe("Load Test for ECONNRESET", () => { const requestPromises: Promise[] = []; for (let i = 0; i < CONCURRENT_REQUESTS; i++) { // Start the request but don't wait for it to finish here. - requestPromises.push(executor.getWorkflow(executionId, false)); + //requestPromises.push(executor.getWorkflow(executionId, false)); + requestPromises.push(fetch(`https://google.com`)); if (i < CONCURRENT_REQUESTS - 1) { // Wait 100ms before starting the next request. From f72dc7d6a1e58bdf3bea2567da9ce8bbf88ae53e Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 20:50:55 +0300 Subject: [PATCH 062/124] retry fetching cluster --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index d2825a48..e1d40525 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -49,7 +49,7 @@ describe("Load Test for ECONNRESET", () => { for (let i = 0; i < CONCURRENT_REQUESTS; i++) { // Start the request but don't wait for it to finish here. //requestPromises.push(executor.getWorkflow(executionId, false)); - requestPromises.push(fetch(`https://google.com`)); + requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); if (i < CONCURRENT_REQUESTS - 1) { // Wait 100ms before starting the next request. From a97815e904949faa02f411fca6f90ae0447d7573 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 20:55:28 +0300 Subject: [PATCH 063/124] retry with more tests --- integration-tests/common/LoadTest.test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index e1d40525..8fb7e989 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -6,8 +6,8 @@ import { TaskType } from "../../src/common"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. // Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 500; -const TEST_TIMEOUT = 60000 * 10; // 60 seconds +const CONCURRENT_REQUESTS = 1000; +const TEST_TIMEOUT = 180000 * 10; // 180 seconds describe("Load Test for ECONNRESET", () => { jest.setTimeout(TEST_TIMEOUT); @@ -51,10 +51,10 @@ describe("Load Test for ECONNRESET", () => { //requestPromises.push(executor.getWorkflow(executionId, false)); requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); - if (i < CONCURRENT_REQUESTS - 1) { - // Wait 100ms before starting the next request. - await new Promise((resolve) => setTimeout(resolve, 0)); - } + // if (i < CONCURRENT_REQUESTS - 1) { + // // Wait 100ms before starting the next request. + // await new Promise((resolve) => setTimeout(resolve, 0)); + // } } // Now, wait for all the in-flight requests to complete. From f598aae0832e8db6b4311389dad08d29529f8bae Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 20:59:23 +0300 Subject: [PATCH 064/124] retry with sdkdev cluster --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 8fb7e989..4c965c22 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -49,7 +49,7 @@ describe("Load Test for ECONNRESET", () => { for (let i = 0; i < CONCURRENT_REQUESTS; i++) { // Start the request but don't wait for it to finish here. //requestPromises.push(executor.getWorkflow(executionId, false)); - requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); + requestPromises.push(fetch(`https://sdkdev.orkesconductor.io`)); // if (i < CONCURRENT_REQUESTS - 1) { // // Wait 100ms before starting the next request. From 6953394caecb375da592e9ed188b3f4561eebbba Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:01:28 +0300 Subject: [PATCH 065/124] retry with https://cloud.orkes.io/ --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 4c965c22..846e4038 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -49,7 +49,7 @@ describe("Load Test for ECONNRESET", () => { for (let i = 0; i < CONCURRENT_REQUESTS; i++) { // Start the request but don't wait for it to finish here. //requestPromises.push(executor.getWorkflow(executionId, false)); - requestPromises.push(fetch(`https://sdkdev.orkesconductor.io`)); + requestPromises.push(fetch(`https://cloud.orkes.io/`)); // if (i < CONCURRENT_REQUESTS - 1) { // // Wait 100ms before starting the next request. From 46afac24013103ea3476b2e26cc8e65bdbb8061d Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:04:28 +0300 Subject: [PATCH 066/124] retry with google --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 846e4038..d52ac9c0 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -49,7 +49,7 @@ describe("Load Test for ECONNRESET", () => { for (let i = 0; i < CONCURRENT_REQUESTS; i++) { // Start the request but don't wait for it to finish here. //requestPromises.push(executor.getWorkflow(executionId, false)); - requestPromises.push(fetch(`https://cloud.orkes.io/`)); + requestPromises.push(fetch(`https://google.com/`)); // if (i < CONCURRENT_REQUESTS - 1) { // // Wait 100ms before starting the next request. From e9f3e2504aab738ee99d2555a8341aaa7c23f10b Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:10:12 +0300 Subject: [PATCH 067/124] retry with google --- .github/workflows/pull_request.yml | 32 ++++++++++++----------- integration-tests/common/LoadTest.test.ts | 2 +- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index bb7103ab..0abdf1f8 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -3,28 +3,30 @@ name: Continuous Integration on: pull_request jobs: - linter: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up Node - uses: actions/setup-node@v4 - with: - node-version: "22" - - name: Install Dependencies - run: npm ci - - name: Run Linter - run: npm run lint + # linter: + # runs-on: ubuntu-latest + # steps: + # - name: Checkout + # uses: actions/checkout@v4 + # - name: Set up Node + # uses: actions/setup-node@v4 + # with: + # node-version: "22" + # - name: Install Dependencies + # run: npm ci + # - name: Run Linter + # run: npm run lint tests: + # runs-on: windows-latest runs-on: ubuntu-latest strategy: fail-fast: false max-parallel: 1 matrix: - node-version: [18, 20, 22, 24] - test: ["unit", "integration:v5", "integration:v4"] + node-version: [22] + # test: ["unit", "integration:v5", "integration:v4"] + test: ["integration:v5"] name: Node.js v${{ matrix.node-version }} - ${{ matrix.test }} tests steps: - name: Checkout diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index d52ac9c0..8fb7e989 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -49,7 +49,7 @@ describe("Load Test for ECONNRESET", () => { for (let i = 0; i < CONCURRENT_REQUESTS; i++) { // Start the request but don't wait for it to finish here. //requestPromises.push(executor.getWorkflow(executionId, false)); - requestPromises.push(fetch(`https://google.com/`)); + requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); // if (i < CONCURRENT_REQUESTS - 1) { // // Wait 100ms before starting the next request. From 4126a3005f8957039b03f1e3f525ceda11d30ee4 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:11:59 +0300 Subject: [PATCH 068/124] retry with only google fetch test --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 027cf57e..7ebc81bf 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "lint-fix": "npx eslint . --fix", "test": "jest --force-exit --detectOpenHandles", "test:unit": "jest --testMatch='**/src/**/__tests__/**/*.test.[jt]s?(x)' --force-exit", - "test:integration:v5": "jest --testMatch='**/integration-tests/{common,v5-only}/**/*.test.[jt]s?(x)' --force-exit --detectOpenHandles", + "test:integration:v5": "jest --testMatch='**/integration-tests/{common,v5-only}/**/LoadTest.test.[jt]s?(x)' --force-exit --detectOpenHandles", "test:integration:v4": "jest --testMatch='**/integration-tests/common/**/*.test.[jt]s?(x)' --force-exit --detectOpenHandles", "ci": "npm run lint && npm run test", "build": "tsup index.ts", From dbcfc9c5022df0d1aac0f35fb37f6946d9e52625 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:13:20 +0300 Subject: [PATCH 069/124] retry with 300 requests --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 8fb7e989..a213b67d 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -6,7 +6,7 @@ import { TaskType } from "../../src/common"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. // Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 1000; +const CONCURRENT_REQUESTS = 300; const TEST_TIMEOUT = 180000 * 10; // 180 seconds describe("Load Test for ECONNRESET", () => { From 020713d718217d0fed54be9fbcdc1d56a7bd8524 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:15:39 +0300 Subject: [PATCH 070/124] retry with 50 requests --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index a213b67d..c79a8fbd 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -6,7 +6,7 @@ import { TaskType } from "../../src/common"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. // Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 300; +const CONCURRENT_REQUESTS = 50; const TEST_TIMEOUT = 180000 * 10; // 180 seconds describe("Load Test for ECONNRESET", () => { From 8eb519ba8ce593b5b13d1d6028b6bfdf3db0ab3f Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:23:34 +0300 Subject: [PATCH 071/124] retry with google --- integration-tests/common/LoadTest.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index c79a8fbd..6914e2c3 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -6,7 +6,7 @@ import { TaskType } from "../../src/common"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. // Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 50; +const CONCURRENT_REQUESTS = 100; const TEST_TIMEOUT = 180000 * 10; // 180 seconds describe("Load Test for ECONNRESET", () => { @@ -49,7 +49,7 @@ describe("Load Test for ECONNRESET", () => { for (let i = 0; i < CONCURRENT_REQUESTS; i++) { // Start the request but don't wait for it to finish here. //requestPromises.push(executor.getWorkflow(executionId, false)); - requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); + requestPromises.push(fetch(`https://google.com/`)); // if (i < CONCURRENT_REQUESTS - 1) { // // Wait 100ms before starting the next request. From 0dce52f899ce6c360d91f348675a68e4a2f70a0f Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:24:46 +0300 Subject: [PATCH 072/124] retry with 1000 requests --- integration-tests/common/LoadTestPost.test.ts | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 integration-tests/common/LoadTestPost.test.ts diff --git a/integration-tests/common/LoadTestPost.test.ts b/integration-tests/common/LoadTestPost.test.ts new file mode 100644 index 00000000..aa1630a2 --- /dev/null +++ b/integration-tests/common/LoadTestPost.test.ts @@ -0,0 +1,88 @@ +import { describe, test, expect, jest } from "@jest/globals"; +import { orkesConductorClient } from "../../src/orkes"; +import { WorkflowExecutor } from "../../src/core"; +import { TaskType, WorkflowDef } from "../../src/common"; + +// --- Configuration for the Load Test --- +// The number of requests to send in parallel. +// Adjust this number to find the breaking point of your load balancer. +const CONCURRENT_REQUESTS = 3000; +const TEST_TIMEOUT = 60000 * 10; // 60 seconds + +describe("Load balancer test for POST requests", () => { + jest.setTimeout(TEST_TIMEOUT); + + test(`should handle ${CONCURRENT_REQUESTS} POST requests`, async () => { + const client = await orkesConductorClient(); + const executor = new WorkflowExecutor(client); + console.log(`Starting POST load test for workflow registration`); + console.log(`Sending ${CONCURRENT_REQUESTS} concurrent requests...`); + const requestPromises: Promise[] = []; + for (let i = 0; i < CONCURRENT_REQUESTS; i++) { + const workflowName = "JS_SDK_load_test_post_workflow" + const workflowDef: WorkflowDef = { + name: workflowName, + version: 1, + inputParameters: [], + tasks: [ + { + name: "JS_SDK_simple_task_post", + taskReferenceName: "JS_SDK_simple_task_post_ref", + type: TaskType.SIMPLE, + }, + ], + timeoutSeconds: 0, + }; + requestPromises.push(executor.registerWorkflow(true, workflowDef)); + } + const results = await Promise.allSettled(requestPromises); + let successCount = 0; + const econnresetErrors: any[] = []; + const http429Errors: any[] = []; + const otherErrors: any[] = []; + results.forEach((result, index) => { + if (result.status === "fulfilled") { + successCount++; + } else { + const reason = result.reason; + if (reason?.code === "ECONNRESET") { + econnresetErrors.push({ requestIndex: index, reason }); + } else if (reason?.body?.status === 429) { + http429Errors.push({ requestIndex: index, reason }); + } else { + otherErrors.push({ requestIndex: index, reason }); + } + } + }); + console.log("--- Load Test Results ---"); + console.log( + `Successful Requests: ${successCount} / ${CONCURRENT_REQUESTS}` + ); + console.log(`ECONNRESET Failures: ${econnresetErrors.length}`); + console.log(`HTTP 429 Failures: ${http429Errors.length}`); + console.log(`Other Failures: ${otherErrors.length}`); + console.log("-------------------------"); + if (econnresetErrors.length > 0) { + console.error("ECONNRESET errors detected:", econnresetErrors); + } + if (http429Errors.length > 0) { + console.error( + "HTTP 429 (Too Many Requests) errors detected:", + http429Errors + ); + } + if (otherErrors.length > 0) { + console.error(`\n--- Other Errors (${otherErrors.length}) ---`); + for (const error of otherErrors) { + console.error( + `Request Index ${error.requestIndex} failed. Reason:`, + error.reason + ); + } + console.error("--------------------------\n"); + } + expect(econnresetErrors.length).toBe(0); + expect(http429Errors.length).toBe(0); + expect(otherErrors.length).toBe(0); + }); +}); From a7ca85945beb9703f454d43a2192b785e4880845 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:25:58 +0300 Subject: [PATCH 073/124] retry with 1000 requests --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 6914e2c3..d52ac9c0 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -6,7 +6,7 @@ import { TaskType } from "../../src/common"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. // Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 100; +const CONCURRENT_REQUESTS = 1000; const TEST_TIMEOUT = 180000 * 10; // 180 seconds describe("Load Test for ECONNRESET", () => { From 054e0dfd7153eb95ed54b038ec964146ec22bba6 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:27:45 +0300 Subject: [PATCH 074/124] retry with undici --- integration-tests/common/LoadTest.test.ts | 26 +++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index d52ac9c0..79cc22dc 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -44,12 +44,26 @@ describe("Load Test for ECONNRESET", () => { `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 0ms)...` ); - // Create an array to hold all the request promises. - const requestPromises: Promise[] = []; - for (let i = 0; i < CONCURRENT_REQUESTS; i++) { - // Start the request but don't wait for it to finish here. - //requestPromises.push(executor.getWorkflow(executionId, false)); - requestPromises.push(fetch(`https://google.com/`)); + // Create an array to hold all the request promises. + const { fetch: undiciFetch, Agent } = await import("undici"); + const undiciAgent = new Agent({ + //allowH2: true, + connect: { + timeout: 270000, // Connect timeout in milliseconds (e.g., 60 seconds) + }, + }); + + // Create an array to hold all the request promises. + const requestPromises: Promise[] = []; + for (let i = 0; i < CONCURRENT_REQUESTS; i++) { + // Start the request but don't wait for it to finish here. + //requestPromises.push(executor.getWorkflow(executionId, false)); + //requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); + requestPromises.push( + undiciFetch(`https://google.com/`, { + dispatcher: undiciAgent, + }) + ); // if (i < CONCURRENT_REQUESTS - 1) { // // Wait 100ms before starting the next request. From 02e7464e37f5e6d0827df08ec4abe56b708a3b4d Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:29:29 +0300 Subject: [PATCH 075/124] retry with undici --- integration-tests/common/LoadTest.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 79cc22dc..878fb6df 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -2,6 +2,7 @@ import { describe, test, expect, jest } from "@jest/globals"; import { orkesConductorClient } from "../../src/orkes"; import { WorkflowExecutor } from "../../src/core"; import { TaskType } from "../../src/common"; +import { fetch as undiciFetch, Agent as UndiciAgent } from "undici"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. @@ -45,8 +46,7 @@ describe("Load Test for ECONNRESET", () => { ); // Create an array to hold all the request promises. - const { fetch: undiciFetch, Agent } = await import("undici"); - const undiciAgent = new Agent({ + const undiciAgent = new UndiciAgent({ //allowH2: true, connect: { timeout: 270000, // Connect timeout in milliseconds (e.g., 60 seconds) From ca01cb9f838fce185bdd68b6f4dd12236f61bb88 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:34:59 +0300 Subject: [PATCH 076/124] retry with fetch --- integration-tests/common/LoadTest.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 878fb6df..c7a2284f 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -7,7 +7,7 @@ import { fetch as undiciFetch, Agent as UndiciAgent } from "undici"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. // Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 1000; +const CONCURRENT_REQUESTS = 500; const TEST_TIMEOUT = 180000 * 10; // 180 seconds describe("Load Test for ECONNRESET", () => { @@ -60,9 +60,9 @@ describe("Load Test for ECONNRESET", () => { //requestPromises.push(executor.getWorkflow(executionId, false)); //requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); requestPromises.push( - undiciFetch(`https://google.com/`, { - dispatcher: undiciAgent, - }) + fetch(`https://google.com/`) //, { + // dispatcher: undiciAgent, + // }) ); // if (i < CONCURRENT_REQUESTS - 1) { From d1f0685b9fe81010d6c0ed2901058fc83b37ac12 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:38:09 +0300 Subject: [PATCH 077/124] retry with abortcontroller --- integration-tests/common/LoadTest.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index c7a2284f..0c3d680b 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -52,6 +52,9 @@ describe("Load Test for ECONNRESET", () => { timeout: 270000, // Connect timeout in milliseconds (e.g., 60 seconds) }, }); + + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 270000) // Create an array to hold all the request promises. const requestPromises: Promise[] = []; @@ -60,7 +63,7 @@ describe("Load Test for ECONNRESET", () => { //requestPromises.push(executor.getWorkflow(executionId, false)); //requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); requestPromises.push( - fetch(`https://google.com/`) //, { + fetch(`https://google.com/`, { signal: controller.signal }) //, { // dispatcher: undiciAgent, // }) ); From 85de3b7e37745630ded419cf5dd129569a4b04f6 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:40:17 +0300 Subject: [PATCH 078/124] retry with abortcontroller --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 0c3d680b..82c6ea93 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -63,7 +63,7 @@ describe("Load Test for ECONNRESET", () => { //requestPromises.push(executor.getWorkflow(executionId, false)); //requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); requestPromises.push( - fetch(`https://google.com/`, { signal: controller.signal }) //, { + fetch(`https://google.com/`, { signal: AbortSignal.timeout(1000000) }) //, { // dispatcher: undiciAgent, // }) ); From aba45e4c64bbfbd5730dba285a4b8d67bc1b1865 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:42:22 +0300 Subject: [PATCH 079/124] retry with undici --- integration-tests/common/LoadTest.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 82c6ea93..168ee18a 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -47,6 +47,7 @@ describe("Load Test for ECONNRESET", () => { // Create an array to hold all the request promises. const undiciAgent = new UndiciAgent({ + connectTimeout: 270000, //allowH2: true, connect: { timeout: 270000, // Connect timeout in milliseconds (e.g., 60 seconds) @@ -63,7 +64,7 @@ describe("Load Test for ECONNRESET", () => { //requestPromises.push(executor.getWorkflow(executionId, false)); //requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); requestPromises.push( - fetch(`https://google.com/`, { signal: AbortSignal.timeout(1000000) }) //, { + undiciFetch(`https://google.com/`, { dispatcher: undiciAgent }) //, { // dispatcher: undiciAgent, // }) ); From 1b3ffd90834bc78cc9fae4357231915f81204379 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:44:45 +0300 Subject: [PATCH 080/124] retry with fetch & 100 requests --- integration-tests/common/LoadTest.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 168ee18a..cbf361c9 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -7,7 +7,7 @@ import { fetch as undiciFetch, Agent as UndiciAgent } from "undici"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. // Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 500; +const CONCURRENT_REQUESTS = 100; const TEST_TIMEOUT = 180000 * 10; // 180 seconds describe("Load Test for ECONNRESET", () => { @@ -55,7 +55,7 @@ describe("Load Test for ECONNRESET", () => { }); const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), 270000) + //const timeoutId = setTimeout(() => controller.abort(), 270000) // Create an array to hold all the request promises. const requestPromises: Promise[] = []; @@ -64,7 +64,7 @@ describe("Load Test for ECONNRESET", () => { //requestPromises.push(executor.getWorkflow(executionId, false)); //requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); requestPromises.push( - undiciFetch(`https://google.com/`, { dispatcher: undiciAgent }) //, { + fetch(`https://google.com/`) //, { // dispatcher: undiciAgent, // }) ); From e947a4e56f47de268a4657820707c1295c2cc187 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:46:00 +0300 Subject: [PATCH 081/124] retry with 300 requests --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index cbf361c9..a222c8af 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -7,7 +7,7 @@ import { fetch as undiciFetch, Agent as UndiciAgent } from "undici"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. // Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 100; +const CONCURRENT_REQUESTS = 300; const TEST_TIMEOUT = 180000 * 10; // 180 seconds describe("Load Test for ECONNRESET", () => { From ca362bc1141f8f8b791ed4ccc064f9125e325bfb Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:47:18 +0300 Subject: [PATCH 082/124] retry with 200 requests --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index a222c8af..f8650e59 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -7,7 +7,7 @@ import { fetch as undiciFetch, Agent as UndiciAgent } from "undici"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. // Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 300; +const CONCURRENT_REQUESTS = 200; const TEST_TIMEOUT = 180000 * 10; // 180 seconds describe("Load Test for ECONNRESET", () => { From 6b3789c4b1252966c8ee11d47a2b7ac8a0e1c49a Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:51:07 +0300 Subject: [PATCH 083/124] retry with abortcontroller --- integration-tests/common/LoadTest.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index f8650e59..9ece67ca 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -55,7 +55,7 @@ describe("Load Test for ECONNRESET", () => { }); const controller = new AbortController(); - //const timeoutId = setTimeout(() => controller.abort(), 270000) + const timeoutId = setTimeout(() => controller.abort(), 270000) // Create an array to hold all the request promises. const requestPromises: Promise[] = []; @@ -64,7 +64,7 @@ describe("Load Test for ECONNRESET", () => { //requestPromises.push(executor.getWorkflow(executionId, false)); //requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); requestPromises.push( - fetch(`https://google.com/`) //, { + fetch(`https://google.com/`, { signal: controller.signal }) //, { // dispatcher: undiciAgent, // }) ); From 51fb0b739034d46072edfde51775a4e793007809 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:52:35 +0300 Subject: [PATCH 084/124] retry with 500 requests --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 9ece67ca..2f89c662 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -7,7 +7,7 @@ import { fetch as undiciFetch, Agent as UndiciAgent } from "undici"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. // Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 200; +const CONCURRENT_REQUESTS = 500; const TEST_TIMEOUT = 180000 * 10; // 180 seconds describe("Load Test for ECONNRESET", () => { From 0bcb2caf5ed1c1721f32bf43bd85e9b37370cb69 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:53:50 +0300 Subject: [PATCH 085/124] 200 requests --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 2f89c662..9ece67ca 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -7,7 +7,7 @@ import { fetch as undiciFetch, Agent as UndiciAgent } from "undici"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. // Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 500; +const CONCURRENT_REQUESTS = 200; const TEST_TIMEOUT = 180000 * 10; // 180 seconds describe("Load Test for ECONNRESET", () => { From 0d1edec4aea48eed41dfbcb76a8cfdb48ddeac84 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 21:55:05 +0300 Subject: [PATCH 086/124] retry with orkes cluster --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 9ece67ca..e3bb1af1 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -64,7 +64,7 @@ describe("Load Test for ECONNRESET", () => { //requestPromises.push(executor.getWorkflow(executionId, false)); //requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); requestPromises.push( - fetch(`https://google.com/`, { signal: controller.signal }) //, { + fetch(`https://siliconmint-dev-5x.orkesconductor.io/`, { signal: controller.signal }) //, { // dispatcher: undiciAgent, // }) ); From b015af957b1ad88e46228228c58941e8a6bba336 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 22:00:59 +0300 Subject: [PATCH 087/124] Update LoadTest.test.ts --- integration-tests/common/LoadTest.test.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index e3bb1af1..d9c2eee4 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -54,17 +54,15 @@ describe("Load Test for ECONNRESET", () => { }, }); - const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), 270000) - // Create an array to hold all the request promises. const requestPromises: Promise[] = []; for (let i = 0; i < CONCURRENT_REQUESTS; i++) { // Start the request but don't wait for it to finish here. //requestPromises.push(executor.getWorkflow(executionId, false)); //requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); + const signal = AbortSignal.timeout(60000) requestPromises.push( - fetch(`https://siliconmint-dev-5x.orkesconductor.io/`, { signal: controller.signal }) //, { + fetch(`https://siliconmint-dev-5x.orkesconductor.io/`, { signal }) //, { // dispatcher: undiciAgent, // }) ); From ee2cf6d84492813dab43b926bae4245d54620283 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 22:02:05 +0300 Subject: [PATCH 088/124] Update LoadTest.test.ts --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index d9c2eee4..147476b7 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -62,7 +62,7 @@ describe("Load Test for ECONNRESET", () => { //requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); const signal = AbortSignal.timeout(60000) requestPromises.push( - fetch(`https://siliconmint-dev-5x.orkesconductor.io/`, { signal }) //, { + fetch(`https://google.com/`, { signal }) //, { // dispatcher: undiciAgent, // }) ); From d26f2f5a4dcca3815860342bc73e0e300e8b4454 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 22:09:02 +0300 Subject: [PATCH 089/124] Update LoadTest.test.ts --- integration-tests/common/LoadTest.test.ts | 46 ++++++++++++----------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 147476b7..abd4be2a 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -45,27 +45,28 @@ describe("Load Test for ECONNRESET", () => { `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 0ms)...` ); - // Create an array to hold all the request promises. - const undiciAgent = new UndiciAgent({ - connectTimeout: 270000, - //allowH2: true, - connect: { - timeout: 270000, // Connect timeout in milliseconds (e.g., 60 seconds) - }, - }); + // Create an array to hold all the request promises. + const undiciAgent = new UndiciAgent({ + connectTimeout: 270000, + bodyTimeout: 270000, + headersTimeout: 270000, + //allowH2: true, + connect: { + timeout: 270000, // Connect timeout in milliseconds (e.g., 60 seconds) + }, + }); - // Create an array to hold all the request promises. - const requestPromises: Promise[] = []; - for (let i = 0; i < CONCURRENT_REQUESTS; i++) { - // Start the request but don't wait for it to finish here. - //requestPromises.push(executor.getWorkflow(executionId, false)); - //requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); - const signal = AbortSignal.timeout(60000) - requestPromises.push( - fetch(`https://google.com/`, { signal }) //, { - // dispatcher: undiciAgent, - // }) - ); + // Create an array to hold all the request promises. + const requestPromises: Promise[] = []; + for (let i = 0; i < CONCURRENT_REQUESTS; i++) { + // Start the request but don't wait for it to finish here. + //requestPromises.push(executor.getWorkflow(executionId, false)); + //requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); + requestPromises.push( + undiciFetch(`https://google.com/`, { + dispatcher: undiciAgent, + }) + ); // if (i < CONCURRENT_REQUESTS - 1) { // // Wait 100ms before starting the next request. @@ -111,7 +112,10 @@ describe("Load Test for ECONNRESET", () => { console.error("ECONNRESET errors detected:", econnresetErrors); } if (http429Errors.length > 0) { - console.error("HTTP 429 (Too Many Requests) errors detected:", http429Errors); + console.error( + "HTTP 429 (Too Many Requests) errors detected:", + http429Errors + ); } if (otherErrors.length > 0) { console.error(`\n--- Other Errors (${otherErrors.length}) ---`); From adc72a3312b9541ae32db0a4732e165d2a45f431 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 22:10:01 +0300 Subject: [PATCH 090/124] Update LoadTest.test.ts --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index abd4be2a..72accb6f 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -7,7 +7,7 @@ import { fetch as undiciFetch, Agent as UndiciAgent } from "undici"; // --- Configuration for the Load Test --- // The number of requests to send in parallel. // Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 200; +const CONCURRENT_REQUESTS = 500; const TEST_TIMEOUT = 180000 * 10; // 180 seconds describe("Load Test for ECONNRESET", () => { From ef6354522f41f08fab14d1c44ec3667cf2f53c03 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 22:15:10 +0300 Subject: [PATCH 091/124] Update LoadTest.test.ts --- integration-tests/common/LoadTest.test.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 72accb6f..84cb4607 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -47,6 +47,7 @@ describe("Load Test for ECONNRESET", () => { // Create an array to hold all the request promises. const undiciAgent = new UndiciAgent({ + connections: 500, connectTimeout: 270000, bodyTimeout: 270000, headersTimeout: 270000, @@ -67,6 +68,11 @@ describe("Load Test for ECONNRESET", () => { dispatcher: undiciAgent, }) ); + // requestPromises.push( + // undiciFetch(`https://siliconmint-dev-5x.orkesconductor.io/`, { + // dispatcher: undiciAgent, + // }) + // ); // if (i < CONCURRENT_REQUESTS - 1) { // // Wait 100ms before starting the next request. From e9ee0ae3b606194eb5d15280c13e9cc916348cc9 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 22:17:07 +0300 Subject: [PATCH 092/124] Update LoadTest.test.ts --- integration-tests/common/LoadTest.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 84cb4607..6ed56283 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -48,6 +48,9 @@ describe("Load Test for ECONNRESET", () => { // Create an array to hold all the request promises. const undiciAgent = new UndiciAgent({ connections: 500, + //pipelining: 10, + keepAliveTimeout: 270000, + keepAliveMaxTimeout: 270000, connectTimeout: 270000, bodyTimeout: 270000, headersTimeout: 270000, From 77ae4fdef8567b12d6e9e83602939b6202dd702c Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 22:18:09 +0300 Subject: [PATCH 093/124] Update LoadTest.test.ts --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 6ed56283..b7d0da75 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -47,7 +47,7 @@ describe("Load Test for ECONNRESET", () => { // Create an array to hold all the request promises. const undiciAgent = new UndiciAgent({ - connections: 500, + connections: 20, //pipelining: 10, keepAliveTimeout: 270000, keepAliveMaxTimeout: 270000, From 76d0308c6470d5770c084c191c58c13744d60178 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 22:20:28 +0300 Subject: [PATCH 094/124] Update LoadTest.test.ts --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index b7d0da75..e76a5bbd 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -67,7 +67,7 @@ describe("Load Test for ECONNRESET", () => { //requestPromises.push(executor.getWorkflow(executionId, false)); //requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); requestPromises.push( - undiciFetch(`https://google.com/`, { + undiciFetch(`https://siliconmint-dev-5x.orkesconductor.io/`, { dispatcher: undiciAgent, }) ); From 15e567eed6d2548cbe1d8bf26828d74d1a562e7f Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 22:22:35 +0300 Subject: [PATCH 095/124] Update LoadTest.test.ts --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index e76a5bbd..65f4b179 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -47,7 +47,7 @@ describe("Load Test for ECONNRESET", () => { // Create an array to hold all the request promises. const undiciAgent = new UndiciAgent({ - connections: 20, + connections: 1, //pipelining: 10, keepAliveTimeout: 270000, keepAliveMaxTimeout: 270000, From 0cef45cf05b1dedd616c6e974eef5852918cdfe7 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 22:24:46 +0300 Subject: [PATCH 096/124] Update LoadTest.test.ts --- integration-tests/common/LoadTest.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 65f4b179..acce0027 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -47,6 +47,7 @@ describe("Load Test for ECONNRESET", () => { // Create an array to hold all the request promises. const undiciAgent = new UndiciAgent({ + allowH2: true, connections: 1, //pipelining: 10, keepAliveTimeout: 270000, From 5186525cbdad442c06ea133f2c81ec31b5050857 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 22:31:46 +0300 Subject: [PATCH 097/124] Update LoadTest.test.ts --- integration-tests/common/LoadTest.test.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index acce0027..6bc321b4 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -50,15 +50,14 @@ describe("Load Test for ECONNRESET", () => { allowH2: true, connections: 1, //pipelining: 10, - keepAliveTimeout: 270000, - keepAliveMaxTimeout: 270000, - connectTimeout: 270000, - bodyTimeout: 270000, - headersTimeout: 270000, - //allowH2: true, - connect: { - timeout: 270000, // Connect timeout in milliseconds (e.g., 60 seconds) - }, + // keepAliveTimeout: 270000, + // keepAliveMaxTimeout: 270000, + // connectTimeout: 270000, + // bodyTimeout: 270000, + // headersTimeout: 270000, + // connect: { + // timeout: 270000, // Connect timeout in milliseconds (e.g., 60 seconds) + // }, }); // Create an array to hold all the request promises. From 02575681ca0207f96148b8574d38d94da8b0bd0b Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 22:33:26 +0300 Subject: [PATCH 098/124] Update LoadTest.test.ts --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 6bc321b4..b1e59b27 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -47,7 +47,7 @@ describe("Load Test for ECONNRESET", () => { // Create an array to hold all the request promises. const undiciAgent = new UndiciAgent({ - allowH2: true, + //allowH2: true, connections: 1, //pipelining: 10, // keepAliveTimeout: 270000, From 4a03765dbc4529defa85d415970bef3c204db973 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 22:43:01 +0300 Subject: [PATCH 099/124] Update LoadTest.test.ts --- integration-tests/common/LoadTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index b1e59b27..6bc321b4 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -47,7 +47,7 @@ describe("Load Test for ECONNRESET", () => { // Create an array to hold all the request promises. const undiciAgent = new UndiciAgent({ - //allowH2: true, + allowH2: true, connections: 1, //pipelining: 10, // keepAliveTimeout: 270000, From e3f1fbffca82723f143e71a66f061ec4df0a509b Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 22:49:48 +0300 Subject: [PATCH 100/124] restore changes --- .github/workflows/pull_request.yml | 32 ++++--- integration-tests/common/LoadTestPost.test.ts | 88 ------------------- package.json | 2 +- src/orkes/helpers/resolveFetchFn.ts | 2 +- 4 files changed, 17 insertions(+), 107 deletions(-) delete mode 100644 integration-tests/common/LoadTestPost.test.ts diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 0abdf1f8..1f4a65dc 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -3,30 +3,28 @@ name: Continuous Integration on: pull_request jobs: - # linter: - # runs-on: ubuntu-latest - # steps: - # - name: Checkout - # uses: actions/checkout@v4 - # - name: Set up Node - # uses: actions/setup-node@v4 - # with: - # node-version: "22" - # - name: Install Dependencies - # run: npm ci - # - name: Run Linter - # run: npm run lint + linter: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: "22" + - name: Install Dependencies + run: npm ci + - name: Run Linter + run: npm run lint tests: - # runs-on: windows-latest runs-on: ubuntu-latest strategy: fail-fast: false max-parallel: 1 matrix: - node-version: [22] - # test: ["unit", "integration:v5", "integration:v4"] - test: ["integration:v5"] + node-version: [18, 20, 22] + test: ["unit", "integration:v5", "integration:v4"] name: Node.js v${{ matrix.node-version }} - ${{ matrix.test }} tests steps: - name: Checkout diff --git a/integration-tests/common/LoadTestPost.test.ts b/integration-tests/common/LoadTestPost.test.ts deleted file mode 100644 index aa1630a2..00000000 --- a/integration-tests/common/LoadTestPost.test.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { describe, test, expect, jest } from "@jest/globals"; -import { orkesConductorClient } from "../../src/orkes"; -import { WorkflowExecutor } from "../../src/core"; -import { TaskType, WorkflowDef } from "../../src/common"; - -// --- Configuration for the Load Test --- -// The number of requests to send in parallel. -// Adjust this number to find the breaking point of your load balancer. -const CONCURRENT_REQUESTS = 3000; -const TEST_TIMEOUT = 60000 * 10; // 60 seconds - -describe("Load balancer test for POST requests", () => { - jest.setTimeout(TEST_TIMEOUT); - - test(`should handle ${CONCURRENT_REQUESTS} POST requests`, async () => { - const client = await orkesConductorClient(); - const executor = new WorkflowExecutor(client); - console.log(`Starting POST load test for workflow registration`); - console.log(`Sending ${CONCURRENT_REQUESTS} concurrent requests...`); - const requestPromises: Promise[] = []; - for (let i = 0; i < CONCURRENT_REQUESTS; i++) { - const workflowName = "JS_SDK_load_test_post_workflow" - const workflowDef: WorkflowDef = { - name: workflowName, - version: 1, - inputParameters: [], - tasks: [ - { - name: "JS_SDK_simple_task_post", - taskReferenceName: "JS_SDK_simple_task_post_ref", - type: TaskType.SIMPLE, - }, - ], - timeoutSeconds: 0, - }; - requestPromises.push(executor.registerWorkflow(true, workflowDef)); - } - const results = await Promise.allSettled(requestPromises); - let successCount = 0; - const econnresetErrors: any[] = []; - const http429Errors: any[] = []; - const otherErrors: any[] = []; - results.forEach((result, index) => { - if (result.status === "fulfilled") { - successCount++; - } else { - const reason = result.reason; - if (reason?.code === "ECONNRESET") { - econnresetErrors.push({ requestIndex: index, reason }); - } else if (reason?.body?.status === 429) { - http429Errors.push({ requestIndex: index, reason }); - } else { - otherErrors.push({ requestIndex: index, reason }); - } - } - }); - console.log("--- Load Test Results ---"); - console.log( - `Successful Requests: ${successCount} / ${CONCURRENT_REQUESTS}` - ); - console.log(`ECONNRESET Failures: ${econnresetErrors.length}`); - console.log(`HTTP 429 Failures: ${http429Errors.length}`); - console.log(`Other Failures: ${otherErrors.length}`); - console.log("-------------------------"); - if (econnresetErrors.length > 0) { - console.error("ECONNRESET errors detected:", econnresetErrors); - } - if (http429Errors.length > 0) { - console.error( - "HTTP 429 (Too Many Requests) errors detected:", - http429Errors - ); - } - if (otherErrors.length > 0) { - console.error(`\n--- Other Errors (${otherErrors.length}) ---`); - for (const error of otherErrors) { - console.error( - `Request Index ${error.requestIndex} failed. Reason:`, - error.reason - ); - } - console.error("--------------------------\n"); - } - expect(econnresetErrors.length).toBe(0); - expect(http429Errors.length).toBe(0); - expect(otherErrors.length).toBe(0); - }); -}); diff --git a/package.json b/package.json index 7ebc81bf..027cf57e 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "lint-fix": "npx eslint . --fix", "test": "jest --force-exit --detectOpenHandles", "test:unit": "jest --testMatch='**/src/**/__tests__/**/*.test.[jt]s?(x)' --force-exit", - "test:integration:v5": "jest --testMatch='**/integration-tests/{common,v5-only}/**/LoadTest.test.[jt]s?(x)' --force-exit --detectOpenHandles", + "test:integration:v5": "jest --testMatch='**/integration-tests/{common,v5-only}/**/*.test.[jt]s?(x)' --force-exit --detectOpenHandles", "test:integration:v4": "jest --testMatch='**/integration-tests/common/**/*.test.[jt]s?(x)' --force-exit --detectOpenHandles", "ci": "npm run lint && npm run test", "build": "tsup index.ts", diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index 5f5f5261..bf0b4c70 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -13,7 +13,7 @@ export const resolveFetchFn = async ( // eslint-disable-next-line // @ts-ignore since undici is an optional dependency and could me missing const { fetch: undiciFetch, Agent } = await import("undici"); - const undiciAgent = new Agent({ allowH2: true }); + const undiciAgent = new Agent({ allowH2: true, connections: 1 }); return ((input: RequestInfo, init?: RequestInit) => undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; From 732b86a716fe7afafe4cf5b9548188971fd1a6ad Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 22:59:56 +0300 Subject: [PATCH 101/124] retry with 500 connections --- src/orkes/helpers/resolveFetchFn.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index bf0b4c70..06dcb7ca 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -13,7 +13,7 @@ export const resolveFetchFn = async ( // eslint-disable-next-line // @ts-ignore since undici is an optional dependency and could me missing const { fetch: undiciFetch, Agent } = await import("undici"); - const undiciAgent = new Agent({ allowH2: true, connections: 1 }); + const undiciAgent = new Agent({ allowH2: true, connections: 500 }); return ((input: RequestInfo, init?: RequestInit) => undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; From 39921c65e5dbbc50b5d3cf805bfd959da40e6bc4 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 23:10:34 +0300 Subject: [PATCH 102/124] retry with 1 connection --- integration-tests/common/LoadTest.test.ts | 129 ++++++---------------- src/orkes/helpers/resolveFetchFn.ts | 2 +- 2 files changed, 35 insertions(+), 96 deletions(-) diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts index 6bc321b4..2ec6f115 100644 --- a/integration-tests/common/LoadTest.test.ts +++ b/integration-tests/common/LoadTest.test.ts @@ -2,11 +2,7 @@ import { describe, test, expect, jest } from "@jest/globals"; import { orkesConductorClient } from "../../src/orkes"; import { WorkflowExecutor } from "../../src/core"; import { TaskType } from "../../src/common"; -import { fetch as undiciFetch, Agent as UndiciAgent } from "undici"; -// --- Configuration for the Load Test --- -// The number of requests to send in parallel. -// Adjust this number to find the breaking point of your load balancer. const CONCURRENT_REQUESTS = 500; const TEST_TIMEOUT = 180000 * 10; // 180 seconds @@ -14,97 +10,54 @@ describe("Load Test for ECONNRESET", () => { jest.setTimeout(TEST_TIMEOUT); test(`should handle ${CONCURRENT_REQUESTS} staggered GET requests (1 every 0ms) without ECONNRESET`, async () => { - // const client = await orkesConductorClient(); - // const executor = new WorkflowExecutor(client); + const client = await orkesConductorClient(); + const executor = new WorkflowExecutor(client); - // // To ensure we are making valid API calls, we first create a simple - // // workflow and start one execution. We will then query this execution's status. - // const workflowName = "load_test_workflow"; - // await executor.registerWorkflow(true, { - // name: workflowName, - // version: 1, - // tasks: [ - // { - // name: "simple_task", - // taskReferenceName: "simple_task_ref", - // type: TaskType.SIMPLE, - // }, - // ], - // timeoutSeconds: 0, - // inputParameters: [], - // }); - // const executionId = await executor.startWorkflow({ - // name: workflowName, - // version: 1, - // }); + // To ensure we are making valid API calls, we first create a simple + // workflow and start one execution. We will then query this execution's status. + const workflowName = "load_test_workflow"; + await executor.registerWorkflow(true, { + name: workflowName, + version: 1, + tasks: [ + { + name: "simple_task", + taskReferenceName: "simple_task_ref", + type: TaskType.SIMPLE, + }, + ], + timeoutSeconds: 0, + inputParameters: [], + }); + const executionId = await executor.startWorkflow({ + name: workflowName, + version: 1, + }); - // console.log( - // `Starting load test with workflow execution ID: ${executionId}` - // ); + console.log( + `Starting load test with workflow execution ID: ${executionId}` + ); console.log( `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 0ms)...` ); - // Create an array to hold all the request promises. - const undiciAgent = new UndiciAgent({ - allowH2: true, - connections: 1, - //pipelining: 10, - // keepAliveTimeout: 270000, - // keepAliveMaxTimeout: 270000, - // connectTimeout: 270000, - // bodyTimeout: 270000, - // headersTimeout: 270000, - // connect: { - // timeout: 270000, // Connect timeout in milliseconds (e.g., 60 seconds) - // }, - }); - - // Create an array to hold all the request promises. const requestPromises: Promise[] = []; for (let i = 0; i < CONCURRENT_REQUESTS; i++) { - // Start the request but don't wait for it to finish here. - //requestPromises.push(executor.getWorkflow(executionId, false)); - //requestPromises.push(fetch(`https://siliconmint-dev-5x.orkesconductor.io/`)); - requestPromises.push( - undiciFetch(`https://siliconmint-dev-5x.orkesconductor.io/`, { - dispatcher: undiciAgent, - }) - ); - // requestPromises.push( - // undiciFetch(`https://siliconmint-dev-5x.orkesconductor.io/`, { - // dispatcher: undiciAgent, - // }) - // ); - - // if (i < CONCURRENT_REQUESTS - 1) { - // // Wait 100ms before starting the next request. - // await new Promise((resolve) => setTimeout(resolve, 0)); - // } + requestPromises.push(executor.getWorkflow(executionId, false)); } - // Now, wait for all the in-flight requests to complete. const results = await Promise.allSettled(requestPromises); - // Analyze the results to find specific errors let successCount = 0; - const econnresetErrors: any[] = []; - const http429Errors: any[] = []; - const otherErrors: any[] = []; + const errors: any[] = []; results.forEach((result, index) => { if (result.status === "fulfilled") { successCount++; } else { const reason = result.reason; - // Check if the rejection reason is the specific ECONNRESET error - if (reason?.code === "ECONNRESET") { - econnresetErrors.push({ requestIndex: index, reason }); - } else if (reason?.body?.status === 429) { - http429Errors.push({ requestIndex: index, reason }); - } else { - otherErrors.push({ requestIndex: index, reason }); - } + + errors.push({ requestIndex: index, reason }); } }); @@ -112,23 +65,12 @@ describe("Load Test for ECONNRESET", () => { console.log( `Successful Requests: ${successCount} / ${CONCURRENT_REQUESTS}` ); - console.log(`ECONNRESET Failures: ${econnresetErrors.length}`); - console.log(`HTTP 429 Failures: ${http429Errors.length}`); - console.log(`Other Failures: ${otherErrors.length}`); + console.log(`Failures: ${errors.length}`); console.log("-------------------------"); - if (econnresetErrors.length > 0) { - console.error("ECONNRESET errors detected:", econnresetErrors); - } - if (http429Errors.length > 0) { - console.error( - "HTTP 429 (Too Many Requests) errors detected:", - http429Errors - ); - } - if (otherErrors.length > 0) { - console.error(`\n--- Other Errors (${otherErrors.length}) ---`); - for (const error of otherErrors) { + if (errors.length > 0) { + console.error(`\n--- Errors (${errors.length}) ---`); + for (const error of errors) { console.error( `Request Index ${error.requestIndex} failed. Reason:`, error.reason @@ -137,9 +79,6 @@ describe("Load Test for ECONNRESET", () => { console.error("--------------------------\n"); } - // The test assertion: Fail if we encounter any ECONNRESET errors. - expect(econnresetErrors.length).toBe(0); - expect(http429Errors.length).toBe(0); - expect(otherErrors.length).toBe(0); + expect(errors.length).toBe(0); }); }); diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index 06dcb7ca..bf0b4c70 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -13,7 +13,7 @@ export const resolveFetchFn = async ( // eslint-disable-next-line // @ts-ignore since undici is an optional dependency and could me missing const { fetch: undiciFetch, Agent } = await import("undici"); - const undiciAgent = new Agent({ allowH2: true, connections: 500 }); + const undiciAgent = new Agent({ allowH2: true, connections: 1 }); return ((input: RequestInfo, init?: RequestInit) => undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; From 719f9b416639a1b389d4299ea8b60fcc2f5097e6 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 23:43:58 +0300 Subject: [PATCH 103/124] add maxSockets: 1 for node 18 --- src/orkes/helpers/resolveFetchFn.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index bf0b4c70..af05ecd5 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -1,7 +1,10 @@ import { FetchFn } from "../types"; // eslint-disable-next-line // @ts-ignore since undici is an optional dependency and could me missing -import type { RequestInfo, RequestInit } from "undici"; +import type { + RequestInfo as UndiciRequestInfo, + RequestInit as UndiciRequestInit, +} from "undici"; export const resolveFetchFn = async ( customFetch?: FetchFn @@ -15,9 +18,12 @@ export const resolveFetchFn = async ( const { fetch: undiciFetch, Agent } = await import("undici"); const undiciAgent = new Agent({ allowH2: true, connections: 1 }); - return ((input: RequestInfo, init?: RequestInit) => + return ((input: UndiciRequestInfo, init?: UndiciRequestInit) => undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; } catch { - return fetch; + const httpsModule = await import("https"); + const agent = new httpsModule.Agent({ maxSockets: 1 }); + return (input: RequestInfo, init?: RequestInit) => + fetch(input, { ...init, agent } as RequestInit & { agent: typeof agent }); } }; From 451fabe1095236f08b709944a4df13c9586c1f52 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 23:49:24 +0300 Subject: [PATCH 104/124] Update resolveFetchFn.ts --- src/orkes/helpers/resolveFetchFn.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index af05ecd5..38651a00 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -21,9 +21,15 @@ export const resolveFetchFn = async ( return ((input: UndiciRequestInfo, init?: UndiciRequestInit) => undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; } catch { - const httpsModule = await import("https"); - const agent = new httpsModule.Agent({ maxSockets: 1 }); - return (input: RequestInfo, init?: RequestInit) => - fetch(input, { ...init, agent } as RequestInit & { agent: typeof agent }); + try { + const httpsModule = await import("https"); + const agent = new httpsModule.Agent({ maxSockets: 1 }); + return (input: RequestInfo, init?: RequestInit) => + fetch(input, { ...init, agent } as RequestInit & { + agent: typeof agent; + }); + } catch { + return fetch; + } } }; From 25b20924af961fffdde40228f11ff432715d0509 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 25 Sep 2025 23:57:06 +0300 Subject: [PATCH 105/124] remove node18 --- .github/workflows/pull_request.yml | 2 +- src/orkes/helpers/resolveFetchFn.ts | 11 +---------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 1f4a65dc..81069060 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -23,7 +23,7 @@ jobs: fail-fast: false max-parallel: 1 matrix: - node-version: [18, 20, 22] + node-version: [20, 22, 24] test: ["unit", "integration:v5", "integration:v4"] name: Node.js v${{ matrix.node-version }} - ${{ matrix.test }} tests steps: diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index 38651a00..ac4f1b81 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -21,15 +21,6 @@ export const resolveFetchFn = async ( return ((input: UndiciRequestInfo, init?: UndiciRequestInit) => undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; } catch { - try { - const httpsModule = await import("https"); - const agent = new httpsModule.Agent({ maxSockets: 1 }); - return (input: RequestInfo, init?: RequestInit) => - fetch(input, { ...init, agent } as RequestInit & { - agent: typeof agent; - }); - } catch { - return fetch; - } + return fetch; } }; From f001ae77bff40fddd72942f6d4a12a145b531573 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 26 Sep 2025 00:04:17 +0300 Subject: [PATCH 106/124] Update resolveFetchFn.ts --- src/orkes/helpers/resolveFetchFn.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index ac4f1b81..0f5b348b 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -20,7 +20,7 @@ export const resolveFetchFn = async ( return ((input: UndiciRequestInfo, init?: UndiciRequestInit) => undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; - } catch { - return fetch; + } catch { + throw new Error("failed to import undici"); } }; From 45526bf01595f41fe2a58299f79a056e79f7fe2b Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 26 Sep 2025 00:27:42 +0300 Subject: [PATCH 107/124] update jest config --- jest.config.mjs | 10 ++++++++++ src/orkes/helpers/resolveFetchFn.ts | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/jest.config.mjs b/jest.config.mjs index 1c06294f..cd5d205b 100644 --- a/jest.config.mjs +++ b/jest.config.mjs @@ -5,4 +5,14 @@ export default { clearMocks: true, coverageProvider: "v8", transformIgnorePatterns: ["/node_modules/", "\\.pnp\\.[^\\/]+$"], + transform: { + "^.+\\.tsx?$": [ + "ts-jest", + { + tsconfig: { + module: "commonjs", + }, + }, + ], + }, }; diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index 0f5b348b..ac4f1b81 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -20,7 +20,7 @@ export const resolveFetchFn = async ( return ((input: UndiciRequestInfo, init?: UndiciRequestInit) => undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; - } catch { - throw new Error("failed to import undici"); + } catch { + return fetch; } }; From a4898c411cd5fea46b8c52b60c66689859f9312c Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 26 Sep 2025 00:58:53 +0300 Subject: [PATCH 108/124] fix worker example test, remove LoadTest --- integration-tests/common/LoadTest.test.ts | 84 ------------------- .../common/TaskRunnerIntTest.test.ts | 3 +- 2 files changed, 2 insertions(+), 85 deletions(-) delete mode 100644 integration-tests/common/LoadTest.test.ts diff --git a/integration-tests/common/LoadTest.test.ts b/integration-tests/common/LoadTest.test.ts deleted file mode 100644 index 2ec6f115..00000000 --- a/integration-tests/common/LoadTest.test.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { describe, test, expect, jest } from "@jest/globals"; -import { orkesConductorClient } from "../../src/orkes"; -import { WorkflowExecutor } from "../../src/core"; -import { TaskType } from "../../src/common"; - -const CONCURRENT_REQUESTS = 500; -const TEST_TIMEOUT = 180000 * 10; // 180 seconds - -describe("Load Test for ECONNRESET", () => { - jest.setTimeout(TEST_TIMEOUT); - - test(`should handle ${CONCURRENT_REQUESTS} staggered GET requests (1 every 0ms) without ECONNRESET`, async () => { - const client = await orkesConductorClient(); - const executor = new WorkflowExecutor(client); - - // To ensure we are making valid API calls, we first create a simple - // workflow and start one execution. We will then query this execution's status. - const workflowName = "load_test_workflow"; - await executor.registerWorkflow(true, { - name: workflowName, - version: 1, - tasks: [ - { - name: "simple_task", - taskReferenceName: "simple_task_ref", - type: TaskType.SIMPLE, - }, - ], - timeoutSeconds: 0, - inputParameters: [], - }); - const executionId = await executor.startWorkflow({ - name: workflowName, - version: 1, - }); - - console.log( - `Starting load test with workflow execution ID: ${executionId}` - ); - console.log( - `Sending ${CONCURRENT_REQUESTS} staggered requests (1 every 0ms)...` - ); - - const requestPromises: Promise[] = []; - for (let i = 0; i < CONCURRENT_REQUESTS; i++) { - requestPromises.push(executor.getWorkflow(executionId, false)); - } - - const results = await Promise.allSettled(requestPromises); - - let successCount = 0; - const errors: any[] = []; - - results.forEach((result, index) => { - if (result.status === "fulfilled") { - successCount++; - } else { - const reason = result.reason; - - errors.push({ requestIndex: index, reason }); - } - }); - - console.log("--- Load Test Results ---"); - console.log( - `Successful Requests: ${successCount} / ${CONCURRENT_REQUESTS}` - ); - console.log(`Failures: ${errors.length}`); - console.log("-------------------------"); - - if (errors.length > 0) { - console.error(`\n--- Errors (${errors.length}) ---`); - for (const error of errors) { - console.error( - `Request Index ${error.requestIndex} failed. Reason:`, - error.reason - ); - } - console.error("--------------------------\n"); - } - - expect(errors.length).toBe(0); - }); -}); diff --git a/integration-tests/common/TaskRunnerIntTest.test.ts b/integration-tests/common/TaskRunnerIntTest.test.ts index 9eadb449..6aff533b 100644 --- a/integration-tests/common/TaskRunnerIntTest.test.ts +++ b/integration-tests/common/TaskRunnerIntTest.test.ts @@ -2,6 +2,7 @@ import { expect, describe, test, jest } from "@jest/globals"; import { TaskRunner } from "../../src/task/TaskRunner"; import { WorkflowExecutor, simpleTask } from "../../src/core"; import { orkesConductorClient } from "../../src/orkes"; +import { TestUtil } from "../utils/test-util"; describe("TaskManager", () => { const clientPromise = orkesConductorClient(); @@ -58,7 +59,7 @@ describe("TaskManager", () => { taskRunner.updateOptions({ concurrency: 1, pollInterval: 100 }); - const workflowStatus = await executor.getWorkflow(executionId!, true); + const workflowStatus = await TestUtil.waitForWorkflowStatus(executor, executionId!, "COMPLETED"); const [firstTask] = workflowStatus.tasks || []; expect(firstTask?.taskType).toEqual("task-manager-int-test"); From 6ec44ed65dc4d0f40283bd59036385f320b580b8 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 26 Sep 2025 01:01:21 +0300 Subject: [PATCH 109/124] adjust integration tests workflow wait timing --- integration-tests/utils/test-util.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/utils/test-util.ts b/integration-tests/utils/test-util.ts index f6246e52..9b237e6f 100644 --- a/integration-tests/utils/test-util.ts +++ b/integration-tests/utils/test-util.ts @@ -88,8 +88,8 @@ export class TestUtil { workflowClient: any, workflowId: string, expectedStatus: string, - maxWaitTimeMs: number = 5000, - pollIntervalMs: number = 100 + maxWaitTimeMs: number = 15000, + pollIntervalMs: number = 1000 ): Promise { const startTime = Date.now(); From e91c26ffbc844be298ed87be21948fec7d44fb0b Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 26 Sep 2025 01:15:08 +0300 Subject: [PATCH 110/124] remove max-parallel --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 81069060..ca908ea2 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest strategy: fail-fast: false - max-parallel: 1 + # max-parallel: 1 matrix: node-version: [20, 22, 24] test: ["unit", "integration:v5", "integration:v4"] From 55d645a2fef3a71142faa2593c6c8836011ad278 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 26 Sep 2025 03:32:19 +0300 Subject: [PATCH 111/124] update tests to allow them running in parallel on the same cluster --- .../common/EventResourceService.test.ts | 4 +- .../common/MetadataClient.test.ts | 10 ++-- integration-tests/common/TaskManager.test.ts | 58 +++++++++++-------- .../common/TaskRunnerIntTest.test.ts | 12 ++-- .../common/WorkflowResourceService.test.ts | 2 +- integration-tests/common/executor.test.ts | 20 ++++--- integration-tests/common/readme.test.ts | 27 +++++---- .../common/schedulerExecutor.test.ts | 7 ++- integration-tests/utils/test-util.ts | 5 +- .../v5-only/ServiceRegistryClient.test.ts | 10 ++-- integration-tests/v5-only/executor.test.ts | 23 +++++--- .../metadata/complex_wf_signal_test.json | 0 .../complex_wf_signal_test_subworkflow_1.json | 0 .../complex_wf_signal_test_subworkflow_2.json | 0 .../metadata/wait_signal_test.json | 0 15 files changed, 103 insertions(+), 75 deletions(-) rename integration-tests/{common => v5-only}/metadata/complex_wf_signal_test.json (100%) rename integration-tests/{common => v5-only}/metadata/complex_wf_signal_test_subworkflow_1.json (100%) rename integration-tests/{common => v5-only}/metadata/complex_wf_signal_test_subworkflow_2.json (100%) rename integration-tests/{common => v5-only}/metadata/wait_signal_test.json (100%) diff --git a/integration-tests/common/EventResourceService.test.ts b/integration-tests/common/EventResourceService.test.ts index 4968b9ba..ed9ebd0c 100644 --- a/integration-tests/common/EventResourceService.test.ts +++ b/integration-tests/common/EventResourceService.test.ts @@ -7,8 +7,8 @@ describe("EventResourceService", () => { const eventApi = orkesClient.eventResource; const [eventName, event, eventDescription, eventTagKey, eventTagValue] = [ - "jsSdkTestEventName", - "jsSdkTest:eventHandler:1", + `jsSdkTest-EventName-${Date.now()}`, + `jsSdkTest:eventHandler:1${Date.now()}`, "jsSdkTestDescription", "jsSdkTestTagKey", "jsSdkTestTagValue", diff --git a/integration-tests/common/MetadataClient.test.ts b/integration-tests/common/MetadataClient.test.ts index f0b5543c..02ff50d8 100644 --- a/integration-tests/common/MetadataClient.test.ts +++ b/integration-tests/common/MetadataClient.test.ts @@ -5,6 +5,7 @@ import { orkesConductorClient } from "../../src/orkes"; describe("MetadataClient", () => { const clientPromise = orkesConductorClient(); + const taskName = `jsSdkTest-test_task_definition-${Date.now()}`; jest.setTimeout(15000); test("Should register a task definition", async () => { @@ -12,7 +13,7 @@ describe("MetadataClient", () => { const metadataClient = new MetadataClient(client); const newTaskDefinition = taskDefinition({ - name: "test_task_definition", + name: taskName, description: "New Task Definition", retryCount: 4, timeoutSeconds: 7200, @@ -62,7 +63,7 @@ describe("MetadataClient", () => { const metadataClient = new MetadataClient(client); const newTaskDefinition = taskDefinition({ - name: "test_task_definition", + name: taskName, description: "New Task Definition Update", retryCount: 5, timeoutSeconds: 7201, @@ -110,14 +111,13 @@ describe("MetadataClient", () => { test("Should unregister a task definition", async () => { const client = await clientPromise; const metadataClient = new MetadataClient(client); - const name ="test_task_definition"; await expect( - metadataClient.unregisterTask("test_task_definition") + metadataClient.unregisterTask(taskName) ).resolves.not.toThrow(); await expect(client.metadataResource.getTaskDef( - name + taskName )).rejects.toThrow(); }) }); diff --git a/integration-tests/common/TaskManager.test.ts b/integration-tests/common/TaskManager.test.ts index 4b2ba116..f1faf7c2 100644 --- a/integration-tests/common/TaskManager.test.ts +++ b/integration-tests/common/TaskManager.test.ts @@ -15,9 +15,11 @@ describe("TaskManager", () => { test("Should run workflow with worker", async () => { const client = await clientPromise; const executor = new WorkflowExecutor(client); + const taskName = `jsSdkTest-taskmanager-test-${Date.now()}`; + const workflowName = `jsSdkTest-taskmanager-test-wf-${Date.now()}`; const worker: ConductorWorker = { - taskDefName: "taskmanager-test", + taskDefName: taskName, execute: async () => { return { outputData: { @@ -34,17 +36,17 @@ describe("TaskManager", () => { manager.startPolling(); await executor.registerWorkflow(true, { - name: "TaskManagerTest", + name: workflowName, version: 1, ownerEmail: "developers@orkes.io", - tasks: [simpleTask("taskmanager-test", "taskmanager-test", {})], + tasks: [simpleTask(taskName, taskName, {})], inputParameters: [], outputParameters: {}, timeoutSeconds: 0, }); const executionId = await executor.startWorkflow({ - name: "TaskManagerTest", + name: workflowName, input: {}, version: 1, }); @@ -59,18 +61,20 @@ describe("TaskManager", () => { test("On error it should call the errorHandler provided", async () => { const client = await clientPromise; const executor = new WorkflowExecutor(client); + const taskName = `jsSdkTest-taskmanager-error-handler-test-${Date.now()}`; + const workflowName = `jsSdkTest-taskmanager-error-handler-test-wf-${Date.now()}`; const mockErrorHandler = jest.fn(); const worker: ConductorWorker = { - taskDefName: "taskmanager-error-handler-test-unique", + taskDefName: taskName, execute: async () => { throw new Error("This is a forced error for testing error handler"); }, }; await client.metadataResource.registerTaskDef([taskDefinition({ - name: "taskmanager-error-handler-test-unique", + name: taskName, timeoutSeconds: 0, retryCount: 0, })]); @@ -83,20 +87,20 @@ describe("TaskManager", () => { manager.startPolling(); await executor.registerWorkflow(true, { - name: "TaskManagerTestErrorHandlerUnique", + name: workflowName, version: 1, ownerEmail: "developers@orkes.io", - tasks: [simpleTask("taskmanager-error-handler-test-unique", "taskmanager-error-handler-test-unique", {})], + tasks: [simpleTask(taskName, taskName, {})], inputParameters: [], outputParameters: {}, timeoutSeconds: 0, }); const status = await executor.startWorkflow({ - name: "TaskManagerTestErrorHandlerUnique", + name: workflowName, input: {}, version: 1, - correlationId: "errorHandlerTestIdentifierUnique" + correlationId: `${workflowName}-id` }); const workflowStatus = await TestUtil.waitForWorkflowCompletion(executor, status, BASE_TIME * 30); @@ -109,16 +113,18 @@ describe("TaskManager", () => { test("If no error handler provided. it should just update the task", async () => { const client = await clientPromise; const executor = new WorkflowExecutor(client); + const taskName = `jsSdkTest-taskmanager-error-test-${Date.now()}`; + const workflowName = `jsSdkTest-taskmanager-error-test-wf-${Date.now()}`; const worker: ConductorWorker = { - taskDefName: "taskmanager-error-test", + taskDefName: taskName, execute: async () => { throw new Error("This is a forced error"); }, }; await client.metadataResource.registerTaskDef([taskDefinition({ - name: "taskmanager-error-test", + name: taskName, timeoutSeconds: 0, retryCount: 0, })]); @@ -130,20 +136,20 @@ describe("TaskManager", () => { manager.startPolling(); await executor.registerWorkflow(true, { - name: "TaskManagerTestE", + name: workflowName, version: 1, ownerEmail: "developers@orkes.io", - tasks: [simpleTask("taskmanager-error-test", "taskmanager-error-test", {})], + tasks: [simpleTask(taskName, taskName, {})], inputParameters: [], outputParameters: {}, timeoutSeconds: 0, }); const executionId = await executor.startWorkflow({ - name: "TaskManagerTestE", + name: workflowName, input: {}, version: 1, - correlationId: "noErrorHandlerProvidedIdentifier" + correlationId: `${workflowName}-id` }); const workflowStatus = await TestUtil.waitForWorkflowCompletion(executor, executionId!, BASE_TIME * 30); @@ -158,7 +164,7 @@ describe("TaskManager", () => { // just create a bunch of worker names const workerNames: string[] = Array.from({ length: 3 }) .fill(0) - .map((_, i: number) => `taskman-multi-${1 + i}`); + .map((_, i: number) => `jsSdkTest-taskman-multi-${1 + i}-${Date.now()}`); // names to actual workers const workers: ConductorWorker[] = workerNames.map((name) => ({ @@ -183,7 +189,7 @@ describe("TaskManager", () => { expect(manager.isPolling).toBeTruthy(); - const workflowName = "TaskManagerTestMulti"; + const workflowName = `jsSdkTest-taskmanager-multi-test-wf-${Date.now()}`; // increase polling speed manager.updatePollingOptions({ concurrency: 4 }); @@ -203,7 +209,7 @@ describe("TaskManager", () => { const executionId = await executor.startWorkflow({ name: workflowName, version: 1, - correlationId: "identifierTaskManMulti" + correlationId: `${workflowName}-id` }); expect(executionId).toBeDefined(); @@ -233,10 +239,11 @@ describe("TaskManager", () => { test("Should not be able to startPolling if duplicate workers", async () => { const client = await clientPromise; + const workerName = `jsSdkTest-worker-name-${Date.now()}`; const workerNames: string[] = Array.from({ length: 3 }) .fill(0) - .map(() => `worker-name`); + .map(() => workerName); // names to actual workers const workers: ConductorWorker[] = workerNames.map((name) => ({ @@ -255,7 +262,7 @@ describe("TaskManager", () => { options: { pollInterval: BASE_TIME, concurrency: 2 }, }); expect(() => manager.startPolling()).toThrow( - "Duplicate worker taskDefName: worker-name" + `Duplicate worker taskDefName: ${workerName}` ); }); @@ -263,12 +270,13 @@ describe("TaskManager", () => { const client = await clientPromise; const executor = new WorkflowExecutor(client); + const workerName = `jsSdkTest-taskman-single-worker-update-${Date.now()}`; // just create a bunch of worker names const workerNames: string[] = Array.from({ length: 3 }) .fill(0) - .map((_, i: number) => `taskman-single-worker-update${1 + i}`); + .map((_, i: number) => `${workerName}-${1 + i}`); - const candidateWorkerUpdate = "taskman-single-worker-update1"; + const candidateWorkerUpdate = `${workerName}-1`; const initialCandidateWorkflowOptions = { concurrency: 1, pollInterval: BASE_TIME * 3, @@ -300,7 +308,7 @@ describe("TaskManager", () => { expect(manager.isPolling).toBeTruthy(); - const workflowName = "TaskManagerTestMultiSingleWorkerUpdate"; + const workflowName = `jsSdkTest-taskmanager-multi-single-worker-update-wf-${Date.now()}`; const updatedWorkerOptions = { concurrency: 3, @@ -328,7 +336,7 @@ describe("TaskManager", () => { const executionId = await executor.startWorkflow({ name: workflowName, version: 1, - correlationId: "identifierTaskManMulti" + correlationId: `${workflowName}-id` }); expect(executionId).toBeDefined(); diff --git a/integration-tests/common/TaskRunnerIntTest.test.ts b/integration-tests/common/TaskRunnerIntTest.test.ts index 6aff533b..52cb298a 100644 --- a/integration-tests/common/TaskRunnerIntTest.test.ts +++ b/integration-tests/common/TaskRunnerIntTest.test.ts @@ -11,11 +11,13 @@ describe("TaskManager", () => { test("worker example ", async () => { const client = await clientPromise; const executor = new WorkflowExecutor(client); + const taskName = `jsSdkTest-task-manager-int-test-${Date.now()}`; + const workflowName = `jsSdkTest-task-manager-int-test-wf-${Date.now()}`; const taskRunner = new TaskRunner({ taskResource: client.taskResource, worker: { - taskDefName: "task-manager-int-test", + taskDefName: taskName, execute: async () => { return { outputData: { @@ -35,12 +37,12 @@ describe("TaskManager", () => { taskRunner.startPolling(); expect(taskRunner.isPolling).toEqual(true); - const workflowName = "task-manager-int-test-wf"; + await executor.registerWorkflow(true, { name: workflowName, version: 1, ownerEmail: "developers@orkes.io", - tasks: [simpleTask("task-manager-int-test", "task-manager-int-test", {})], + tasks: [simpleTask(taskName, taskName, {})], inputParameters: [], outputParameters: {}, timeoutSeconds: 0, @@ -53,7 +55,7 @@ describe("TaskManager", () => { }, workflowName, 1, - "RunnerIdentifier" + `${workflowName}-id` ); expect(executionId).toBeDefined(); @@ -62,7 +64,7 @@ describe("TaskManager", () => { const workflowStatus = await TestUtil.waitForWorkflowStatus(executor, executionId!, "COMPLETED"); const [firstTask] = workflowStatus.tasks || []; - expect(firstTask?.taskType).toEqual("task-manager-int-test"); + expect(firstTask?.taskType).toEqual(taskName); expect(workflowStatus.status).toEqual("COMPLETED"); await taskRunner.stopPolling(); diff --git a/integration-tests/common/WorkflowResourceService.test.ts b/integration-tests/common/WorkflowResourceService.test.ts index a9835086..d0d28190 100644 --- a/integration-tests/common/WorkflowResourceService.test.ts +++ b/integration-tests/common/WorkflowResourceService.test.ts @@ -14,7 +14,7 @@ describe("WorkflowResourceService", () => { simpleTask("simple_ref", "le_simple_task", {}), ]; - const wfDef = workflow("unit_test_wf", tasks); + const wfDef = workflow(`jsSdkTest-test_wf-${Date.now()}`, tasks); wfDef.outputParameters = { message: "${simple_ref.output.message}" }; metadataClient.registerWorkflowDef(wfDef, true); diff --git a/integration-tests/common/executor.test.ts b/integration-tests/common/executor.test.ts index 55f72541..ba1b3b0d 100644 --- a/integration-tests/common/executor.test.ts +++ b/integration-tests/common/executor.test.ts @@ -11,7 +11,7 @@ describe("Executor", () => { const clientPromise = orkesConductorClient(); jest.setTimeout(15000); - const name = `testWorkflow-${Date.now()}`; + const name = `jsSdkTest-Workflow-${Date.now()}`; const version = 1; test("Should be able to register a workflow", async () => { const client = await clientPromise; @@ -114,19 +114,21 @@ describe("Executor", () => { test("Should run workflow with http task with asyncComplete true", async () => { const client = await clientPromise; const executor = new WorkflowExecutor(client); + const workflowName = `jsSdkTest-wf_with_asyncComplete_http_task-${Date.now()}`; + const taskName = `jsSdkTest-http_task_with_asyncComplete_true-${Date.now()}`; await executor.registerWorkflow(true, { - name: "test_jssdk_workflow_with_http_task_with_asyncComplete_true", + name: workflowName, version: 1, ownerEmail: "developers@orkes.io", - tasks: [httpTask("test_jssdk_http_task_with_asyncComplete_true", { uri: "http://www.yahoo.com", method: "GET" }, true)], + tasks: [httpTask(taskName, { uri: "http://www.yahoo.com", method: "GET" }, true)], inputParameters: [], outputParameters: {}, timeoutSeconds: 300, }); const executionId = await executor.startWorkflow({ - name: "test_jssdk_workflow_with_http_task_with_asyncComplete_true", + name: workflowName, input: {}, version: 1, }); @@ -136,7 +138,7 @@ describe("Executor", () => { expect(["IN_PROGRESS", "SCHEDULED"]).toContain(workflowStatusBefore.tasks?.[0]?.status); const taskClient = new TaskClient(client); - taskClient.updateTaskResult(executionId, "test_jssdk_http_task_with_asyncComplete_true", "COMPLETED", { hello: "From manuall api call updating task result" }); + taskClient.updateTaskResult(executionId, taskName, "COMPLETED", { hello: "From manuall api call updating task result" }); const workflowStatusAfter = await TestUtil.waitForWorkflowStatus(executor, executionId, "COMPLETED"); @@ -145,19 +147,21 @@ describe("Executor", () => { test("Should run workflow with an optional http task", async () => { const executor = new WorkflowExecutor(await clientPromise); + const workflowName = `jsSdkTest-wf_with_optional_http_task-${Date.now()}`; + const taskName = `jsSdkTest-optional_http_task-${Date.now()}`; await executor.registerWorkflow(true, { - name: "test_jssdk_workflow_with_optional_http_task", + name: workflowName, version: 1, ownerEmail: "developers@orkes.io", - tasks: [httpTask("test_jssdk_optional_http_task", { uri: "uncorrect_uri", method: "GET" }, false, true)], + tasks: [httpTask(taskName, { uri: "uncorrect_uri", method: "GET" }, false, true)], inputParameters: [], outputParameters: {}, timeoutSeconds: 300, }); const executionId = await executor.startWorkflow({ - name: "test_jssdk_workflow_with_optional_http_task", + name: workflowName, input: {}, version: 1, }); diff --git a/integration-tests/common/readme.test.ts b/integration-tests/common/readme.test.ts index e8a73621..59dd284b 100644 --- a/integration-tests/common/readme.test.ts +++ b/integration-tests/common/readme.test.ts @@ -11,11 +11,13 @@ describe("TaskManager", () => { test("worker example ", async () => { const client = await clientPromise; const executor = new WorkflowExecutor(client); + const workflowName = `jsSdkTest-my_first_js_wf-${Date.now()}`; + const taskName = `jsSdkTest-taskmanager-test-${Date.now()}`; const taskRunner = new TaskRunner({ taskResource: client.taskResource, worker: { - taskDefName: "taskmanager-test", + taskDefName: taskName, execute: async () => { return { outputData: { @@ -34,18 +36,19 @@ describe("TaskManager", () => { }); taskRunner.startPolling(); + await executor.registerWorkflow(true, { - name: "my_first_js_wf", + name: workflowName, version: 1, ownerEmail: "developers@orkes.io", - tasks: [simpleTask("taskmanager-test", "taskmanager-test", {})], + tasks: [simpleTask(taskName, taskName, {})], inputParameters: [], outputParameters: {}, timeoutSeconds: 0, }); const executionId = await executor.startWorkflow({ - name: "my_first_js_wf", + name: workflowName, input: {}, version: 1, }); @@ -53,7 +56,7 @@ describe("TaskManager", () => { const workflowStatus = await executor.getWorkflow(executionId, true); const [firstTask] = workflowStatus.tasks || []; - expect(firstTask?.taskType).toEqual("taskmanager-test"); + expect(firstTask?.taskType).toEqual(taskName); expect(workflowStatus.status).toEqual("COMPLETED"); taskRunner.stopPolling(); @@ -64,9 +67,9 @@ describe("TaskManager", () => { test("update task example ", async () => { const client = await clientPromise; const executor = new WorkflowExecutor(client); - const waitTaskReference = "wait_task_ref"; + const waitTaskReference = `jsSdkTest-wait_task_ref-${Date.now()}`; const workflowWithWaitTask = generate({ - name: "waitTaskWf", + name: `jsSdkTest-waitTaskWf-${Date.now()}`, tasks: [{ type: TaskType.WAIT, taskReferenceName: waitTaskReference }], }); await executor.registerWorkflow(true, workflowWithWaitTask); @@ -113,13 +116,15 @@ describe("TaskManager", () => { //Create new workflow executor const executor = new WorkflowExecutor(client); + const taskName = `jsSdkTest-sum_two_numbers-task-${Date.now()}`; + const workflowName = `jsSdkTest-sumTwoNumbersWf-${Date.now()}`; // Create a workflow const sumTwoNumbers = generate({ - name: "sumTwoNumbers", + name: workflowName, tasks: [ { - name: "sum_two_numbers", + name: taskName, inputParameters: { numberOne: "${workflow.input.numberOne}", numberTwo: "${workflow.input.numberTwo}", @@ -135,7 +140,7 @@ describe("TaskManager", () => { ], inputParameters: ["numberOne", "numberTwo"], outputParameters: { - result: "${sum_two_numbers_ref.output.result}", + result: `\${${taskName}_ref.output.result}`, }, }); @@ -153,7 +158,7 @@ describe("TaskManager", () => { }, sumTwoNumbers.name, 1, - "workflowSummTwoNumbers" + `workflow${sumTwoNumbers.name}` ); const workflowStatus = await executor.getWorkflow(executionId!, true); diff --git a/integration-tests/common/schedulerExecutor.test.ts b/integration-tests/common/schedulerExecutor.test.ts index d25c9549..0ef2996d 100644 --- a/integration-tests/common/schedulerExecutor.test.ts +++ b/integration-tests/common/schedulerExecutor.test.ts @@ -7,10 +7,11 @@ describe("ScheduleExecutor", () => { const clientPromise = orkesConductorClient(); jest.setTimeout(15000); - const name = `testSchedule_${Date.now()}`; + const now = Date.now(); + const name = `jsSdkTestSchedule_${now}`; const cronExpression = "0/5 * * ? * *"; //every 5 second - const workflowName = `testScheduleWf_${Date.now()}`; + const workflowName = `jsSdkTestScheduleWf_${now}`; const workflowVersion = 1; test("Should be able to register a workflow and retrieve it", async () => { @@ -115,7 +116,7 @@ describe("ScheduleExecutor", () => { }); test("Should be able to retrieve next (default 3) execution times for a scheduler", async () => { - const cronExpression = "0 0 * ? * *"; //every hour + const cronExpression = "0 0 * * * *"; //every hour const client = await clientPromise; const executor = new SchedulerClient(client); const result = await executor.getNextFewSchedules(cronExpression); diff --git a/integration-tests/utils/test-util.ts b/integration-tests/utils/test-util.ts index 9b237e6f..65a77b06 100644 --- a/integration-tests/utils/test-util.ts +++ b/integration-tests/utils/test-util.ts @@ -26,9 +26,10 @@ export class TestUtil { /** * Register a single workflow from JSON file */ - public static async registerWorkflow(workflowName: string): Promise { + public static async registerWorkflow(workflowName: string, workflowJsonFilePath: string): Promise { try { - const workflowDef = this.getWorkflowDef(`../common/metadata/${workflowName}.json`); + const workflowDef = this.getWorkflowDef(workflowJsonFilePath); + workflowDef.name = workflowName; await this.metadataClient.registerWorkflowDef(workflowDef, true); console.log(`✓ Registered workflow: ${workflowName}`); } catch (error) { diff --git a/integration-tests/v5-only/ServiceRegistryClient.test.ts b/integration-tests/v5-only/ServiceRegistryClient.test.ts index b25cf2f8..caab62fb 100644 --- a/integration-tests/v5-only/ServiceRegistryClient.test.ts +++ b/integration-tests/v5-only/ServiceRegistryClient.test.ts @@ -33,7 +33,7 @@ describe("ServiceRegistryClient", () => { test("Should add and retrieve a service registry", async () => { // Create a test service registry const testServiceRegistry = { - name: "test_service_registry", + name: `jsSdkTest-test_service_registry${Date.now()}`, type: ServiceType.HTTP, serviceURI: "http://httpbin:8081/api-docs", config: { @@ -87,7 +87,7 @@ describe("ServiceRegistryClient", () => { test("Should add and remove a service registry", async () => { // Create a test service registry const testServiceRegistry = { - name: "test_service_registry_to_remove", + name: `jsSdkTest-test_service_registry_to_remove-${Date.now()}`, type: ServiceType.HTTP, serviceURI: "http://httpbin:8081/api-docs" }; @@ -119,7 +119,7 @@ describe("ServiceRegistryClient", () => { test("Should add a service method to a registry", async () => { // Create a test service registry const testServiceRegistry = { - name: "test_service_registry_with_method", + name: `jsSdkTest-test_service_registry_with_method-${Date.now()}`, type: ServiceType.HTTP, serviceURI: "http://httpbin:8081/api-docs" }; @@ -173,7 +173,7 @@ describe("ServiceRegistryClient", () => { test("Should discover methods from a http service", async () => { // Create a test service registry for discovery const testServiceRegistry = { - name: "test_service_registry_discovery", + name: `jsSdkTest-test_service_registry_discovery-${Date.now()}`, type: ServiceType.HTTP, serviceURI: "http://httpbin:8081/api-docs" }; @@ -206,7 +206,7 @@ describe("ServiceRegistryClient", () => { test("Should discover methods from a gRPC service", async () => { // Create a test service registry for discovery const testServiceRegistry = { - name: "test_gRPC_service_registry_discovery", + name: `jsSdkTest-test_gRPC_service_registry_discovery-${Date.now()}`, type: ServiceType.gRPC, serviceURI: "grpcbin:50051" }; diff --git a/integration-tests/v5-only/executor.test.ts b/integration-tests/v5-only/executor.test.ts index 5cb72b5d..79417d92 100644 --- a/integration-tests/v5-only/executor.test.ts +++ b/integration-tests/v5-only/executor.test.ts @@ -11,10 +11,17 @@ import {SignalResponse} from "../../src/common/open-api/models/SignalResponse"; describe("Execute with Return Strategy and Consistency", () => { // Constants specific to this test suite const WORKFLOW_NAMES = { - COMPLEX_WF: 'complex_wf_signal_test', - SUB_WF_1: 'complex_wf_signal_test_subworkflow_1', - SUB_WF_2: 'complex_wf_signal_test_subworkflow_2', - WAIT_SIGNAL_TEST: 'wait_signal_test' + COMPLEX_WF: `jsSdkTest-Complex_wf_signal_test-${Date.now()}`, + SUB_WF_1: `jsSdkTest-Complex_wf_signal_test_subworkflow_1-${Date.now()}`, + SUB_WF_2: `jsSdkTest-Complex_wf_signal_test_subworkflow_2-${Date.now()}`, + WAIT_SIGNAL_TEST: `jsSdkTest-Wait_signal_test-${Date.now()}` + }; + + const WORKFLOW_JSON_FILE_PATHS = { + COMPLEX_WF: `../v5-only/metadata/complex_wf_signal_test.json`, + SUB_WF_1: `../v5-only/metadata/complex_wf_signal_test_subworkflow_1.json`, + SUB_WF_2: `../v5-only/metadata/complex_wf_signal_test_subworkflow_2.json`, + WAIT_SIGNAL_TEST: `../v5-only/metadata/wait_signal_test.json` }; const clientPromise = orkesConductorClient(); @@ -63,10 +70,10 @@ describe("Execute with Return Strategy and Consistency", () => { async function registerAllWorkflows(): Promise { try { await Promise.all([ - TestUtil.registerWorkflow(WORKFLOW_NAMES.COMPLEX_WF), - TestUtil.registerWorkflow(WORKFLOW_NAMES.SUB_WF_1), - TestUtil.registerWorkflow(WORKFLOW_NAMES.SUB_WF_2), - TestUtil.registerWorkflow(WORKFLOW_NAMES.WAIT_SIGNAL_TEST) + TestUtil.registerWorkflow(WORKFLOW_NAMES.COMPLEX_WF, WORKFLOW_JSON_FILE_PATHS.COMPLEX_WF), + TestUtil.registerWorkflow(WORKFLOW_NAMES.SUB_WF_1, WORKFLOW_JSON_FILE_PATHS.SUB_WF_1), + TestUtil.registerWorkflow(WORKFLOW_NAMES.SUB_WF_2, WORKFLOW_JSON_FILE_PATHS.SUB_WF_2), + TestUtil.registerWorkflow(WORKFLOW_NAMES.WAIT_SIGNAL_TEST, WORKFLOW_JSON_FILE_PATHS.WAIT_SIGNAL_TEST) ]); // Add to cleanup list diff --git a/integration-tests/common/metadata/complex_wf_signal_test.json b/integration-tests/v5-only/metadata/complex_wf_signal_test.json similarity index 100% rename from integration-tests/common/metadata/complex_wf_signal_test.json rename to integration-tests/v5-only/metadata/complex_wf_signal_test.json diff --git a/integration-tests/common/metadata/complex_wf_signal_test_subworkflow_1.json b/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.json similarity index 100% rename from integration-tests/common/metadata/complex_wf_signal_test_subworkflow_1.json rename to integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.json diff --git a/integration-tests/common/metadata/complex_wf_signal_test_subworkflow_2.json b/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.json similarity index 100% rename from integration-tests/common/metadata/complex_wf_signal_test_subworkflow_2.json rename to integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.json diff --git a/integration-tests/common/metadata/wait_signal_test.json b/integration-tests/v5-only/metadata/wait_signal_test.json similarity index 100% rename from integration-tests/common/metadata/wait_signal_test.json rename to integration-tests/v5-only/metadata/wait_signal_test.json From 6210209806bcb48ad75dc60d9f7aaa9ae15e4660 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 26 Sep 2025 03:40:55 +0300 Subject: [PATCH 112/124] fix test "update task example" --- integration-tests/common/readme.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/readme.test.ts b/integration-tests/common/readme.test.ts index 59dd284b..1b8764d7 100644 --- a/integration-tests/common/readme.test.ts +++ b/integration-tests/common/readme.test.ts @@ -82,7 +82,7 @@ describe("TaskManager", () => { }, workflowWithWaitTask.name, 1, - "someId" + `${workflowWithWaitTask.name}-id` ); const workflowStatus = await executor.getWorkflow(executionId!, true); From fde587f31c0fe2ad749a3f8436ae771e340d7da2 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 26 Sep 2025 12:26:17 +0300 Subject: [PATCH 113/124] simplify test package.json scripts --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 027cf57e..46def077 100644 --- a/package.json +++ b/package.json @@ -46,9 +46,9 @@ "lint": "npx eslint .", "lint-fix": "npx eslint . --fix", "test": "jest --force-exit --detectOpenHandles", - "test:unit": "jest --testMatch='**/src/**/__tests__/**/*.test.[jt]s?(x)' --force-exit", - "test:integration:v5": "jest --testMatch='**/integration-tests/{common,v5-only}/**/*.test.[jt]s?(x)' --force-exit --detectOpenHandles", - "test:integration:v4": "jest --testMatch='**/integration-tests/common/**/*.test.[jt]s?(x)' --force-exit --detectOpenHandles", + "test:unit": "npm run test -- --testMatch='**/src/**/__tests__/**/*.test.[jt]s?(x)'", + "test:integration:v5": "npm run test -- --testMatch='**/integration-tests/{common,v5-only}/**/*.test.[jt]s?(x)'", + "test:integration:v4": "npm run test -- --testMatch='**/integration-tests/common/**/*.test.[jt]s?(x)'", "ci": "npm run lint && npm run test", "build": "tsup index.ts", "generateClient:models": "npx openapi-typescript-codegen --input http://localhost:8080/api-docs --output src/common/open-api --client node --indent 2 --name ConductorClient --useUnionTypes --exportCore false", From d79dc4aedd83e2b29040af2517d5a7a1d19fd4ef Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 26 Sep 2025 12:30:55 +0300 Subject: [PATCH 114/124] simplify test package.json scripts --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 46def077..1536f9c5 100644 --- a/package.json +++ b/package.json @@ -46,9 +46,9 @@ "lint": "npx eslint .", "lint-fix": "npx eslint . --fix", "test": "jest --force-exit --detectOpenHandles", - "test:unit": "npm run test -- --testMatch='**/src/**/__tests__/**/*.test.[jt]s?(x)'", - "test:integration:v5": "npm run test -- --testMatch='**/integration-tests/{common,v5-only}/**/*.test.[jt]s?(x)'", - "test:integration:v4": "npm run test -- --testMatch='**/integration-tests/common/**/*.test.[jt]s?(x)'", + "test:unit": "npm test -- --testMatch='**/src/**/__tests__/**/*.test.[jt]s?(x)'", + "test:integration:v5": "npm test -- --testMatch='**/integration-tests/{common,v5-only}/**/*.test.[jt]s?(x)'", + "test:integration:v4": "npm test -- --testMatch='**/integration-tests/common/**/*.test.[jt]s?(x)'", "ci": "npm run lint && npm run test", "build": "tsup index.ts", "generateClient:models": "npx openapi-typescript-codegen --input http://localhost:8080/api-docs --output src/common/open-api --client node --indent 2 --name ConductorClient --useUnionTypes --exportCore false", From 9ecce58402d70e856c6b9e15290f82681212e18d Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Mon, 29 Sep 2025 14:14:20 +0300 Subject: [PATCH 115/124] add ability to change maxHttpConnections via config and env var --- src/orkes/OrkesConductorClient.ts | 7 +++++-- src/orkes/helpers/resolveFetchFn.ts | 5 +++-- src/orkes/helpers/resolveOrkesConfig.ts | 2 ++ src/orkes/types.ts | 1 + 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/orkes/OrkesConductorClient.ts b/src/orkes/OrkesConductorClient.ts index 4d80a901..68d3a9fa 100644 --- a/src/orkes/OrkesConductorClient.ts +++ b/src/orkes/OrkesConductorClient.ts @@ -16,13 +16,16 @@ export const orkesConductorClient = async ( config?: Partial, customFetch?: FetchFn ) => { - const { serverUrl, keyId, keySecret } = resolveOrkesConfig(config); + const { serverUrl, keyId, keySecret, maxHttpConnections } = + resolveOrkesConfig(config); if (!serverUrl) throw new Error("Conductor server URL is not set"); const conductorClientWithAuth = new ConductorClientWithAuth( { ...config, BASE: serverUrl }, - createOrkesHttpRequest(await resolveFetchFn(customFetch)) + createOrkesHttpRequest( + await resolveFetchFn(customFetch, maxHttpConnections) + ) ); if (keyId && keySecret) { diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index ac4f1b81..3f9a4386 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -7,7 +7,8 @@ import type { } from "undici"; export const resolveFetchFn = async ( - customFetch?: FetchFn + customFetch?: FetchFn, + maxHttpConnections: number = 1 ): Promise => { if (customFetch) return customFetch; if (process?.release?.name !== "node") return fetch; @@ -16,7 +17,7 @@ export const resolveFetchFn = async ( // eslint-disable-next-line // @ts-ignore since undici is an optional dependency and could me missing const { fetch: undiciFetch, Agent } = await import("undici"); - const undiciAgent = new Agent({ allowH2: true, connections: 1 }); + const undiciAgent = new Agent({ allowH2: true, connections: maxHttpConnections }); return ((input: UndiciRequestInfo, init?: UndiciRequestInit) => undiciFetch(input, { ...init, dispatcher: undiciAgent })) as FetchFn; diff --git a/src/orkes/helpers/resolveOrkesConfig.ts b/src/orkes/helpers/resolveOrkesConfig.ts index 7f841244..004f9ea2 100644 --- a/src/orkes/helpers/resolveOrkesConfig.ts +++ b/src/orkes/helpers/resolveOrkesConfig.ts @@ -5,5 +5,7 @@ export const resolveOrkesConfig = (config?: Partial) => { serverUrl: process.env.CONDUCTOR_SERVER_URL || config?.serverUrl, keyId: process.env.CONDUCTOR_AUTH_KEY || config?.keyId, keySecret: process.env.CONDUCTOR_AUTH_SECRET || config?.keySecret, + maxHttpConnections: + Number(process.env.CONDUCTOR_MAX_HTTP_CONNECTIONS) || config?.maxHttpConnections, }; }; diff --git a/src/orkes/types.ts b/src/orkes/types.ts index 48b438ab..0a849d69 100644 --- a/src/orkes/types.ts +++ b/src/orkes/types.ts @@ -9,4 +9,5 @@ export interface OrkesApiConfig extends GenerateTokenRequest, OpenAPIConfig { serverUrl: string; refreshTokenInterval: number; useEnvVars?: boolean; // DEPRECATED, has no effect + maxHttpConnections?: number; // max number of simultaneous http connections to the conductor server, defaults to 1 (since we use http2) } From 4f35bfc76de891919f9576b169c26974a815faa0 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Mon, 29 Sep 2025 14:24:53 +0300 Subject: [PATCH 116/124] use waitForWorkflowStatus util in readme.test.ts --- integration-tests/common/readme.test.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/integration-tests/common/readme.test.ts b/integration-tests/common/readme.test.ts index 1b8764d7..dd85e4d8 100644 --- a/integration-tests/common/readme.test.ts +++ b/integration-tests/common/readme.test.ts @@ -3,6 +3,7 @@ import { orkesConductorClient } from "../../src/orkes"; import { WorkflowExecutor, simpleTask, generate } from "../../src/core"; import { TaskType } from "../../src/common"; import { TaskRunner } from "../../src/task"; +import { TestUtil } from "../utils/test-util"; describe("TaskManager", () => { const clientPromise = orkesConductorClient(); @@ -52,8 +53,8 @@ describe("TaskManager", () => { input: {}, version: 1, }); - await new Promise((r) => setTimeout(() => r(true), 900)); - const workflowStatus = await executor.getWorkflow(executionId, true); + + const workflowStatus = await TestUtil.waitForWorkflowStatus(executor, executionId, "COMPLETED"); const [firstTask] = workflowStatus.tasks || []; expect(firstTask?.taskType).toEqual(taskName); @@ -161,7 +162,7 @@ describe("TaskManager", () => { `workflow${sumTwoNumbers.name}` ); - const workflowStatus = await executor.getWorkflow(executionId!, true); + const workflowStatus = await TestUtil.waitForWorkflowStatus(executor, executionId!, "COMPLETED"); expect(workflowStatus.status).toEqual("COMPLETED"); expect(workflowStatus.output?.result).toEqual(3); From 89c861316af9d199d7d85801ee24a286781ab45e Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Mon, 29 Sep 2025 14:31:10 +0300 Subject: [PATCH 117/124] remove comment with max-parallel --- .github/workflows/pull_request.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index ca908ea2..016df57b 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -21,7 +21,6 @@ jobs: runs-on: ubuntu-latest strategy: fail-fast: false - # max-parallel: 1 matrix: node-version: [20, 22, 24] test: ["unit", "integration:v5", "integration:v4"] From 3d61c4f598a7a7fa46def7851b4e77809c2a1bc2 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Mon, 29 Sep 2025 14:49:21 +0300 Subject: [PATCH 118/124] restore cronExpression changes in schedulerExecutor.test.ts --- integration-tests/common/schedulerExecutor.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/common/schedulerExecutor.test.ts b/integration-tests/common/schedulerExecutor.test.ts index 0ef2996d..ccf847d2 100644 --- a/integration-tests/common/schedulerExecutor.test.ts +++ b/integration-tests/common/schedulerExecutor.test.ts @@ -116,7 +116,7 @@ describe("ScheduleExecutor", () => { }); test("Should be able to retrieve next (default 3) execution times for a scheduler", async () => { - const cronExpression = "0 0 * * * *"; //every hour + const cronExpression = "0 0 * ? * *"; //every hour const client = await clientPromise; const executor = new SchedulerClient(client); const result = await executor.getNextFewSchedules(cronExpression); From 7a7a380fad9554f3e24d59d083b82cee9e01936c Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Mon, 29 Sep 2025 14:55:51 +0300 Subject: [PATCH 119/124] renamed maxHttpConnections to maxHttp2Connections --- src/orkes/OrkesConductorClient.ts | 4 ++-- src/orkes/helpers/resolveOrkesConfig.ts | 4 ++-- src/orkes/types.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/orkes/OrkesConductorClient.ts b/src/orkes/OrkesConductorClient.ts index 68d3a9fa..1e9145c7 100644 --- a/src/orkes/OrkesConductorClient.ts +++ b/src/orkes/OrkesConductorClient.ts @@ -16,7 +16,7 @@ export const orkesConductorClient = async ( config?: Partial, customFetch?: FetchFn ) => { - const { serverUrl, keyId, keySecret, maxHttpConnections } = + const { serverUrl, keyId, keySecret, maxHttp2Connections } = resolveOrkesConfig(config); if (!serverUrl) throw new Error("Conductor server URL is not set"); @@ -24,7 +24,7 @@ export const orkesConductorClient = async ( const conductorClientWithAuth = new ConductorClientWithAuth( { ...config, BASE: serverUrl }, createOrkesHttpRequest( - await resolveFetchFn(customFetch, maxHttpConnections) + await resolveFetchFn(customFetch, maxHttp2Connections) ) ); diff --git a/src/orkes/helpers/resolveOrkesConfig.ts b/src/orkes/helpers/resolveOrkesConfig.ts index 004f9ea2..bb652a59 100644 --- a/src/orkes/helpers/resolveOrkesConfig.ts +++ b/src/orkes/helpers/resolveOrkesConfig.ts @@ -5,7 +5,7 @@ export const resolveOrkesConfig = (config?: Partial) => { serverUrl: process.env.CONDUCTOR_SERVER_URL || config?.serverUrl, keyId: process.env.CONDUCTOR_AUTH_KEY || config?.keyId, keySecret: process.env.CONDUCTOR_AUTH_SECRET || config?.keySecret, - maxHttpConnections: - Number(process.env.CONDUCTOR_MAX_HTTP_CONNECTIONS) || config?.maxHttpConnections, + maxHttp2Connections: + Number(process.env.CONDUCTOR_MAX_HTTP2_CONNECTIONS) || config?.maxHttp2Connections, }; }; diff --git a/src/orkes/types.ts b/src/orkes/types.ts index 0a849d69..ff0089b7 100644 --- a/src/orkes/types.ts +++ b/src/orkes/types.ts @@ -9,5 +9,5 @@ export interface OrkesApiConfig extends GenerateTokenRequest, OpenAPIConfig { serverUrl: string; refreshTokenInterval: number; useEnvVars?: boolean; // DEPRECATED, has no effect - maxHttpConnections?: number; // max number of simultaneous http connections to the conductor server, defaults to 1 (since we use http2) + maxHttp2Connections?: number; // max number of simultaneous http connections to the conductor server, defaults to 1 (since we use http2) } From 1ed56184c00fceae9debaea1c8fdec27cf694597 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Mon, 29 Sep 2025 18:02:44 +0300 Subject: [PATCH 120/124] Delete .node-version --- .node-version | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .node-version diff --git a/.node-version b/.node-version deleted file mode 100644 index 91d5f6ff..00000000 --- a/.node-version +++ /dev/null @@ -1 +0,0 @@ -22.18.0 From df0597ec8c3bbdf5215e01b7cbc85125412c5b67 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Tue, 30 Sep 2025 01:26:05 +0300 Subject: [PATCH 121/124] code review fixes --- integration-tests/common/EventResourceService.test.ts | 5 +++-- src/orkes/helpers/resolveFetchFn.ts | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/integration-tests/common/EventResourceService.test.ts b/integration-tests/common/EventResourceService.test.ts index ed9ebd0c..09718dd8 100644 --- a/integration-tests/common/EventResourceService.test.ts +++ b/integration-tests/common/EventResourceService.test.ts @@ -6,9 +6,10 @@ describe("EventResourceService", () => { const orkesClient = await orkesConductorClient(); const eventApi = orkesClient.eventResource; + const now = Date.now(); const [eventName, event, eventDescription, eventTagKey, eventTagValue] = [ - `jsSdkTest-EventName-${Date.now()}`, - `jsSdkTest:eventHandler:1${Date.now()}`, + `jsSdkTest-EventName-${now}`, + `jsSdkTest:eventHandler:1${now}`, "jsSdkTestDescription", "jsSdkTestTagKey", "jsSdkTestTagValue", diff --git a/src/orkes/helpers/resolveFetchFn.ts b/src/orkes/helpers/resolveFetchFn.ts index 3f9a4386..8ed08896 100644 --- a/src/orkes/helpers/resolveFetchFn.ts +++ b/src/orkes/helpers/resolveFetchFn.ts @@ -1,6 +1,6 @@ import { FetchFn } from "../types"; // eslint-disable-next-line -// @ts-ignore since undici is an optional dependency and could me missing +// @ts-ignore since undici is an optional dependency and could be missing import type { RequestInfo as UndiciRequestInfo, RequestInit as UndiciRequestInit, @@ -15,7 +15,7 @@ export const resolveFetchFn = async ( try { // eslint-disable-next-line - // @ts-ignore since undici is an optional dependency and could me missing + // @ts-ignore since undici is an optional dependency and could be missing const { fetch: undiciFetch, Agent } = await import("undici"); const undiciAgent = new Agent({ allowH2: true, connections: maxHttpConnections }); From d08e0999248b57380f078359022b073955810941 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Tue, 30 Sep 2025 15:19:52 +0300 Subject: [PATCH 122/124] fix executor v5 test issues related to naming, remove test utils class --- integration-tests/common/TaskManager.test.ts | 12 +- .../common/TaskRunnerIntTest.test.ts | 4 +- integration-tests/common/executor.test.ts | 8 +- integration-tests/common/readme.test.ts | 6 +- integration-tests/utils/test-util.ts | 124 ------------------ .../utils/waitForWorkflowCompletion.ts | 44 +++++++ .../utils/waitForWorkflowStatus.ts | 36 +++++ integration-tests/v5-only/executor.test.ts | 51 ++++--- .../metadata/complex_wf_signal_test.json | 65 --------- .../metadata/complex_wf_signal_test.ts | 67 ++++++++++ .../complex_wf_signal_test_subworkflow_1.json | 82 ------------ .../complex_wf_signal_test_subworkflow_1.ts | 84 ++++++++++++ .../complex_wf_signal_test_subworkflow_2.json | 61 --------- .../complex_wf_signal_test_subworkflow_2.ts | 63 +++++++++ .../v5-only/metadata/wait_signal_test.json | 71 ---------- .../v5-only/metadata/wait_signal_test.ts | 73 +++++++++++ 16 files changed, 406 insertions(+), 445 deletions(-) delete mode 100644 integration-tests/utils/test-util.ts create mode 100644 integration-tests/utils/waitForWorkflowCompletion.ts create mode 100644 integration-tests/utils/waitForWorkflowStatus.ts delete mode 100644 integration-tests/v5-only/metadata/complex_wf_signal_test.json create mode 100644 integration-tests/v5-only/metadata/complex_wf_signal_test.ts delete mode 100644 integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.json create mode 100644 integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.ts delete mode 100644 integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.json create mode 100644 integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.ts delete mode 100644 integration-tests/v5-only/metadata/wait_signal_test.json create mode 100644 integration-tests/v5-only/metadata/wait_signal_test.ts diff --git a/integration-tests/common/TaskManager.test.ts b/integration-tests/common/TaskManager.test.ts index f1faf7c2..5f9cfbc2 100644 --- a/integration-tests/common/TaskManager.test.ts +++ b/integration-tests/common/TaskManager.test.ts @@ -3,7 +3,7 @@ import { simpleTask, taskDefinition, WorkflowExecutor } from "../../src/core"; import { orkesConductorClient } from "../../src/orkes"; import { TaskManager, ConductorWorker } from "../../src/task/index"; import { mockLogger } from "../utils/mockLogger"; -import { TestUtil } from "../utils/test-util"; +import { waitForWorkflowCompletion } from "../utils/waitForWorkflowCompletion"; const BASE_TIME = 1000; @@ -51,7 +51,7 @@ describe("TaskManager", () => { version: 1, }); - const workflowStatus = await TestUtil.waitForWorkflowCompletion(executor, executionId, BASE_TIME * 30); + const workflowStatus = await waitForWorkflowCompletion(executor, executionId, BASE_TIME * 30); expect(workflowStatus.status).toEqual("COMPLETED"); @@ -103,7 +103,7 @@ describe("TaskManager", () => { correlationId: `${workflowName}-id` }); - const workflowStatus = await TestUtil.waitForWorkflowCompletion(executor, status, BASE_TIME * 30); + const workflowStatus = await waitForWorkflowCompletion(executor, status, BASE_TIME * 30); expect(workflowStatus.status).toEqual("FAILED"); expect(mockErrorHandler).toHaveBeenCalledTimes(1); @@ -152,7 +152,7 @@ describe("TaskManager", () => { correlationId: `${workflowName}-id` }); - const workflowStatus = await TestUtil.waitForWorkflowCompletion(executor, executionId!, BASE_TIME * 30); + const workflowStatus = await waitForWorkflowCompletion(executor, executionId!, BASE_TIME * 30); expect(workflowStatus.status).toEqual("FAILED"); await manager.stopPolling(); }); @@ -217,7 +217,7 @@ describe("TaskManager", () => { // decrease speed again manager.updatePollingOptions({ pollInterval: BASE_TIME, concurrency: 1 }); - const workflowStatus = await TestUtil.waitForWorkflowCompletion(executor, executionId, BASE_TIME * 30); + const workflowStatus = await waitForWorkflowCompletion(executor, executionId, BASE_TIME * 30); expect(workflowStatus.status).toEqual("COMPLETED"); await manager.stopPolling(); @@ -343,7 +343,7 @@ describe("TaskManager", () => { // decrease speed again manager.updatePollingOptions({ pollInterval: BASE_TIME, concurrency: 1 }); - const workflowStatus = await TestUtil.waitForWorkflowCompletion(executor, executionId, BASE_TIME * 30); + const workflowStatus = await waitForWorkflowCompletion(executor, executionId, BASE_TIME * 30); expect(workflowStatus.status).toEqual("COMPLETED"); await manager.stopPolling(); diff --git a/integration-tests/common/TaskRunnerIntTest.test.ts b/integration-tests/common/TaskRunnerIntTest.test.ts index 52cb298a..60439722 100644 --- a/integration-tests/common/TaskRunnerIntTest.test.ts +++ b/integration-tests/common/TaskRunnerIntTest.test.ts @@ -2,7 +2,7 @@ import { expect, describe, test, jest } from "@jest/globals"; import { TaskRunner } from "../../src/task/TaskRunner"; import { WorkflowExecutor, simpleTask } from "../../src/core"; import { orkesConductorClient } from "../../src/orkes"; -import { TestUtil } from "../utils/test-util"; +import { waitForWorkflowStatus } from "../utils/waitForWorkflowStatus"; describe("TaskManager", () => { const clientPromise = orkesConductorClient(); @@ -61,7 +61,7 @@ describe("TaskManager", () => { taskRunner.updateOptions({ concurrency: 1, pollInterval: 100 }); - const workflowStatus = await TestUtil.waitForWorkflowStatus(executor, executionId!, "COMPLETED"); + const workflowStatus = await waitForWorkflowStatus(executor, executionId!, "COMPLETED"); const [firstTask] = workflowStatus.tasks || []; expect(firstTask?.taskType).toEqual(taskName); diff --git a/integration-tests/common/executor.test.ts b/integration-tests/common/executor.test.ts index ba1b3b0d..feabb593 100644 --- a/integration-tests/common/executor.test.ts +++ b/integration-tests/common/executor.test.ts @@ -3,7 +3,7 @@ import { SetVariableTaskDef, TaskType, WorkflowDef} from "../../src/common"; import { orkesConductorClient } from "../../src/orkes"; import { WorkflowExecutor } from "../../src/core/executor"; import { v4 as uuidv4 } from "uuid"; -import {TestUtil} from "../utils/test-util"; +import { waitForWorkflowStatus } from "../utils/waitForWorkflowStatus"; import { httpTask } from "../../src/core/sdk"; import { TaskClient } from "../../src/core/taskClient"; @@ -133,14 +133,14 @@ describe("Executor", () => { version: 1, }); - const workflowStatusBefore = await TestUtil.waitForWorkflowStatus(executor, executionId, "RUNNING"); + const workflowStatusBefore = await waitForWorkflowStatus(executor, executionId, "RUNNING"); expect(["IN_PROGRESS", "SCHEDULED"]).toContain(workflowStatusBefore.tasks?.[0]?.status); const taskClient = new TaskClient(client); taskClient.updateTaskResult(executionId, taskName, "COMPLETED", { hello: "From manuall api call updating task result" }); - const workflowStatusAfter = await TestUtil.waitForWorkflowStatus(executor, executionId, "COMPLETED"); + const workflowStatusAfter = await waitForWorkflowStatus(executor, executionId, "COMPLETED"); expect(workflowStatusAfter.tasks?.[0]?.status).toEqual("COMPLETED"); }); @@ -166,7 +166,7 @@ describe("Executor", () => { version: 1, }); - const workflowStatus = await TestUtil.waitForWorkflowStatus(executor, executionId, "COMPLETED"); + const workflowStatus = await waitForWorkflowStatus(executor, executionId, "COMPLETED"); expect(["FAILED", "COMPLETED_WITH_ERRORS"]).toContain(workflowStatus.tasks?.[0]?.status); }); }); diff --git a/integration-tests/common/readme.test.ts b/integration-tests/common/readme.test.ts index dd85e4d8..501f283f 100644 --- a/integration-tests/common/readme.test.ts +++ b/integration-tests/common/readme.test.ts @@ -3,7 +3,7 @@ import { orkesConductorClient } from "../../src/orkes"; import { WorkflowExecutor, simpleTask, generate } from "../../src/core"; import { TaskType } from "../../src/common"; import { TaskRunner } from "../../src/task"; -import { TestUtil } from "../utils/test-util"; +import { waitForWorkflowStatus } from "../utils/waitForWorkflowStatus"; describe("TaskManager", () => { const clientPromise = orkesConductorClient(); @@ -54,7 +54,7 @@ describe("TaskManager", () => { version: 1, }); - const workflowStatus = await TestUtil.waitForWorkflowStatus(executor, executionId, "COMPLETED"); + const workflowStatus = await waitForWorkflowStatus(executor, executionId, "COMPLETED"); const [firstTask] = workflowStatus.tasks || []; expect(firstTask?.taskType).toEqual(taskName); @@ -162,7 +162,7 @@ describe("TaskManager", () => { `workflow${sumTwoNumbers.name}` ); - const workflowStatus = await TestUtil.waitForWorkflowStatus(executor, executionId!, "COMPLETED"); + const workflowStatus = await waitForWorkflowStatus(executor, executionId!, "COMPLETED"); expect(workflowStatus.status).toEqual("COMPLETED"); expect(workflowStatus.output?.result).toEqual(3); diff --git a/integration-tests/utils/test-util.ts b/integration-tests/utils/test-util.ts deleted file mode 100644 index 65a77b06..00000000 --- a/integration-tests/utils/test-util.ts +++ /dev/null @@ -1,124 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; -import {WorkflowDef} from "../../src/common"; -import {MetadataClient} from "../../src/core/metadataClient"; -import {WorkflowExecutor} from "../../src/core/executor"; - -export class TestUtil { - private static metadataClient: MetadataClient; - - public static setMetadataClient(metadataClient: MetadataClient): void { - this.metadataClient = metadataClient; - } - /** - * Read and parse workflow definition from JSON file - */ - public static getWorkflowDef(filePath: string): WorkflowDef { - try { - const fullPath = path.join(__dirname, filePath); - const fileContent = fs.readFileSync(fullPath, 'utf8'); - return JSON.parse(fileContent) as WorkflowDef; - } catch (error) { - throw new Error(`Failed to read workflow definition from ${filePath}: ${error}`); - } - } - - /** - * Register a single workflow from JSON file - */ - public static async registerWorkflow(workflowName: string, workflowJsonFilePath: string): Promise { - try { - const workflowDef = this.getWorkflowDef(workflowJsonFilePath); - workflowDef.name = workflowName; - await this.metadataClient.registerWorkflowDef(workflowDef, true); - console.log(`✓ Registered workflow: ${workflowName}`); - } catch (error) { - throw new Error(`Failed to register workflow ${workflowName}: ${error}`); - } - } - - // Helper function to wait for workflow completion - public static async waitForWorkflowCompletion( - executor: WorkflowExecutor, - workflowId: string, - maxWaitMs: number = 300000, // 5 minutes default - pollIntervalMs: number = 100 // 100ms default - ) { - const startTime = Date.now(); - - while (Date.now() - startTime < maxWaitMs) { - try { - const workflowStatus = await executor.getWorkflow(workflowId, true); - - // Check if workflow is in a terminal state - if (['COMPLETED', 'FAILED', 'TERMINATED', 'TIMED_OUT'].includes(workflowStatus.status!)) { - console.debug(`Workflow ${workflowId} reached terminal state: ${workflowStatus.status}`); - return workflowStatus; - } - - console.debug(`Workflow ${workflowId} status: ${workflowStatus.status}, waiting...`); - - // Wait before next poll - await new Promise(resolve => setTimeout(resolve, pollIntervalMs)); - - } catch (error) { - console.warn(`Error checking workflow status for ${workflowId}:`, error); - await new Promise(resolve => setTimeout(resolve, pollIntervalMs)); - } - } - - throw new Error(`Workflow ${workflowId} did not complete within ${maxWaitMs}ms`); - } - - /** - * Unregister a workflow - */ - public static async unregisterWorkflow(workflowName: string, version: number = 1): Promise { - try { - await this.metadataClient.unregisterWorkflow(workflowName, version); - console.log(`✓ Unregistered workflow: ${workflowName} ${version}`); - } catch (error) { - console.warn(`Failed to unregister workflow ${workflowName}: ${error}`); - } - } - - /** - * Wait for workflow to reach expected status - */ - public static async waitForWorkflowStatus( - workflowClient: any, - workflowId: string, - expectedStatus: string, - maxWaitTimeMs: number = 15000, - pollIntervalMs: number = 1000 - ): Promise { - const startTime = Date.now(); - - while (Date.now() - startTime < maxWaitTimeMs) { - try { - const workflow = await workflowClient.getWorkflow(workflowId, true); - - if (workflow.status === expectedStatus) { - return workflow; - } - - if (workflow.status === 'FAILED' || workflow.status === 'TERMINATED') { - throw new Error(`Workflow ended in unexpected state: ${workflow.status}`); - } - - await this.sleep(pollIntervalMs); - } catch (error) { - throw new Error(`Failed to get workflow status: ${error}`); - } - } - - throw new Error(`Workflow did not reach status ${expectedStatus} within ${maxWaitTimeMs}ms`); - } - - /** - * Sleep utility - */ - private static sleep(ms: number): Promise { - return new Promise(resolve => setTimeout(resolve, ms)); - } -} \ No newline at end of file diff --git a/integration-tests/utils/waitForWorkflowCompletion.ts b/integration-tests/utils/waitForWorkflowCompletion.ts new file mode 100644 index 00000000..63a1e9b1 --- /dev/null +++ b/integration-tests/utils/waitForWorkflowCompletion.ts @@ -0,0 +1,44 @@ +import type { WorkflowExecutor } from "../../src/core/executor"; + +// Helper function to wait for workflow completion +export const waitForWorkflowCompletion = async ( + executor: WorkflowExecutor, + workflowId: string, + maxWaitMs: number = 300000, // 5 minutes default + pollIntervalMs: number = 100 // 100ms default +) => { + const startTime = Date.now(); + + while (Date.now() - startTime < maxWaitMs) { + try { + const workflowStatus = await executor.getWorkflow(workflowId, true); + + // Check if workflow is in a terminal state + if ( + ["COMPLETED", "FAILED", "TERMINATED", "TIMED_OUT"].includes( + workflowStatus.status! + ) + ) { + console.debug( + `Workflow ${workflowId} reached terminal state: ${workflowStatus.status}` + ); + return workflowStatus; + } + + console.debug( + `Workflow ${workflowId} status: ${workflowStatus.status}, waiting...` + ); + + // Wait before next poll + await new Promise((resolve) => setTimeout(resolve, pollIntervalMs)); + } catch (error) { + console.warn(`Error checking workflow status for ${workflowId}:`, error); + await new Promise((resolve) => setTimeout(resolve, pollIntervalMs)); + } + } + + throw new Error( + `Workflow ${workflowId} did not complete within ${maxWaitMs}ms` + ); +}; + diff --git a/integration-tests/utils/waitForWorkflowStatus.ts b/integration-tests/utils/waitForWorkflowStatus.ts new file mode 100644 index 00000000..9b65225c --- /dev/null +++ b/integration-tests/utils/waitForWorkflowStatus.ts @@ -0,0 +1,36 @@ +/** + * Wait for workflow to reach expected status + */ +export const waitForWorkflowStatus = async ( + workflowClient: any, + workflowId: string, + expectedStatus: string, + maxWaitTimeMs: number = 15000, + pollIntervalMs: number = 1000 +): Promise => { + const startTime = Date.now(); + + while (Date.now() - startTime < maxWaitTimeMs) { + try { + const workflow = await workflowClient.getWorkflow(workflowId, true); + + if (workflow.status === expectedStatus) { + return workflow; + } + + if (workflow.status === "FAILED" || workflow.status === "TERMINATED") { + throw new Error( + `Workflow ended in unexpected state: ${workflow.status}` + ); + } + + await new Promise((resolve) => setTimeout(resolve, pollIntervalMs)); + } catch (error) { + throw new Error(`Failed to get workflow status: ${error}`); + } + } + + throw new Error( + `Workflow did not reach status ${expectedStatus} within ${maxWaitTimeMs}ms` + ); +}; diff --git a/integration-tests/v5-only/executor.test.ts b/integration-tests/v5-only/executor.test.ts index 79417d92..d4ed55bc 100644 --- a/integration-tests/v5-only/executor.test.ts +++ b/integration-tests/v5-only/executor.test.ts @@ -4,24 +4,22 @@ import { orkesConductorClient } from "../../src/orkes"; import { WorkflowExecutor } from "../../src/core/executor"; import { v4 as uuidv4 } from "uuid"; import {MetadataClient} from "../../src/core/metadataClient"; -import {TestUtil} from "../utils/test-util"; +import {waitForWorkflowStatus} from "../utils/waitForWorkflowStatus"; import {TaskResultStatusEnum} from "../../src/common/open-api/models/TaskResultStatusEnum"; import {SignalResponse} from "../../src/common/open-api/models/SignalResponse"; +import { getComplexWfSignalTest } from "./metadata/complex_wf_signal_test"; +import { getComplexWfSignalTestSubworkflow1 } from "./metadata/complex_wf_signal_test_subworkflow_1"; +import { getComplexWfSignalTestSubworkflow2 } from "./metadata/complex_wf_signal_test_subworkflow_2"; +import { getWaitSignalTest } from "./metadata/wait_signal_test"; describe("Execute with Return Strategy and Consistency", () => { // Constants specific to this test suite - const WORKFLOW_NAMES = { - COMPLEX_WF: `jsSdkTest-Complex_wf_signal_test-${Date.now()}`, - SUB_WF_1: `jsSdkTest-Complex_wf_signal_test_subworkflow_1-${Date.now()}`, - SUB_WF_2: `jsSdkTest-Complex_wf_signal_test_subworkflow_2-${Date.now()}`, - WAIT_SIGNAL_TEST: `jsSdkTest-Wait_signal_test-${Date.now()}` - }; - - const WORKFLOW_JSON_FILE_PATHS = { - COMPLEX_WF: `../v5-only/metadata/complex_wf_signal_test.json`, - SUB_WF_1: `../v5-only/metadata/complex_wf_signal_test_subworkflow_1.json`, - SUB_WF_2: `../v5-only/metadata/complex_wf_signal_test_subworkflow_2.json`, - WAIT_SIGNAL_TEST: `../v5-only/metadata/wait_signal_test.json` + const now = Date.now(); + const WORKFLOWS = { + COMPLEX_WF: getComplexWfSignalTest(now), + SUB_WF_1: getComplexWfSignalTestSubworkflow1(now), + SUB_WF_2: getComplexWfSignalTestSubworkflow2(now), + WAIT_SIGNAL_TEST: getWaitSignalTest(now) }; const clientPromise = orkesConductorClient(); @@ -37,7 +35,6 @@ describe("Execute with Return Strategy and Consistency", () => { client = await clientPromise; executor = new WorkflowExecutor(client); metadataClient = new MetadataClient(client); - TestUtil.setMetadataClient(metadataClient); // Register all test workflows await registerAllWorkflows(); @@ -70,15 +67,15 @@ describe("Execute with Return Strategy and Consistency", () => { async function registerAllWorkflows(): Promise { try { await Promise.all([ - TestUtil.registerWorkflow(WORKFLOW_NAMES.COMPLEX_WF, WORKFLOW_JSON_FILE_PATHS.COMPLEX_WF), - TestUtil.registerWorkflow(WORKFLOW_NAMES.SUB_WF_1, WORKFLOW_JSON_FILE_PATHS.SUB_WF_1), - TestUtil.registerWorkflow(WORKFLOW_NAMES.SUB_WF_2, WORKFLOW_JSON_FILE_PATHS.SUB_WF_2), - TestUtil.registerWorkflow(WORKFLOW_NAMES.WAIT_SIGNAL_TEST, WORKFLOW_JSON_FILE_PATHS.WAIT_SIGNAL_TEST) + metadataClient.registerWorkflowDef(WORKFLOWS.COMPLEX_WF, true), + metadataClient.registerWorkflowDef(WORKFLOWS.SUB_WF_1, true), + metadataClient.registerWorkflowDef(WORKFLOWS.SUB_WF_2, true), + metadataClient.registerWorkflowDef(WORKFLOWS.WAIT_SIGNAL_TEST, true) ]); // Add to cleanup list - Object.values(WORKFLOW_NAMES).forEach(name => { - workflowsToCleanup.push({name, version: 1}); + Object.values(WORKFLOWS).forEach(workflow => { + workflowsToCleanup.push({name: workflow.name, version: 1}); }); console.log('✓ All workflows registered successfully'); @@ -89,7 +86,7 @@ describe("Execute with Return Strategy and Consistency", () => { async function cleanupAllWorkflows(): Promise { const cleanupPromises = workflowsToCleanup.map(({name, version}) => - TestUtil.unregisterWorkflow(name, version) + metadataClient.unregisterWorkflow(name, version) ); const results = await Promise.allSettled(cleanupPromises); @@ -172,8 +169,8 @@ describe("Execute with Return Strategy and Consistency", () => { // 1. Execute workflow with return strategy const rawResult = await executor.executeWorkflow( - { name: WORKFLOW_NAMES.COMPLEX_WF, version: 1 }, - WORKFLOW_NAMES.COMPLEX_WF, + { name: WORKFLOWS.COMPLEX_WF.name, version: 1 }, + WORKFLOWS.COMPLEX_WF.name, 1, uuidv4(), "", // waitUntilTaskRef @@ -299,7 +296,7 @@ describe("Execute with Return Strategy and Consistency", () => { ); // Wait for workflow completion - const finalWorkflow = await TestUtil.waitForWorkflowStatus( + const finalWorkflow = await waitForWorkflowStatus( executor, workflowId, 'COMPLETED', @@ -318,8 +315,8 @@ describe("Execute with Return Strategy and Consistency", () => { // Execute workflow const rawResult = await executor.executeWorkflow( - { name: WORKFLOW_NAMES.COMPLEX_WF, version: 1 }, - WORKFLOW_NAMES.COMPLEX_WF, + { name: WORKFLOWS.COMPLEX_WF.name, version: 1 }, + WORKFLOWS.COMPLEX_WF.name, 1, uuidv4(), "", @@ -377,7 +374,7 @@ describe("Execute with Return Strategy and Consistency", () => { await executor.signal(workflowId, TaskResultStatusEnum.COMPLETED, { result: "signal1" }); await executor.signal(workflowId, TaskResultStatusEnum.COMPLETED, { result: "signal2" }); - await TestUtil.waitForWorkflowStatus(executor, workflowId, 'COMPLETED', 300000, 200); + await waitForWorkflowStatus(executor, workflowId, 'COMPLETED', 300000, 200); console.log(`✓ ${testCase.name} test completed successfully`); }); }); diff --git a/integration-tests/v5-only/metadata/complex_wf_signal_test.json b/integration-tests/v5-only/metadata/complex_wf_signal_test.json deleted file mode 100644 index ecf3d55f..00000000 --- a/integration-tests/v5-only/metadata/complex_wf_signal_test.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "createTime": 1744299182957, - "updateTime": 1744299435683, - "name": "complex_wf_signal_test", - "description": "http_yield_signal_test", - "version": 1, - "tasks": [ - { - "name": "http", - "taskReferenceName": "http_ref", - "inputParameters": { - "uri": "http://httpbin:8081/api/hello?name=test1", - "method": "GET", - "accept": "application/json", - "contentType": "application/json", - "encode": true - }, - "type": "HTTP", - "decisionCases": {}, - "defaultCase": [], - "forkTasks": [], - "startDelay": 0, - "joinOn": [], - "optional": false, - "defaultExclusiveJoinTask": [], - "asyncComplete": false, - "loopOver": [], - "onStateChange": {}, - "permissive": false - }, - { - "name": "sub_workflow", - "taskReferenceName": "sub_workflow_ref", - "inputParameters": {}, - "type": "SUB_WORKFLOW", - "decisionCases": {}, - "defaultCase": [], - "forkTasks": [], - "startDelay": 0, - "subWorkflowParam": { - "name": "complex_wf_signal_test_subworkflow_1", - "version": 1 - }, - "joinOn": [], - "optional": false, - "defaultExclusiveJoinTask": [], - "asyncComplete": false, - "loopOver": [], - "onStateChange": {}, - "permissive": false - } - ], - "inputParameters": [], - "outputParameters": {}, - "failureWorkflow": "", - "schemaVersion": 2, - "restartable": true, - "workflowStatusListenerEnabled": false, - "ownerEmail": "shailesh.padave@orkes.io", - "timeoutPolicy": "ALERT_ONLY", - "timeoutSeconds": 0, - "variables": {}, - "inputTemplate": {}, - "enforceSchema": true -} \ No newline at end of file diff --git a/integration-tests/v5-only/metadata/complex_wf_signal_test.ts b/integration-tests/v5-only/metadata/complex_wf_signal_test.ts new file mode 100644 index 00000000..4772a3ed --- /dev/null +++ b/integration-tests/v5-only/metadata/complex_wf_signal_test.ts @@ -0,0 +1,67 @@ +export const getComplexWfSignalTest = (date: number) => { + return { + createTime: 1744299182957, + updateTime: 1744299435683, + name: `complex_wf_signal_test_${date}`, + description: "http_yield_signal_test", + version: 1, + tasks: [ + { + name: "http", + taskReferenceName: "http_ref", + inputParameters: { + uri: "http://httpbin:8081/api/hello?name=test1", + method: "GET", + accept: "application/json", + contentType: "application/json", + encode: true, + }, + type: "HTTP", + decisionCases: {}, + defaultCase: [], + forkTasks: [], + startDelay: 0, + joinOn: [], + optional: false, + defaultExclusiveJoinTask: [], + asyncComplete: false, + loopOver: [], + onStateChange: {}, + permissive: false, + }, + { + name: "sub_workflow", + taskReferenceName: "sub_workflow_ref", + inputParameters: {}, + type: "SUB_WORKFLOW", + decisionCases: {}, + defaultCase: [], + forkTasks: [], + startDelay: 0, + subWorkflowParam: { + name: `complex_wf_signal_test_subworkflow_1_${date}`, + version: 1, + }, + joinOn: [], + optional: false, + defaultExclusiveJoinTask: [], + asyncComplete: false, + loopOver: [], + onStateChange: {}, + permissive: false, + }, + ], + inputParameters: [], + outputParameters: {}, + failureWorkflow: "", + schemaVersion: 2, + restartable: true, + workflowStatusListenerEnabled: false, + ownerEmail: "shailesh.padave@orkes.io", + timeoutPolicy: "ALERT_ONLY" as const, + timeoutSeconds: 0, + variables: {}, + inputTemplate: {}, + enforceSchema: true, + }; +}; diff --git a/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.json b/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.json deleted file mode 100644 index f26a7dbb..00000000 --- a/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "createTime": 1744299356718, - "updateTime": 1744287643769, - "name": "complex_wf_signal_test_subworkflow_1", - "description": "complex_wf_signal_test_subworkflow_1", - "version": 1, - "tasks": [ - { - "name": "http", - "taskReferenceName": "http_ref", - "inputParameters": { - "uri": "http://httpbin:8081/api/hello?name=test1", - "method": "GET", - "accept": "application/json", - "contentType": "application/json", - "encode": true - }, - "type": "HTTP", - "decisionCases": {}, - "defaultCase": [], - "forkTasks": [], - "startDelay": 0, - "joinOn": [], - "optional": false, - "defaultExclusiveJoinTask": [], - "asyncComplete": false, - "loopOver": [], - "onStateChange": {}, - "permissive": false - }, - { - "name": "yield", - "taskReferenceName": "simple_ref_1", - "inputParameters": {}, - "type": "YIELD", - "decisionCases": {}, - "defaultCase": [], - "forkTasks": [], - "startDelay": 0, - "joinOn": [], - "optional": false, - "defaultExclusiveJoinTask": [], - "asyncComplete": false, - "loopOver": [], - "onStateChange": {}, - "permissive": false - }, - { - "name": "sub_workflow", - "taskReferenceName": "sub_workflow_ref", - "inputParameters": {}, - "type": "SUB_WORKFLOW", - "decisionCases": {}, - "defaultCase": [], - "forkTasks": [], - "startDelay": 0, - "subWorkflowParam": { - "name": "complex_wf_signal_test_subworkflow_2", - "version": 1 - }, - "joinOn": [], - "optional": false, - "defaultExclusiveJoinTask": [], - "asyncComplete": false, - "loopOver": [], - "onStateChange": {}, - "permissive": false - } - ], - "inputParameters": [], - "outputParameters": {}, - "failureWorkflow": "", - "schemaVersion": 2, - "restartable": true, - "workflowStatusListenerEnabled": false, - "ownerEmail": "shailesh.padave@orkes.io", - "timeoutPolicy": "ALERT_ONLY", - "timeoutSeconds": 0, - "variables": {}, - "inputTemplate": {}, - "enforceSchema": true -} \ No newline at end of file diff --git a/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.ts b/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.ts new file mode 100644 index 00000000..30ffc678 --- /dev/null +++ b/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.ts @@ -0,0 +1,84 @@ +export const getComplexWfSignalTestSubworkflow1 = (date: number) => { + return { + createTime: 1744299356718, + updateTime: 1744287643769, + name: `complex_wf_signal_test_subworkflow_1_${date}`, + description: `complex_wf_signal_test_subworkflow_${date}`, + version: 1, + tasks: [ + { + name: "http", + taskReferenceName: "http_ref", + inputParameters: { + uri: "http://httpbin:8081/api/hello?name=test1", + method: "GET", + accept: "application/json", + contentType: "application/json", + encode: true, + }, + type: "HTTP", + decisionCases: {}, + defaultCase: [], + forkTasks: [], + startDelay: 0, + joinOn: [], + optional: false, + defaultExclusiveJoinTask: [], + asyncComplete: false, + loopOver: [], + onStateChange: {}, + permissive: false, + }, + { + name: "yield", + taskReferenceName: "simple_ref_1", + inputParameters: {}, + type: "YIELD", + decisionCases: {}, + defaultCase: [], + forkTasks: [], + startDelay: 0, + joinOn: [], + optional: false, + defaultExclusiveJoinTask: [], + asyncComplete: false, + loopOver: [], + onStateChange: {}, + permissive: false, + }, + { + name: "sub_workflow", + taskReferenceName: "sub_workflow_ref", + inputParameters: {}, + type: "SUB_WORKFLOW", + decisionCases: {}, + defaultCase: [], + forkTasks: [], + startDelay: 0, + subWorkflowParam: { + name: `complex_wf_signal_test_subworkflow_2_${date}`, + version: 1, + }, + joinOn: [], + optional: false, + defaultExclusiveJoinTask: [], + asyncComplete: false, + loopOver: [], + onStateChange: {}, + permissive: false, + }, + ], + inputParameters: [], + outputParameters: {}, + failureWorkflow: "", + schemaVersion: 2, + restartable: true, + workflowStatusListenerEnabled: false, + ownerEmail: "shailesh.padave@orkes.io", + timeoutPolicy: "ALERT_ONLY" as const, + timeoutSeconds: 0, + variables: {}, + inputTemplate: {}, + enforceSchema: true, + }; +}; diff --git a/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.json b/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.json deleted file mode 100644 index 1bc32297..00000000 --- a/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "createTime": 1744299371396, - "updateTime": 0, - "name": "complex_wf_signal_test_subworkflow_2", - "description": "complex_wf_signal_test_subworkflow_2", - "version": 1, - "tasks": [ - { - "name": "http", - "taskReferenceName": "http_ref", - "inputParameters": { - "uri": "http://httpbin:8081/api/hello?name=test1", - "method": "GET", - "accept": "application/json", - "contentType": "application/json", - "encode": true - }, - "type": "HTTP", - "decisionCases": {}, - "defaultCase": [], - "forkTasks": [], - "startDelay": 0, - "joinOn": [], - "optional": false, - "defaultExclusiveJoinTask": [], - "asyncComplete": false, - "loopOver": [], - "onStateChange": {}, - "permissive": false - }, - { - "name": "yield", - "taskReferenceName": "simple_ref_1", - "inputParameters": {}, - "type": "YIELD", - "decisionCases": {}, - "defaultCase": [], - "forkTasks": [], - "startDelay": 0, - "joinOn": [], - "optional": false, - "defaultExclusiveJoinTask": [], - "asyncComplete": false, - "loopOver": [], - "onStateChange": {}, - "permissive": false - } - ], - "inputParameters": [], - "outputParameters": {}, - "failureWorkflow": "", - "schemaVersion": 2, - "restartable": true, - "workflowStatusListenerEnabled": false, - "ownerEmail": "shailesh.padave@orkes.io", - "timeoutPolicy": "ALERT_ONLY", - "timeoutSeconds": 0, - "variables": {}, - "inputTemplate": {}, - "enforceSchema": true -} \ No newline at end of file diff --git a/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.ts b/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.ts new file mode 100644 index 00000000..0adcafb5 --- /dev/null +++ b/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.ts @@ -0,0 +1,63 @@ +export const getComplexWfSignalTestSubworkflow2 = (date: number) => { + return { + createTime: 1744299371396, + updateTime: 0, + name: `complex_wf_signal_test_subworkflow_2_${date}`, + description: `complex_wf_signal_test_subworkflow_${date}`, + version: 1, + tasks: [ + { + name: "http", + taskReferenceName: "http_ref", + inputParameters: { + uri: "http://httpbin:8081/api/hello?name=test1", + method: "GET", + accept: "application/json", + contentType: "application/json", + encode: true, + }, + type: "HTTP", + decisionCases: {}, + defaultCase: [], + forkTasks: [], + startDelay: 0, + joinOn: [], + optional: false, + defaultExclusiveJoinTask: [], + asyncComplete: false, + loopOver: [], + onStateChange: {}, + permissive: false, + }, + { + name: "yield", + taskReferenceName: "simple_ref_1", + inputParameters: {}, + type: "YIELD", + decisionCases: {}, + defaultCase: [], + forkTasks: [], + startDelay: 0, + joinOn: [], + optional: false, + defaultExclusiveJoinTask: [], + asyncComplete: false, + loopOver: [], + onStateChange: {}, + permissive: false, + }, + ], + inputParameters: [], + outputParameters: {}, + failureWorkflow: "", + schemaVersion: 2, + restartable: true, + workflowStatusListenerEnabled: false, + ownerEmail: "shailesh.padave@orkes.io", + timeoutPolicy: "ALERT_ONLY" as const, + timeoutSeconds: 0, + variables: {}, + inputTemplate: {}, + enforceSchema: true, + }; +}; diff --git a/integration-tests/v5-only/metadata/wait_signal_test.json b/integration-tests/v5-only/metadata/wait_signal_test.json deleted file mode 100644 index f3208552..00000000 --- a/integration-tests/v5-only/metadata/wait_signal_test.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "createTime": 1744183953775, - "updateTime": 0, - "name": "wait_signal_test", - "description": "wait_signal_test", - "version": 1, - "tasks": [ - { - "name": "wait", - "taskReferenceName": "wait_ref", - "inputParameters": {}, - "type": "WAIT", - "decisionCases": {}, - "defaultCase": [], - "forkTasks": [], - "startDelay": 0, - "joinOn": [], - "optional": false, - "defaultExclusiveJoinTask": [], - "asyncComplete": false, - "loopOver": [], - "onStateChange": {}, - "permissive": false - }, - { - "name": "json_transform", - "taskReferenceName": "json_transform_ref", - "type": "JSON_JQ_TRANSFORM", - "inputParameters": { - "persons": [ - { - "name": "some", - "last": "name", - "email": "mail@mail.com", - "id": 1 - }, - { - "name": "some2", - "last": "name2", - "email": "mail2@mail.com", - "id": 2 - } - ], - "queryExpression": ".persons | map({user:{email,id}})" - } - }, - { - "name": "inline", - "taskReferenceName": "inline_ref", - "type": "INLINE", - "inputParameters": { - "expression": "(function () {\n return $.value1 + $.value2;\n})();", - "evaluatorType": "graaljs", - "value1": 1, - "value2": 2 - } - } - ], - "inputParameters": [], - "outputParameters": {}, - "failureWorkflow": "", - "schemaVersion": 2, - "restartable": true, - "workflowStatusListenerEnabled": false, - "ownerEmail": "test.user@orkes.io", - "timeoutPolicy": "ALERT_ONLY", - "timeoutSeconds": 0, - "variables": {}, - "inputTemplate": {}, - "enforceSchema": true -} \ No newline at end of file diff --git a/integration-tests/v5-only/metadata/wait_signal_test.ts b/integration-tests/v5-only/metadata/wait_signal_test.ts new file mode 100644 index 00000000..154f3d08 --- /dev/null +++ b/integration-tests/v5-only/metadata/wait_signal_test.ts @@ -0,0 +1,73 @@ +export const getWaitSignalTest = (date: number) => { + return { + createTime: 1744183953775, + updateTime: 0, + name: `wait_signal_test_${date}`, + description: "wait_signal_test", + version: 1, + tasks: [ + { + name: "wait", + taskReferenceName: "wait_ref", + inputParameters: {}, + type: "WAIT", + decisionCases: {}, + defaultCase: [], + forkTasks: [], + startDelay: 0, + joinOn: [], + optional: false, + defaultExclusiveJoinTask: [], + asyncComplete: false, + loopOver: [], + onStateChange: {}, + permissive: false, + }, + { + name: "json_transform", + taskReferenceName: "json_transform_ref", + type: "JSON_JQ_TRANSFORM", + inputParameters: { + persons: [ + { + name: "some", + last: "name", + email: "mail@mail.com", + id: 1, + }, + { + name: "some2", + last: "name2", + email: "mail2@mail.com", + id: 2, + }, + ], + queryExpression: ".persons | map({user:{email,id}})", + }, + }, + { + name: "inline", + taskReferenceName: "inline_ref", + type: "INLINE", + inputParameters: { + expression: "(function () {\n return $.value1 + $.value2;\n})();", + evaluatorType: "graaljs", + value1: 1, + value2: 2, + }, + }, + ], + inputParameters: [], + outputParameters: {}, + failureWorkflow: "", + schemaVersion: 2, + restartable: true, + workflowStatusListenerEnabled: false, + ownerEmail: "test.user@orkes.io", + timeoutPolicy: "ALERT_ONLY" as const, + timeoutSeconds: 0, + variables: {}, + inputTemplate: {}, + enforceSchema: true, + }; +}; From 83ce4c95b23ebef46d76ec5aa3322585bacaa321 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Tue, 30 Sep 2025 15:26:41 +0300 Subject: [PATCH 123/124] update metadata function names --- integration-tests/v5-only/executor.test.ts | 16 ++++++++-------- .../v5-only/metadata/complex_wf_signal_test.ts | 2 +- .../complex_wf_signal_test_subworkflow_1.ts | 2 +- .../complex_wf_signal_test_subworkflow_2.ts | 2 +- .../v5-only/metadata/wait_signal_test.ts | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/integration-tests/v5-only/executor.test.ts b/integration-tests/v5-only/executor.test.ts index d4ed55bc..3f01b80c 100644 --- a/integration-tests/v5-only/executor.test.ts +++ b/integration-tests/v5-only/executor.test.ts @@ -7,19 +7,19 @@ import {MetadataClient} from "../../src/core/metadataClient"; import {waitForWorkflowStatus} from "../utils/waitForWorkflowStatus"; import {TaskResultStatusEnum} from "../../src/common/open-api/models/TaskResultStatusEnum"; import {SignalResponse} from "../../src/common/open-api/models/SignalResponse"; -import { getComplexWfSignalTest } from "./metadata/complex_wf_signal_test"; -import { getComplexWfSignalTestSubworkflow1 } from "./metadata/complex_wf_signal_test_subworkflow_1"; -import { getComplexWfSignalTestSubworkflow2 } from "./metadata/complex_wf_signal_test_subworkflow_2"; -import { getWaitSignalTest } from "./metadata/wait_signal_test"; +import { getComplexSignalTestWfData } from "./metadata/complex_wf_signal_test"; +import { getComplexSignalTestSubWf1Data } from "./metadata/complex_wf_signal_test_subworkflow_1"; +import { getComplexSignalTestSubWf2Data } from "./metadata/complex_wf_signal_test_subworkflow_2"; +import { getWaitSignalTestWfData } from "./metadata/wait_signal_test"; describe("Execute with Return Strategy and Consistency", () => { // Constants specific to this test suite const now = Date.now(); const WORKFLOWS = { - COMPLEX_WF: getComplexWfSignalTest(now), - SUB_WF_1: getComplexWfSignalTestSubworkflow1(now), - SUB_WF_2: getComplexWfSignalTestSubworkflow2(now), - WAIT_SIGNAL_TEST: getWaitSignalTest(now) + COMPLEX_WF: getComplexSignalTestWfData(now), + SUB_WF_1: getComplexSignalTestSubWf1Data(now), + SUB_WF_2: getComplexSignalTestSubWf2Data(now), + WAIT_SIGNAL_TEST: getWaitSignalTestWfData(now) }; const clientPromise = orkesConductorClient(); diff --git a/integration-tests/v5-only/metadata/complex_wf_signal_test.ts b/integration-tests/v5-only/metadata/complex_wf_signal_test.ts index 4772a3ed..038bc178 100644 --- a/integration-tests/v5-only/metadata/complex_wf_signal_test.ts +++ b/integration-tests/v5-only/metadata/complex_wf_signal_test.ts @@ -1,4 +1,4 @@ -export const getComplexWfSignalTest = (date: number) => { +export const getComplexSignalTestWfData = (date: number) => { return { createTime: 1744299182957, updateTime: 1744299435683, diff --git a/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.ts b/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.ts index 30ffc678..cc6af9bd 100644 --- a/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.ts +++ b/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.ts @@ -1,4 +1,4 @@ -export const getComplexWfSignalTestSubworkflow1 = (date: number) => { +export const getComplexSignalTestSubWf1Data = (date: number) => { return { createTime: 1744299356718, updateTime: 1744287643769, diff --git a/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.ts b/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.ts index 0adcafb5..1906ffbc 100644 --- a/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.ts +++ b/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.ts @@ -1,4 +1,4 @@ -export const getComplexWfSignalTestSubworkflow2 = (date: number) => { +export const getComplexSignalTestSubWf2Data = (date: number) => { return { createTime: 1744299371396, updateTime: 0, diff --git a/integration-tests/v5-only/metadata/wait_signal_test.ts b/integration-tests/v5-only/metadata/wait_signal_test.ts index 154f3d08..ed1ea3d8 100644 --- a/integration-tests/v5-only/metadata/wait_signal_test.ts +++ b/integration-tests/v5-only/metadata/wait_signal_test.ts @@ -1,4 +1,4 @@ -export const getWaitSignalTest = (date: number) => { +export const getWaitSignalTestWfData = (date: number) => { return { createTime: 1744183953775, updateTime: 0, From 0780f300eabc060c61d9f2b6277b2c701d1770cf Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Tue, 30 Sep 2025 15:28:32 +0300 Subject: [PATCH 124/124] update metadata function names --- integration-tests/v5-only/executor.test.ts | 16 ++++++++-------- .../v5-only/metadata/complex_wf_signal_test.ts | 2 +- .../complex_wf_signal_test_subworkflow_1.ts | 2 +- .../complex_wf_signal_test_subworkflow_2.ts | 2 +- .../v5-only/metadata/wait_signal_test.ts | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/integration-tests/v5-only/executor.test.ts b/integration-tests/v5-only/executor.test.ts index 3f01b80c..32116b96 100644 --- a/integration-tests/v5-only/executor.test.ts +++ b/integration-tests/v5-only/executor.test.ts @@ -7,19 +7,19 @@ import {MetadataClient} from "../../src/core/metadataClient"; import {waitForWorkflowStatus} from "../utils/waitForWorkflowStatus"; import {TaskResultStatusEnum} from "../../src/common/open-api/models/TaskResultStatusEnum"; import {SignalResponse} from "../../src/common/open-api/models/SignalResponse"; -import { getComplexSignalTestWfData } from "./metadata/complex_wf_signal_test"; -import { getComplexSignalTestSubWf1Data } from "./metadata/complex_wf_signal_test_subworkflow_1"; -import { getComplexSignalTestSubWf2Data } from "./metadata/complex_wf_signal_test_subworkflow_2"; -import { getWaitSignalTestWfData } from "./metadata/wait_signal_test"; +import { getComplexSignalTestWfDef } from "./metadata/complex_wf_signal_test"; +import { getComplexSignalTestSubWf1Def } from "./metadata/complex_wf_signal_test_subworkflow_1"; +import { getComplexSignalTestSubWf2Def } from "./metadata/complex_wf_signal_test_subworkflow_2"; +import { getWaitSignalTestWfDef } from "./metadata/wait_signal_test"; describe("Execute with Return Strategy and Consistency", () => { // Constants specific to this test suite const now = Date.now(); const WORKFLOWS = { - COMPLEX_WF: getComplexSignalTestWfData(now), - SUB_WF_1: getComplexSignalTestSubWf1Data(now), - SUB_WF_2: getComplexSignalTestSubWf2Data(now), - WAIT_SIGNAL_TEST: getWaitSignalTestWfData(now) + COMPLEX_WF: getComplexSignalTestWfDef(now), + SUB_WF_1: getComplexSignalTestSubWf1Def(now), + SUB_WF_2: getComplexSignalTestSubWf2Def(now), + WAIT_SIGNAL_TEST: getWaitSignalTestWfDef(now) }; const clientPromise = orkesConductorClient(); diff --git a/integration-tests/v5-only/metadata/complex_wf_signal_test.ts b/integration-tests/v5-only/metadata/complex_wf_signal_test.ts index 038bc178..954cfee8 100644 --- a/integration-tests/v5-only/metadata/complex_wf_signal_test.ts +++ b/integration-tests/v5-only/metadata/complex_wf_signal_test.ts @@ -1,4 +1,4 @@ -export const getComplexSignalTestWfData = (date: number) => { +export const getComplexSignalTestWfDef = (date: number) => { return { createTime: 1744299182957, updateTime: 1744299435683, diff --git a/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.ts b/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.ts index cc6af9bd..b7e4cc2b 100644 --- a/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.ts +++ b/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_1.ts @@ -1,4 +1,4 @@ -export const getComplexSignalTestSubWf1Data = (date: number) => { +export const getComplexSignalTestSubWf1Def = (date: number) => { return { createTime: 1744299356718, updateTime: 1744287643769, diff --git a/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.ts b/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.ts index 1906ffbc..56c5d8b2 100644 --- a/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.ts +++ b/integration-tests/v5-only/metadata/complex_wf_signal_test_subworkflow_2.ts @@ -1,4 +1,4 @@ -export const getComplexSignalTestSubWf2Data = (date: number) => { +export const getComplexSignalTestSubWf2Def = (date: number) => { return { createTime: 1744299371396, updateTime: 0, diff --git a/integration-tests/v5-only/metadata/wait_signal_test.ts b/integration-tests/v5-only/metadata/wait_signal_test.ts index ed1ea3d8..6e17026f 100644 --- a/integration-tests/v5-only/metadata/wait_signal_test.ts +++ b/integration-tests/v5-only/metadata/wait_signal_test.ts @@ -1,4 +1,4 @@ -export const getWaitSignalTestWfData = (date: number) => { +export const getWaitSignalTestWfDef = (date: number) => { return { createTime: 1744183953775, updateTime: 0,