Skip to content

Commit 8ac6ad4

Browse files
committed
test(schedule-engine): split scheduleEngine.test.ts so its two heavy cases shard apart
1 parent 3f5ac08 commit 8ac6ad4

3 files changed

Lines changed: 115 additions & 106 deletions

File tree

internal-packages/schedule-engine/test/scheduleEngine.test.ts

Lines changed: 0 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -239,108 +239,4 @@ describe("ScheduleEngine Integration", () => {
239239
}
240240
}
241241
);
242-
243-
// Deploy-moment backward compatibility. At deploy time, in-flight Redis jobs
244-
// were enqueued by the old engine — their payload has no `lastScheduleTime`
245-
// field — and `instance.lastScheduledTimestamp` is still populated (last
246-
// written by the old engine pre-deploy). The new engine must report that DB
247-
// value as `payload.lastTimestamp` so customers don't see a transient
248-
// `undefined` for the one fire per schedule that drains the legacy queue.
249-
containerTest(
250-
"should fall back to instance.lastScheduledTimestamp when payload lacks lastScheduleTime",
251-
{ timeout: 30_000 },
252-
async ({ prisma, redisOptions }) => {
253-
const triggerCalls: TriggerScheduledTaskParams[] = [];
254-
const engine = new ScheduleEngine({
255-
prisma,
256-
redis: redisOptions,
257-
distributionWindow: { seconds: 10 },
258-
worker: {
259-
concurrency: 1,
260-
disabled: true, // Don't actually run the worker — calling triggerScheduledTask directly
261-
pollIntervalMs: 1000,
262-
},
263-
tracer: trace.getTracer("test", "0.0.0"),
264-
onTriggerScheduledTask: async (params) => {
265-
triggerCalls.push(params);
266-
return { success: true };
267-
},
268-
isDevEnvironmentConnectedHandler: vi.fn().mockResolvedValue(true),
269-
});
270-
271-
try {
272-
const organization = await prisma.organization.create({
273-
data: { title: "Legacy Payload Org", slug: "legacy-payload-org" },
274-
});
275-
276-
const project = await prisma.project.create({
277-
data: {
278-
name: "Legacy Payload Project",
279-
slug: "legacy-payload-project",
280-
externalRef: "legacy-payload-ref",
281-
organizationId: organization.id,
282-
},
283-
});
284-
285-
const environment = await prisma.runtimeEnvironment.create({
286-
data: {
287-
slug: "legacy-payload-env",
288-
type: "PRODUCTION",
289-
projectId: project.id,
290-
organizationId: organization.id,
291-
apiKey: "tr_legacy_1234",
292-
pkApiKey: "pk_legacy_1234",
293-
shortcode: "legacy-short",
294-
},
295-
});
296-
297-
const taskSchedule = await prisma.taskSchedule.create({
298-
data: {
299-
friendlyId: "sched_legacy_payload",
300-
taskIdentifier: "legacy-payload-task",
301-
projectId: project.id,
302-
deduplicationKey: "legacy-payload-dedup",
303-
userProvidedDeduplicationKey: false,
304-
generatorExpression: "*/5 * * * *",
305-
generatorDescription: "Every 5 minutes",
306-
timezone: "UTC",
307-
type: "DECLARATIVE",
308-
active: true,
309-
externalId: "legacy-ext",
310-
},
311-
});
312-
313-
// Pre-populate lastScheduledTimestamp on the instance — simulates the
314-
// value the old engine wrote to the DB before this PR deployed.
315-
const preDeployLastFire = new Date("2026-04-30T10:00:00.000Z");
316-
const scheduleInstance = await prisma.taskScheduleInstance.create({
317-
data: {
318-
taskScheduleId: taskSchedule.id,
319-
environmentId: environment.id,
320-
projectId: project.id,
321-
active: true,
322-
lastScheduledTimestamp: preDeployLastFire,
323-
},
324-
});
325-
326-
// Call triggerScheduledTask directly without lastScheduleTime,
327-
// simulating an in-flight Redis job enqueued by the old engine.
328-
const exactScheduleTime = new Date("2026-04-30T10:05:00.000Z");
329-
await engine.triggerScheduledTask({
330-
instanceId: scheduleInstance.id,
331-
finalAttempt: false,
332-
exactScheduleTime,
333-
// lastScheduleTime intentionally omitted — legacy payload shape
334-
});
335-
336-
expect(triggerCalls.length).toBe(1);
337-
expect(triggerCalls[0].payload.timestamp).toEqual(exactScheduleTime);
338-
// Falls back to instance.lastScheduledTimestamp from the DB rather
339-
// than reporting undefined for this one transitional fire.
340-
expect(triggerCalls[0].payload.lastTimestamp).toEqual(preDeployLastFire);
341-
} finally {
342-
await engine.quit();
343-
}
344-
}
345-
);
346242
});
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { containerTest } from "@internal/testcontainers";
2+
import { trace } from "@internal/tracing";
3+
import { setTimeout } from "timers/promises";
4+
import { describe, expect, vi } from "vitest";
5+
import { TriggerScheduledTaskParams } from "../src/engine/types.js";
6+
import { ScheduleEngine } from "../src/index.js";
7+
8+
describe("ScheduleEngine Integration (part 2)", () => {
9+
// Deploy-moment backward compatibility. At deploy time, in-flight Redis jobs
10+
// were enqueued by the old engine — their payload has no `lastScheduleTime`
11+
// field — and `instance.lastScheduledTimestamp` is still populated (last
12+
// written by the old engine pre-deploy). The new engine must report that DB
13+
// value as `payload.lastTimestamp` so customers don't see a transient
14+
// `undefined` for the one fire per schedule that drains the legacy queue.
15+
containerTest(
16+
"should fall back to instance.lastScheduledTimestamp when payload lacks lastScheduleTime",
17+
{ timeout: 30_000 },
18+
async ({ prisma, redisOptions }) => {
19+
const triggerCalls: TriggerScheduledTaskParams[] = [];
20+
const engine = new ScheduleEngine({
21+
prisma,
22+
redis: redisOptions,
23+
distributionWindow: { seconds: 10 },
24+
worker: {
25+
concurrency: 1,
26+
disabled: true, // Don't actually run the worker — calling triggerScheduledTask directly
27+
pollIntervalMs: 1000,
28+
},
29+
tracer: trace.getTracer("test", "0.0.0"),
30+
onTriggerScheduledTask: async (params) => {
31+
triggerCalls.push(params);
32+
return { success: true };
33+
},
34+
isDevEnvironmentConnectedHandler: vi.fn().mockResolvedValue(true),
35+
});
36+
37+
try {
38+
const organization = await prisma.organization.create({
39+
data: { title: "Legacy Payload Org", slug: "legacy-payload-org" },
40+
});
41+
42+
const project = await prisma.project.create({
43+
data: {
44+
name: "Legacy Payload Project",
45+
slug: "legacy-payload-project",
46+
externalRef: "legacy-payload-ref",
47+
organizationId: organization.id,
48+
},
49+
});
50+
51+
const environment = await prisma.runtimeEnvironment.create({
52+
data: {
53+
slug: "legacy-payload-env",
54+
type: "PRODUCTION",
55+
projectId: project.id,
56+
organizationId: organization.id,
57+
apiKey: "tr_legacy_1234",
58+
pkApiKey: "pk_legacy_1234",
59+
shortcode: "legacy-short",
60+
},
61+
});
62+
63+
const taskSchedule = await prisma.taskSchedule.create({
64+
data: {
65+
friendlyId: "sched_legacy_payload",
66+
taskIdentifier: "legacy-payload-task",
67+
projectId: project.id,
68+
deduplicationKey: "legacy-payload-dedup",
69+
userProvidedDeduplicationKey: false,
70+
generatorExpression: "*/5 * * * *",
71+
generatorDescription: "Every 5 minutes",
72+
timezone: "UTC",
73+
type: "DECLARATIVE",
74+
active: true,
75+
externalId: "legacy-ext",
76+
},
77+
});
78+
79+
// Pre-populate lastScheduledTimestamp on the instance — simulates the
80+
// value the old engine wrote to the DB before this PR deployed.
81+
const preDeployLastFire = new Date("2026-04-30T10:00:00.000Z");
82+
const scheduleInstance = await prisma.taskScheduleInstance.create({
83+
data: {
84+
taskScheduleId: taskSchedule.id,
85+
environmentId: environment.id,
86+
projectId: project.id,
87+
active: true,
88+
lastScheduledTimestamp: preDeployLastFire,
89+
},
90+
});
91+
92+
// Call triggerScheduledTask directly without lastScheduleTime,
93+
// simulating an in-flight Redis job enqueued by the old engine.
94+
const exactScheduleTime = new Date("2026-04-30T10:05:00.000Z");
95+
await engine.triggerScheduledTask({
96+
instanceId: scheduleInstance.id,
97+
finalAttempt: false,
98+
exactScheduleTime,
99+
// lastScheduleTime intentionally omitted — legacy payload shape
100+
});
101+
102+
expect(triggerCalls.length).toBe(1);
103+
expect(triggerCalls[0].payload.timestamp).toEqual(exactScheduleTime);
104+
// Falls back to instance.lastScheduledTimestamp from the DB rather
105+
// than reporting undefined for this one transitional fire.
106+
expect(triggerCalls[0].payload.lastTimestamp).toEqual(preDeployLastFire);
107+
} finally {
108+
await engine.quit();
109+
}
110+
}
111+
);
112+
});

