Skip to content

Commit b39d064

Browse files
this is not related to the metrics change, just trying to get some excessively flaky tests to maybe not need to be run five+ times to pass
1 parent 4e5f3b1 commit b39d064

9 files changed

Lines changed: 39 additions & 22 deletions

File tree

src/integration-tests/E2EFiveTaskWorkflow.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ import {
1111
WorkflowExecutor,
1212
clearWorkerRegistry,
1313
OrkesClients,
14-
orkesConductorClient,
1514
simpleTask,
1615
worker,
1716
} from "../sdk";
1817
import { cleanupWorkflowsAndTasks } from "./utils/cleanup";
1918
import { waitForWorkflowStatus } from "./utils/waitForWorkflowStatus";
2019
import { describeForOrkesV5 } from "./utils/customJestDescribe";
20+
import { createClientWithRetry } from "./utils/createClientWithRetry";
2121

2222
describeForOrkesV5("E2E: 5-task workflow × 50 executions", () => {
23-
const clientPromise: Promise<Client> = orkesConductorClient();
23+
const clientPromise: Promise<Client> = createClientWithRetry();
2424
let executor: WorkflowExecutor;
2525
let handler: TaskHandler | undefined;
2626

src/integration-tests/MetadataClient.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import { expect, describe, test, jest } from "@jest/globals";
22
import {
33
MetadataClient,
44
taskDefinition,
5-
orkesConductorClient,
65
} from "../sdk";
6+
import { createClientWithRetry } from "./utils/createClientWithRetry";
77

88
describe("MetadataClient", () => {
9-
const clientPromise = orkesConductorClient();
9+
const clientPromise = createClientWithRetry();
1010
const taskName = `jsSdkTest-test_task_definition-${Date.now()}`;
1111

1212
jest.setTimeout(60000);

src/integration-tests/SchemaClient.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { expect, describe, test, jest, beforeAll, afterAll } from "@jest/globals";
22
import {
3-
orkesConductorClient,
43
OrkesClients,
54
SchemaClient,
65
} from "../sdk";
6+
import { createClientWithRetry } from "./utils/createClientWithRetry";
77
import { describeForOrkesV5 } from "./utils/customJestDescribe";
88

99
/**
@@ -16,7 +16,7 @@ import { describeForOrkesV5 } from "./utils/customJestDescribe";
1616
describeForOrkesV5("SchemaClient", () => {
1717
jest.setTimeout(60000);
1818

19-
const clientPromise = orkesConductorClient();
19+
const clientPromise = createClientWithRetry();
2020
const suffix = Date.now();
2121

2222
let schemaClient: SchemaClient;

src/integration-tests/ServiceRegistryClient.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { beforeAll, afterEach, expect, jest, test } from "@jest/globals";
22
import { ServiceRegistryClient } from "../sdk/clients/service-registry";
3-
import { orkesConductorClient } from "../sdk/createConductorClient";
3+
import { createClientWithRetry } from "./utils/createClientWithRetry";
44
import { ServiceType } from "../open-api";
55
import * as fs from "fs";
66
import * as path from "path";
@@ -13,7 +13,7 @@ const TEST_SERVICE_URI =
1313
"http://httpbin-server:8081/api-docs";
1414

1515
describeForOrkesV5("ServiceRegistryClient", () => {
16-
const clientPromise = orkesConductorClient();
16+
const clientPromise = createClientWithRetry();
1717
let serviceRegistryClient: ServiceRegistryClient;
1818

1919
const testServicesToCleanup: string[] = [];

src/integration-tests/WorkflowExecutor.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ import {
2222
TaskClient,
2323
MetadataClient,
2424
WorkflowExecutor,
25-
orkesConductorClient,
2625
} from "../sdk";
2726
import { cleanupWorkflowsAndTasks } from "./utils/cleanup";
27+
import { createClientWithRetry } from "./utils/createClientWithRetry";
2828
import { waitForWorkflowStatus } from "./utils/waitForWorkflowStatus";
2929
import { getComplexSignalTestWfDef } from "./metadata/complex_wf_signal_test";
3030
import { getComplexSignalTestSubWf1Def } from "./metadata/complex_wf_signal_test_subworkflow_1";
@@ -33,7 +33,7 @@ import { getWaitSignalTestWfDef } from "./metadata/wait_signal_test";
3333
import { describeForOrkesV4, describeForOrkesV5 } from "./utils/customJestDescribe";
3434

3535
describe("WorkflowExecutor", () => {
36-
const clientPromise = orkesConductorClient();
36+
const clientPromise = createClientWithRetry();
3737

3838
jest.setTimeout(60000);
3939

@@ -291,7 +291,7 @@ describe("WorkflowExecutor", () => {
291291
WAIT_SIGNAL_TEST: getWaitSignalTestWfDef(now),
292292
};
293293

294-
const clientPromise = orkesConductorClient();
294+
const clientPromise = createClientWithRetry();
295295
jest.setTimeout(300000);
296296

297297
let client: Client;

src/integration-tests/readme.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import { expect, describe, test, jest, afterAll } from "@jest/globals";
22
import {
3-
orkesConductorClient,
43
TaskRunner,
54
WorkflowExecutor,
65
simpleTask,
76
generate,
87
MetadataClient,
98
} from "../sdk";
9+
import { createClientWithRetry } from "./utils/createClientWithRetry";
1010
import { TaskType } from "../open-api";
1111
import { waitForWorkflowStatus } from "./utils/waitForWorkflowStatus";
1212

1313
describe("TaskManager", () => {
14-
const clientPromise = orkesConductorClient();
14+
const clientPromise = createClientWithRetry();
1515
const workflowsToCleanup: { name: string; version: number }[] = [];
1616

1717
jest.setTimeout(60000);

src/sdk/createConductorClient/__tests__/createConductorClient.test.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
import { jest, expect, describe, it, beforeEach } from "@jest/globals";
2+
import { MAX_AUTH_BACKOFF_MS, MAX_INITIAL_TOKEN_RETRIES } from "../constants";
3+
4+
const INITIAL_AUTH_TOTAL_BACKOFF_MS = Array.from(
5+
{ length: MAX_INITIAL_TOKEN_RETRIES - 1 },
6+
(_, i) => Math.min(Math.pow(2, i) * 1000, MAX_AUTH_BACKOFF_MS)
7+
).reduce((a, b) => a + b, 0);
28

39
// Mock undici to avoid ts-jest compilation failure on missing module
410
jest.mock("../helpers/getUndiciHttp2FetchFn", () => ({
@@ -176,9 +182,10 @@ describe("createConductorClient integration", () => {
176182
});
177183

178184
it("should throw when initial auth fails", async () => {
185+
jest.useFakeTimers();
179186
mockedGenerateToken.mockResolvedValue(tokenFailure("Bad credentials"));
180187

181-
await expect(
188+
const assertion = expect(
182189
createConductorClient(
183190
{
184191
serverUrl: "http://localhost:8080",
@@ -188,6 +195,12 @@ describe("createConductorClient integration", () => {
188195
async () => jsonResponse({})
189196
)
190197
).rejects.toThrow("Failed to generate authorization token");
198+
199+
// Advance past all initial-auth retry backoff delays
200+
await jest.advanceTimersByTimeAsync(INITIAL_AUTH_TOTAL_BACKOFF_MS);
201+
await assertion;
202+
203+
jest.useRealTimers();
191204
});
192205
});
193206

src/sdk/createConductorClient/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export const MAX_HTTP2_CONNECTIONS = 10;
55
export const TOKEN_TTL_MS = 2_700_000; // 45 minutes - refresh token before it expires
66
export const MAX_AUTH_FAILURES = 5; // stop logging errors after this many consecutive failures
77
export const MAX_AUTH_BACKOFF_MS = 60_000; // 60s cap on exponential backoff
8-
export const MAX_INITIAL_TOKEN_RETRIES = 3; // retry initial token request on transient failures
8+
export const MAX_INITIAL_TOKEN_RETRIES = 8; // retry initial token request on transient failures (covers ~3min of 503s)
99

1010
// Fetch retry
1111
export const MAX_TRANSPORT_RETRIES = 3;

src/sdk/createConductorClient/helpers/__tests__/handleAuth.test.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@ import { handleAuth } from "../handleAuth";
44
import { TokenResource } from "../../../../open-api/generated";
55
import type { Client } from "../../../../open-api/generated/client/types.gen";
66
import type { ConductorLogger } from "../../../helpers/logger";
7-
import { TOKEN_TTL_MS, MAX_AUTH_FAILURES, MAX_INITIAL_TOKEN_RETRIES } from "../../constants";
7+
import { TOKEN_TTL_MS, MAX_AUTH_FAILURES, MAX_AUTH_BACKOFF_MS, MAX_INITIAL_TOKEN_RETRIES } from "../../constants";
8+
9+
/** Total fake-time needed to exhaust all initial-auth retry backoffs. */
10+
const INITIAL_AUTH_TOTAL_BACKOFF_MS = Array.from(
11+
{ length: MAX_INITIAL_TOKEN_RETRIES - 1 },
12+
(_, i) => Math.min(Math.pow(2, i) * 1000, MAX_AUTH_BACKOFF_MS)
13+
).reduce((a, b) => a + b, 0);
814

915
// Mock TokenResource.generateToken
1016
jest.mock("../../../../open-api/generated", () => ({
@@ -117,8 +123,7 @@ describe("handleAuth", () => {
117123
handleAuth(mockClient as unknown as Client, "key-id", "key-secret", 3600000, mockLogger)
118124
).rejects.toThrow("Failed to generate authorization token");
119125

120-
// Advance past all retry backoff delays (1s + 2s = 3s)
121-
await jest.advanceTimersByTimeAsync(3000);
126+
await jest.advanceTimersByTimeAsync(INITIAL_AUTH_TOTAL_BACKOFF_MS);
122127
await assertion;
123128

124129
expect(mockedGenerateToken).toHaveBeenCalledTimes(MAX_INITIAL_TOKEN_RETRIES);
@@ -141,8 +146,7 @@ describe("handleAuth", () => {
141146

142147
const p = handleAuth(mockClient as unknown as Client, "key-id", "key-secret", 3600000, mockLogger);
143148

144-
// Advance past retry backoff delays
145-
await jest.advanceTimersByTimeAsync(3000);
149+
await jest.advanceTimersByTimeAsync(INITIAL_AUTH_TOTAL_BACKOFF_MS);
146150

147151
const result = await p;
148152
expect(result).toBeDefined();
@@ -164,7 +168,7 @@ describe("handleAuth", () => {
164168
handleAuth(mockClient as unknown as Client, "key-id", "key-secret", 3600000, mockLogger)
165169
).rejects.toThrow("Failed to generate authorization token");
166170

167-
await jest.advanceTimersByTimeAsync(3000);
171+
await jest.advanceTimersByTimeAsync(INITIAL_AUTH_TOTAL_BACKOFF_MS);
168172
await assertion;
169173

170174
expect(mockLogger.debug).toHaveBeenCalledWith(
@@ -184,7 +188,7 @@ describe("handleAuth", () => {
184188
handleAuth(mockClient as unknown as Client, "key-id", "key-secret", 3600000, mockLogger)
185189
).rejects.toThrow("Failed to generate authorization token");
186190

187-
await jest.advanceTimersByTimeAsync(3000);
191+
await jest.advanceTimersByTimeAsync(INITIAL_AUTH_TOTAL_BACKOFF_MS);
188192
await assertion;
189193

190194
expect(mockLogger.debug).toHaveBeenCalledWith(

0 commit comments

Comments
 (0)