@meetploy/emulator 1.11.0 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundler/bundler.d.ts +1 -1
- package/dist/bundler/bundler.js +3 -1
- package/dist/bundler/bundler.js.map +1 -1
- package/dist/config/ploy-config.d.ts +3 -2
- package/dist/config/ploy-config.js +2 -1
- package/dist/config/ploy-config.js.map +1 -1
- package/dist/dashboard-dist/assets/main-lVJJjCAs.js +354 -0
- package/dist/dashboard-dist/assets/main-pms28kEu.css +1 -0
- package/dist/dashboard-dist/index.html +2 -2
- package/dist/nextjs-dev.js +3 -3
- package/dist/services/dashboard-routes.js +53 -9
- package/dist/services/dashboard-routes.js.map +1 -1
- package/dist/services/mock-server.js +33 -2
- package/dist/services/mock-server.js.map +1 -1
- package/dist/services/workflow-service.d.ts +9 -0
- package/dist/services/workflow-service.js +146 -9
- package/dist/services/workflow-service.js.map +1 -1
- package/dist/services/workflow-service.spec.d.ts +1 -0
- package/dist/services/workflow-service.spec.js +394 -0
- package/dist/services/workflow-service.spec.js.map +1 -0
- package/dist/utils/sqlite.d.ts +1 -1
- package/dist/utils/sqlite.js +7 -7
- package/dist/utils/sqlite.js.map +1 -1
- package/package.json +1 -1
- package/dist/dashboard-dist/assets/main-5Kt9I_hM.css +0 -1
- package/dist/dashboard-dist/assets/main-BFhQn9QT.js +0 -354
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { Hono } from "hono";
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
|
4
|
+
import { openDatabase } from "../utils/sqlite-db.js";
|
|
5
|
+
import { createWorkflowHandlers, startStalledWorkflowRecovery, startWorkflowTimeoutEnforcement, } from "./workflow-service.js";
|
|
6
|
+
const SCHEMA = `
|
|
7
|
+
CREATE TABLE IF NOT EXISTS workflow_executions (
|
|
8
|
+
id TEXT PRIMARY KEY,
|
|
9
|
+
workflow_name TEXT NOT NULL,
|
|
10
|
+
status TEXT DEFAULT 'pending',
|
|
11
|
+
input TEXT,
|
|
12
|
+
output TEXT,
|
|
13
|
+
error TEXT,
|
|
14
|
+
started_at INTEGER,
|
|
15
|
+
completed_at INTEGER,
|
|
16
|
+
created_at INTEGER DEFAULT (strftime('%s', 'now'))
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
CREATE TABLE IF NOT EXISTS workflow_steps (
|
|
20
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
21
|
+
execution_id TEXT NOT NULL,
|
|
22
|
+
step_name TEXT NOT NULL,
|
|
23
|
+
step_index INTEGER NOT NULL,
|
|
24
|
+
status TEXT DEFAULT 'pending',
|
|
25
|
+
output TEXT,
|
|
26
|
+
error TEXT,
|
|
27
|
+
duration_ms INTEGER,
|
|
28
|
+
created_at INTEGER DEFAULT (strftime('%s', 'now')),
|
|
29
|
+
FOREIGN KEY (execution_id) REFERENCES workflow_executions(id),
|
|
30
|
+
UNIQUE (execution_id, step_name, step_index)
|
|
31
|
+
);
|
|
32
|
+
`;
|
|
33
|
+
function createTestApp(db) {
|
|
34
|
+
const handlers = createWorkflowHandlers(db);
|
|
35
|
+
const app = new Hono();
|
|
36
|
+
app.post("/workflow/trigger", handlers.triggerHandler);
|
|
37
|
+
app.post("/workflow/status", handlers.statusHandler);
|
|
38
|
+
app.post("/workflow/step/start", handlers.stepStartHandler);
|
|
39
|
+
app.post("/workflow/step/complete", handlers.stepCompleteHandler);
|
|
40
|
+
app.post("/workflow/step/fail", handlers.stepFailHandler);
|
|
41
|
+
app.post("/workflow/complete", handlers.completeHandler);
|
|
42
|
+
app.post("/workflow/fail", handlers.failHandler);
|
|
43
|
+
return app;
|
|
44
|
+
}
|
|
45
|
+
function post(app, path, body) {
|
|
46
|
+
return app.request(path, {
|
|
47
|
+
method: "POST",
|
|
48
|
+
headers: { "Content-Type": "application/json" },
|
|
49
|
+
body: JSON.stringify(body),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
describe("workflow step idempotency and resume", () => {
|
|
53
|
+
let db;
|
|
54
|
+
let app;
|
|
55
|
+
beforeEach(() => {
|
|
56
|
+
db = openDatabase(":memory:");
|
|
57
|
+
db.exec(SCHEMA);
|
|
58
|
+
app = createTestApp(db);
|
|
59
|
+
});
|
|
60
|
+
afterEach(() => {
|
|
61
|
+
db.close();
|
|
62
|
+
});
|
|
63
|
+
function insertExecution(id, opts = {}) {
|
|
64
|
+
const now = Math.floor(Date.now() / 1000);
|
|
65
|
+
db.prepare(`INSERT INTO workflow_executions (id, workflow_name, status, input, started_at, created_at)
|
|
66
|
+
VALUES (?, ?, ?, ?, ?, ?)`).run(id, opts.workflowName ?? "test_workflow", opts.status ?? "running", opts.input ? JSON.stringify(opts.input) : null, opts.startedAt ?? now, now);
|
|
67
|
+
}
|
|
68
|
+
function insertStep(executionId, stepName, stepIndex, opts = {}) {
|
|
69
|
+
const now = Math.floor(Date.now() / 1000);
|
|
70
|
+
db.prepare(`INSERT INTO workflow_steps (execution_id, step_name, step_index, status, output, error, created_at)
|
|
71
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`).run(executionId, stepName, stepIndex, opts.status ?? "running", opts.output ? JSON.stringify(opts.output) : null, opts.error ?? null, now);
|
|
72
|
+
}
|
|
73
|
+
test("completed step returns cached output (idempotency)", async () => {
|
|
74
|
+
const executionId = randomUUID();
|
|
75
|
+
insertExecution(executionId);
|
|
76
|
+
insertStep(executionId, "step_1", 0, {
|
|
77
|
+
status: "completed",
|
|
78
|
+
output: { result: 42 },
|
|
79
|
+
});
|
|
80
|
+
const res = await post(app, "/workflow/step/start", {
|
|
81
|
+
executionId,
|
|
82
|
+
stepName: "step_1",
|
|
83
|
+
stepIndex: 0,
|
|
84
|
+
});
|
|
85
|
+
const body = (await res.json());
|
|
86
|
+
expect(body.success).toBe(true);
|
|
87
|
+
expect(body.alreadyCompleted).toBe(true);
|
|
88
|
+
expect(body.output).toEqual({ result: 42 });
|
|
89
|
+
});
|
|
90
|
+
test("running step is reset and returned as not completed (resume after crash)", async () => {
|
|
91
|
+
const executionId = randomUUID();
|
|
92
|
+
insertExecution(executionId);
|
|
93
|
+
insertStep(executionId, "step_2", 1, { status: "running" });
|
|
94
|
+
const res = await post(app, "/workflow/step/start", {
|
|
95
|
+
executionId,
|
|
96
|
+
stepName: "step_2",
|
|
97
|
+
stepIndex: 1,
|
|
98
|
+
});
|
|
99
|
+
const body = (await res.json());
|
|
100
|
+
expect(body.success).toBe(true);
|
|
101
|
+
expect(body.alreadyCompleted).toBe(false);
|
|
102
|
+
const step = db
|
|
103
|
+
.prepare(`SELECT status, error FROM workflow_steps WHERE execution_id = ? AND step_name = ?`)
|
|
104
|
+
.get(executionId, "step_2");
|
|
105
|
+
expect(step.status).toBe("running");
|
|
106
|
+
expect(step.error).toBeNull();
|
|
107
|
+
});
|
|
108
|
+
test("failed step is reset and returned as not completed (resume after crash)", async () => {
|
|
109
|
+
const executionId = randomUUID();
|
|
110
|
+
insertExecution(executionId);
|
|
111
|
+
insertStep(executionId, "step_3", 2, {
|
|
112
|
+
status: "failed",
|
|
113
|
+
error: "previous error",
|
|
114
|
+
});
|
|
115
|
+
const res = await post(app, "/workflow/step/start", {
|
|
116
|
+
executionId,
|
|
117
|
+
stepName: "step_3",
|
|
118
|
+
stepIndex: 2,
|
|
119
|
+
});
|
|
120
|
+
const body = (await res.json());
|
|
121
|
+
expect(body.success).toBe(true);
|
|
122
|
+
expect(body.alreadyCompleted).toBe(false);
|
|
123
|
+
const step = db
|
|
124
|
+
.prepare(`SELECT status, error FROM workflow_steps WHERE execution_id = ? AND step_name = ?`)
|
|
125
|
+
.get(executionId, "step_3");
|
|
126
|
+
expect(step.status).toBe("running");
|
|
127
|
+
expect(step.error).toBeNull();
|
|
128
|
+
});
|
|
129
|
+
test("new step is created when none exists", async () => {
|
|
130
|
+
const executionId = randomUUID();
|
|
131
|
+
insertExecution(executionId);
|
|
132
|
+
const res = await post(app, "/workflow/step/start", {
|
|
133
|
+
executionId,
|
|
134
|
+
stepName: "new_step",
|
|
135
|
+
stepIndex: 0,
|
|
136
|
+
});
|
|
137
|
+
const body = (await res.json());
|
|
138
|
+
expect(body.success).toBe(true);
|
|
139
|
+
expect(body.alreadyCompleted).toBe(false);
|
|
140
|
+
const step = db
|
|
141
|
+
.prepare(`SELECT status FROM workflow_steps WHERE execution_id = ? AND step_name = ?`)
|
|
142
|
+
.get(executionId, "new_step");
|
|
143
|
+
expect(step.status).toBe("running");
|
|
144
|
+
});
|
|
145
|
+
test("full workflow replay: completed steps skipped, pending steps re-execute", async () => {
|
|
146
|
+
const executionId = randomUUID();
|
|
147
|
+
insertExecution(executionId);
|
|
148
|
+
for (let i = 0; i < 5; i++) {
|
|
149
|
+
insertStep(executionId, `step_${i}`, i, {
|
|
150
|
+
status: "completed",
|
|
151
|
+
output: { value: i * 10 },
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
insertStep(executionId, "step_5", 5, { status: "running" });
|
|
155
|
+
for (let i = 0; i < 10; i++) {
|
|
156
|
+
const res = await post(app, "/workflow/step/start", {
|
|
157
|
+
executionId,
|
|
158
|
+
stepName: `step_${i}`,
|
|
159
|
+
stepIndex: i,
|
|
160
|
+
});
|
|
161
|
+
const body = (await res.json());
|
|
162
|
+
expect(body.success).toBe(true);
|
|
163
|
+
if (i < 5) {
|
|
164
|
+
expect(body.alreadyCompleted).toBe(true);
|
|
165
|
+
expect(body.output).toEqual({ value: i * 10 });
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
expect(body.alreadyCompleted).toBe(false);
|
|
169
|
+
}
|
|
170
|
+
if (!body.alreadyCompleted) {
|
|
171
|
+
await post(app, "/workflow/step/complete", {
|
|
172
|
+
executionId,
|
|
173
|
+
stepName: `step_${i}`,
|
|
174
|
+
stepIndex: i,
|
|
175
|
+
output: { value: i * 10 },
|
|
176
|
+
durationMs: 50,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
const steps = db
|
|
181
|
+
.prepare(`SELECT step_name, status FROM workflow_steps WHERE execution_id = ? ORDER BY step_index`)
|
|
182
|
+
.all(executionId);
|
|
183
|
+
expect(steps).toHaveLength(10);
|
|
184
|
+
for (const step of steps) {
|
|
185
|
+
expect(step.status).toBe("completed");
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
describe("stalled workflow recovery", () => {
|
|
190
|
+
let db;
|
|
191
|
+
beforeEach(() => {
|
|
192
|
+
db = openDatabase(":memory:");
|
|
193
|
+
db.exec(SCHEMA);
|
|
194
|
+
vi.useFakeTimers();
|
|
195
|
+
});
|
|
196
|
+
afterEach(() => {
|
|
197
|
+
vi.useRealTimers();
|
|
198
|
+
vi.unstubAllGlobals();
|
|
199
|
+
db.close();
|
|
200
|
+
});
|
|
201
|
+
test("recovers workflows that have been running longer than the stall timeout", async () => {
|
|
202
|
+
const fetchSpy = vi.fn().mockResolvedValue(new Response("ok"));
|
|
203
|
+
vi.stubGlobal("fetch", fetchSpy);
|
|
204
|
+
const executionId = randomUUID();
|
|
205
|
+
const oneHundredTenMinutesAgo = Math.floor(Date.now() / 1000) - 110 * 60;
|
|
206
|
+
db.prepare(`INSERT INTO workflow_executions (id, workflow_name, status, input, started_at, created_at)
|
|
207
|
+
VALUES (?, ?, 'running', ?, ?, ?)`).run(executionId, "stalled_workflow", JSON.stringify({ data: 1 }), oneHundredTenMinutesAgo, oneHundredTenMinutesAgo);
|
|
208
|
+
db.prepare(`INSERT INTO workflow_steps (execution_id, step_name, step_index, status, created_at)
|
|
209
|
+
VALUES (?, ?, ?, 'running', ?)`).run(executionId, "stuck_step", 0, oneHundredTenMinutesAgo);
|
|
210
|
+
const interval = startStalledWorkflowRecovery(db, "http://localhost:9999", 100);
|
|
211
|
+
await vi.advanceTimersByTimeAsync(200);
|
|
212
|
+
clearInterval(interval);
|
|
213
|
+
const step = db
|
|
214
|
+
.prepare(`SELECT status FROM workflow_steps WHERE execution_id = ? AND step_name = ?`)
|
|
215
|
+
.get(executionId, "stuck_step");
|
|
216
|
+
expect(step.status).toBe("pending");
|
|
217
|
+
const execution = db
|
|
218
|
+
.prepare(`SELECT started_at FROM workflow_executions WHERE id = ?`)
|
|
219
|
+
.get(executionId);
|
|
220
|
+
expect(execution.started_at).toBeGreaterThan(oneHundredTenMinutesAgo);
|
|
221
|
+
expect(fetchSpy).toHaveBeenCalledWith("http://localhost:9999", expect.objectContaining({
|
|
222
|
+
method: "POST",
|
|
223
|
+
headers: expect.objectContaining({
|
|
224
|
+
"X-Ploy-Workflow-Execution": "true",
|
|
225
|
+
"X-Ploy-Workflow-Name": "stalled_workflow",
|
|
226
|
+
"X-Ploy-Execution-Id": executionId,
|
|
227
|
+
}),
|
|
228
|
+
}));
|
|
229
|
+
});
|
|
230
|
+
test("does not recover workflows that are still within the stall timeout", async () => {
|
|
231
|
+
const fetchSpy = vi.fn().mockResolvedValue(new Response("ok"));
|
|
232
|
+
vi.stubGlobal("fetch", fetchSpy);
|
|
233
|
+
const executionId = randomUUID();
|
|
234
|
+
const oneMinuteAgo = Math.floor(Date.now() / 1000) - 60;
|
|
235
|
+
db.prepare(`INSERT INTO workflow_executions (id, workflow_name, status, input, started_at, created_at)
|
|
236
|
+
VALUES (?, ?, 'running', ?, ?, ?)`).run(executionId, "recent_workflow", null, oneMinuteAgo, oneMinuteAgo);
|
|
237
|
+
const interval = startStalledWorkflowRecovery(db, "http://localhost:9999", 100);
|
|
238
|
+
await vi.advanceTimersByTimeAsync(200);
|
|
239
|
+
clearInterval(interval);
|
|
240
|
+
expect(fetchSpy).not.toHaveBeenCalled();
|
|
241
|
+
const execution = db
|
|
242
|
+
.prepare(`SELECT status FROM workflow_executions WHERE id = ?`)
|
|
243
|
+
.get(executionId);
|
|
244
|
+
expect(execution.status).toBe("running");
|
|
245
|
+
});
|
|
246
|
+
test("does not recover completed or failed workflows", async () => {
|
|
247
|
+
const fetchSpy = vi.fn().mockResolvedValue(new Response("ok"));
|
|
248
|
+
vi.stubGlobal("fetch", fetchSpy);
|
|
249
|
+
const oneHundredTenMinutesAgo = Math.floor(Date.now() / 1000) - 110 * 60;
|
|
250
|
+
db.prepare(`INSERT INTO workflow_executions (id, workflow_name, status, input, started_at, created_at)
|
|
251
|
+
VALUES (?, ?, 'completed', null, ?, ?)`).run(randomUUID(), "done_workflow", oneHundredTenMinutesAgo, oneHundredTenMinutesAgo);
|
|
252
|
+
db.prepare(`INSERT INTO workflow_executions (id, workflow_name, status, input, started_at, created_at)
|
|
253
|
+
VALUES (?, ?, 'failed', null, ?, ?)`).run(randomUUID(), "failed_workflow", oneHundredTenMinutesAgo, oneHundredTenMinutesAgo);
|
|
254
|
+
const interval = startStalledWorkflowRecovery(db, "http://localhost:9999", 100);
|
|
255
|
+
await vi.advanceTimersByTimeAsync(200);
|
|
256
|
+
clearInterval(interval);
|
|
257
|
+
expect(fetchSpy).not.toHaveBeenCalled();
|
|
258
|
+
});
|
|
259
|
+
test("uses custom stall timeout when provided", async () => {
|
|
260
|
+
const fetchSpy = vi.fn().mockResolvedValue(new Response("ok"));
|
|
261
|
+
vi.stubGlobal("fetch", fetchSpy);
|
|
262
|
+
const executionId = randomUUID();
|
|
263
|
+
const tenMinutesAgo = Math.floor(Date.now() / 1000) - 600;
|
|
264
|
+
db.prepare(`INSERT INTO workflow_executions (id, workflow_name, status, input, started_at, created_at)
|
|
265
|
+
VALUES (?, ?, 'running', null, ?, ?)`).run(executionId, "test_workflow", tenMinutesAgo, tenMinutesAgo);
|
|
266
|
+
const interval = startStalledWorkflowRecovery(db, "http://localhost:9999", 100, 300);
|
|
267
|
+
await vi.advanceTimersByTimeAsync(200);
|
|
268
|
+
clearInterval(interval);
|
|
269
|
+
expect(fetchSpy).toHaveBeenCalled();
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
describe("workflow timeout enforcement", () => {
|
|
273
|
+
let db;
|
|
274
|
+
beforeEach(() => {
|
|
275
|
+
db = openDatabase(":memory:");
|
|
276
|
+
db.exec(SCHEMA);
|
|
277
|
+
vi.useFakeTimers();
|
|
278
|
+
});
|
|
279
|
+
afterEach(() => {
|
|
280
|
+
vi.useRealTimers();
|
|
281
|
+
db.close();
|
|
282
|
+
});
|
|
283
|
+
test("marks workflow as failed when it exceeds the configured timeout", async () => {
|
|
284
|
+
const executionId = randomUUID();
|
|
285
|
+
const fifteenMinutesAgo = Math.floor(Date.now() / 1000) - 15 * 60;
|
|
286
|
+
db.prepare(`INSERT INTO workflow_executions (id, workflow_name, status, input, started_at, created_at)
|
|
287
|
+
VALUES (?, ?, 'running', null, ?, ?)`).run(executionId, "slow_workflow", fifteenMinutesAgo, fifteenMinutesAgo);
|
|
288
|
+
const interval = startWorkflowTimeoutEnforcement(db, 100, {
|
|
289
|
+
perWorkflow: {},
|
|
290
|
+
perWorkflowStep: {},
|
|
291
|
+
defaultTimeoutS: 600,
|
|
292
|
+
defaultStepTimeoutS: 120,
|
|
293
|
+
});
|
|
294
|
+
await vi.advanceTimersByTimeAsync(200);
|
|
295
|
+
clearInterval(interval);
|
|
296
|
+
const execution = db
|
|
297
|
+
.prepare(`SELECT status, error FROM workflow_executions WHERE id = ?`)
|
|
298
|
+
.get(executionId);
|
|
299
|
+
expect(execution.status).toBe("failed");
|
|
300
|
+
expect(execution.error).toContain("exceeded timeout");
|
|
301
|
+
});
|
|
302
|
+
test("does not time out workflow that is within its timeout", async () => {
|
|
303
|
+
const executionId = randomUUID();
|
|
304
|
+
const fiveMinutesAgo = Math.floor(Date.now() / 1000) - 5 * 60;
|
|
305
|
+
db.prepare(`INSERT INTO workflow_executions (id, workflow_name, status, input, started_at, created_at)
|
|
306
|
+
VALUES (?, ?, 'running', null, ?, ?)`).run(executionId, "fast_workflow", fiveMinutesAgo, fiveMinutesAgo);
|
|
307
|
+
const interval = startWorkflowTimeoutEnforcement(db, 100, {
|
|
308
|
+
perWorkflow: {},
|
|
309
|
+
perWorkflowStep: {},
|
|
310
|
+
defaultTimeoutS: 600,
|
|
311
|
+
defaultStepTimeoutS: 120,
|
|
312
|
+
});
|
|
313
|
+
await vi.advanceTimersByTimeAsync(200);
|
|
314
|
+
clearInterval(interval);
|
|
315
|
+
const execution = db
|
|
316
|
+
.prepare(`SELECT status FROM workflow_executions WHERE id = ?`)
|
|
317
|
+
.get(executionId);
|
|
318
|
+
expect(execution.status).toBe("running");
|
|
319
|
+
});
|
|
320
|
+
test("respects per-workflow timeout configuration", async () => {
|
|
321
|
+
const shortTimeoutId = randomUUID();
|
|
322
|
+
const defaultTimeoutId = randomUUID();
|
|
323
|
+
const sevenMinutesAgo = Math.floor(Date.now() / 1000) - 7 * 60;
|
|
324
|
+
db.prepare(`INSERT INTO workflow_executions (id, workflow_name, status, input, started_at, created_at)
|
|
325
|
+
VALUES (?, ?, 'running', null, ?, ?)`).run(shortTimeoutId, "quick_workflow", sevenMinutesAgo, sevenMinutesAgo);
|
|
326
|
+
db.prepare(`INSERT INTO workflow_executions (id, workflow_name, status, input, started_at, created_at)
|
|
327
|
+
VALUES (?, ?, 'running', null, ?, ?)`).run(defaultTimeoutId, "normal_workflow", sevenMinutesAgo, sevenMinutesAgo);
|
|
328
|
+
const interval = startWorkflowTimeoutEnforcement(db, 100, {
|
|
329
|
+
perWorkflow: { quick_workflow: 300 },
|
|
330
|
+
perWorkflowStep: {},
|
|
331
|
+
defaultTimeoutS: 600,
|
|
332
|
+
defaultStepTimeoutS: 120,
|
|
333
|
+
});
|
|
334
|
+
await vi.advanceTimersByTimeAsync(200);
|
|
335
|
+
clearInterval(interval);
|
|
336
|
+
const shortExec = db
|
|
337
|
+
.prepare(`SELECT status FROM workflow_executions WHERE id = ?`)
|
|
338
|
+
.get(shortTimeoutId);
|
|
339
|
+
expect(shortExec.status).toBe("failed");
|
|
340
|
+
const defaultExec = db
|
|
341
|
+
.prepare(`SELECT status FROM workflow_executions WHERE id = ?`)
|
|
342
|
+
.get(defaultTimeoutId);
|
|
343
|
+
expect(defaultExec.status).toBe("running");
|
|
344
|
+
});
|
|
345
|
+
test("marks step and workflow as failed when step exceeds timeout", async () => {
|
|
346
|
+
const executionId = randomUUID();
|
|
347
|
+
const now = Math.floor(Date.now() / 1000);
|
|
348
|
+
const fiveMinutesAgo = now - 5 * 60;
|
|
349
|
+
db.prepare(`INSERT INTO workflow_executions (id, workflow_name, status, input, started_at, created_at)
|
|
350
|
+
VALUES (?, ?, 'running', null, ?, ?)`).run(executionId, "step_timeout_wf", fiveMinutesAgo, fiveMinutesAgo);
|
|
351
|
+
db.prepare(`INSERT INTO workflow_steps (execution_id, step_name, step_index, status, created_at)
|
|
352
|
+
VALUES (?, ?, ?, 'running', ?)`).run(executionId, "slow_step", 0, fiveMinutesAgo);
|
|
353
|
+
const interval = startWorkflowTimeoutEnforcement(db, 100, {
|
|
354
|
+
perWorkflow: {},
|
|
355
|
+
perWorkflowStep: {},
|
|
356
|
+
defaultTimeoutS: 600,
|
|
357
|
+
defaultStepTimeoutS: 120,
|
|
358
|
+
});
|
|
359
|
+
await vi.advanceTimersByTimeAsync(200);
|
|
360
|
+
clearInterval(interval);
|
|
361
|
+
const step = db
|
|
362
|
+
.prepare(`SELECT status, error FROM workflow_steps WHERE execution_id = ? AND step_name = ?`)
|
|
363
|
+
.get(executionId, "slow_step");
|
|
364
|
+
expect(step.status).toBe("failed");
|
|
365
|
+
expect(step.error).toContain("exceeded timeout");
|
|
366
|
+
const execution = db
|
|
367
|
+
.prepare(`SELECT status, error FROM workflow_executions WHERE id = ?`)
|
|
368
|
+
.get(executionId);
|
|
369
|
+
expect(execution.status).toBe("failed");
|
|
370
|
+
expect(execution.error).toContain("slow_step");
|
|
371
|
+
});
|
|
372
|
+
test("does not time out step that is within its timeout", async () => {
|
|
373
|
+
const executionId = randomUUID();
|
|
374
|
+
const now = Math.floor(Date.now() / 1000);
|
|
375
|
+
const oneMinuteAgo = now - 60;
|
|
376
|
+
db.prepare(`INSERT INTO workflow_executions (id, workflow_name, status, input, started_at, created_at)
|
|
377
|
+
VALUES (?, ?, 'running', null, ?, ?)`).run(executionId, "step_ok_wf", oneMinuteAgo, oneMinuteAgo);
|
|
378
|
+
db.prepare(`INSERT INTO workflow_steps (execution_id, step_name, step_index, status, created_at)
|
|
379
|
+
VALUES (?, ?, ?, 'running', ?)`).run(executionId, "quick_step", 0, oneMinuteAgo);
|
|
380
|
+
const interval = startWorkflowTimeoutEnforcement(db, 100, {
|
|
381
|
+
perWorkflow: {},
|
|
382
|
+
perWorkflowStep: {},
|
|
383
|
+
defaultTimeoutS: 600,
|
|
384
|
+
defaultStepTimeoutS: 120,
|
|
385
|
+
});
|
|
386
|
+
await vi.advanceTimersByTimeAsync(200);
|
|
387
|
+
clearInterval(interval);
|
|
388
|
+
const step = db
|
|
389
|
+
.prepare(`SELECT status FROM workflow_steps WHERE execution_id = ? AND step_name = ?`)
|
|
390
|
+
.get(executionId, "quick_step");
|
|
391
|
+
expect(step.status).toBe("running");
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
//# sourceMappingURL=workflow-service.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-service.spec.js","sourceRoot":"","sources":["../../src/services/workflow-service.spec.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/sqlite.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type SqliteDatabase } from "./sqlite-db.js";
|
|
2
2
|
export interface DatabaseManager {
|
|
3
3
|
emulatorDb: SqliteDatabase;
|
|
4
|
-
|
|
4
|
+
getDatabase: (bindingName: string) => SqliteDatabase;
|
|
5
5
|
close: () => void;
|
|
6
6
|
}
|
|
7
7
|
export declare function initializeDatabases(projectDir: string): DatabaseManager;
|
package/dist/utils/sqlite.js
CHANGED
|
@@ -169,29 +169,29 @@ CREATE INDEX IF NOT EXISTS idx_timer_executions_name
|
|
|
169
169
|
`;
|
|
170
170
|
export function initializeDatabases(projectDir) {
|
|
171
171
|
const dataDir = ensureDataDir(projectDir);
|
|
172
|
-
const
|
|
172
|
+
const databases = new Map();
|
|
173
173
|
const emulatorDb = openDatabase(join(dataDir, "emulator.db"));
|
|
174
174
|
emulatorDb.pragma("journal_mode = WAL");
|
|
175
175
|
emulatorDb.exec(EMULATOR_SCHEMA);
|
|
176
|
-
function
|
|
177
|
-
let db =
|
|
176
|
+
function getDatabase(bindingName) {
|
|
177
|
+
let db = databases.get(bindingName);
|
|
178
178
|
if (!db) {
|
|
179
179
|
db = openDatabase(join(dataDir, "db", `${bindingName}.db`));
|
|
180
180
|
db.pragma("journal_mode = WAL");
|
|
181
|
-
|
|
181
|
+
databases.set(bindingName, db);
|
|
182
182
|
}
|
|
183
183
|
return db;
|
|
184
184
|
}
|
|
185
185
|
function close() {
|
|
186
186
|
emulatorDb.close();
|
|
187
|
-
for (const db of
|
|
187
|
+
for (const db of databases.values()) {
|
|
188
188
|
db.close();
|
|
189
189
|
}
|
|
190
|
-
|
|
190
|
+
databases.clear();
|
|
191
191
|
}
|
|
192
192
|
return {
|
|
193
193
|
emulatorDb,
|
|
194
|
-
|
|
194
|
+
getDatabase,
|
|
195
195
|
close,
|
|
196
196
|
};
|
|
197
197
|
}
|
package/dist/utils/sqlite.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/utils/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAuB,MAAM,gBAAgB,CAAC;AAEnE,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqKvB,CAAC;AAQF,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACrD,MAAM,OAAO,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,
|
|
1
|
+
{"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/utils/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAuB,MAAM,gBAAgB,CAAC;AAEnE,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqKvB,CAAC;AAQF,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACrD,MAAM,OAAO,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEpD,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;IAC9D,UAAU,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACxC,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAEjC,SAAS,WAAW,CAAC,WAAmB;QACvC,IAAI,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACpC,IAAI,CAAC,EAAE,EAAE,CAAC;YACT,EAAE,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,WAAW,KAAK,CAAC,CAAC,CAAC;YAC5D,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;YAChC,SAAS,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,EAAE,CAAC;IACX,CAAC;IAED,SAAS,KAAK;QACb,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,KAAK,MAAM,EAAE,IAAI,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;YACrC,EAAE,CAAC,KAAK,EAAE,CAAC;QACZ,CAAC;QACD,SAAS,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;IAED,OAAO;QACN,UAAU;QACV,WAAW;QACX,KAAK;KACL,CAAC;AACH,CAAC"}
|