test-timings.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@
186186
"internal-packages/run-engine/src/run-queue/tests/releaseConcurrency.test.ts": 3018,
187187
"internal-packages/run-engine/src/run-queue/tests/workerQueueResolver.test.ts": 38,
188188
"internal-packages/cache/src/stores/lruMemory.test.ts": 44,
189-
"internal-packages/schedule-engine/test/scheduleEngine.test.ts": 86309,
189+
"internal-packages/schedule-engine/test/scheduleEngine.test.ts": 43000,
190190
"internal-packages/schedule-engine/test/scheduleRecovery.test.ts": 17396,
191191
"internal-packages/replication/src/client.test.ts": 31306,
192192
"internal-packages/tsql/src/index.test.ts": 246,
@@ -217,5 +217,6 @@
217217
"apps/webapp/test/runsReplicationService.part6.test.ts": 32000,
218218
"apps/webapp/test/runsRepository.part3.test.ts": 43000,
219219
"apps/webapp/test/runsRepository.part4.test.ts": 57000,
220-
"apps/webapp/test/runsReplicationService.part7.test.ts": 43000
220+
"apps/webapp/test/runsReplicationService.part7.test.ts": 43000,
221+
"internal-packages/schedule-engine/test/scheduleEngine2.test.ts": 43000
221222
}

0 commit comments

Comments
 (0)