Skip to content

Commit 4d7bddc

Browse files
octoperclaude
andcommitted
fix(openworkflow): resolve CI failures after rebase on upstream/main
- Fix backend-concurrency.ts import path (./backend.js → ./core/backend.js) - Add missing concurrencyKey/concurrencyLimit null fields to all createWorkflowRun calls in test files that predate the concurrency feature - Add missing parentStepAttemptNamespaceId/parentStepAttemptId null fields to concurrency test calls that predate the parent linkage feature - Fix SQLite INSERT VALUES clause (was 16 values for 18 columns, missing created_at and updated_at placeholders) - Fix concurrency mismatch check and claim count query to exclude parked runs (upstream changed sleeping status to running+worker_id=null) - Fix test assertion: sleeping status is now running Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 80d1382 commit 4d7bddc

9 files changed

Lines changed: 80 additions & 9 deletions

File tree

packages/openworkflow/backend-concurrency.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { CreateWorkflowRunParams } from "./backend.js";
1+
import type { CreateWorkflowRunParams } from "./core/backend.js";
22

33
const INVALID_CONCURRENCY_KEY_TYPE_ERROR =
44
'Invalid workflow concurrency metadata: "concurrencyKey" must be a string or null.';

packages/openworkflow/client/client.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,8 @@ function createMockWorkflowRun(
810810
version: null,
811811
status: "pending",
812812
idempotencyKey: null,
813+
concurrencyKey: null,
814+
concurrencyLimit: null,
813815
config: {},
814816
context: null,
815817
input: null,

packages/openworkflow/postgres/backend.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ describe("BackendPostgres cancel fallback", () => {
187187
workflowName: "cancel-non-standard-status",
188188
version: null,
189189
idempotencyKey: null,
190+
concurrencyKey: null,
191+
concurrencyLimit: null,
190192
input: null,
191193
config: {},
192194
context: null,
@@ -233,6 +235,8 @@ describe("BackendPostgres legacy sleeping compatibility", () => {
233235
workflowName: "legacy-sleeping-claim",
234236
version: null,
235237
idempotencyKey: null,
238+
concurrencyKey: null,
239+
concurrencyLimit: null,
236240
input: null,
237241
config: {},
238242
context: null,
@@ -286,6 +290,8 @@ describe("BackendPostgres workflow wake-up reconciliation", () => {
286290
workflowName: "workflow-parent-reconcile",
287291
version: null,
288292
idempotencyKey: null,
293+
concurrencyKey: null,
294+
concurrencyLimit: null,
289295
input: null,
290296
config: {},
291297
context: null,
@@ -318,6 +324,8 @@ describe("BackendPostgres workflow wake-up reconciliation", () => {
318324
workflowName: "workflow-child-reconcile",
319325
version: null,
320326
idempotencyKey: null,
327+
concurrencyKey: null,
328+
concurrencyLimit: null,
321329
input: null,
322330
config: {},
323331
context: null,
@@ -381,6 +389,8 @@ describe("BackendPostgres workflow wake-up reconciliation", () => {
381389
workflowName: "workflow-parent-no-wake-after-failed-workflow",
382390
version: null,
383391
idempotencyKey: null,
392+
concurrencyKey: null,
393+
concurrencyLimit: null,
384394
input: null,
385395
config: {},
386396
context: null,
@@ -413,6 +423,8 @@ describe("BackendPostgres workflow wake-up reconciliation", () => {
413423
workflowName: "workflow-child-no-wake-after-failed-workflow",
414424
version: null,
415425
idempotencyKey: null,
426+
concurrencyKey: null,
427+
concurrencyLimit: null,
416428
input: null,
417429
config: {},
418430
context: null,
@@ -490,6 +502,8 @@ describe("BackendPostgres workflow wake-up reconciliation", () => {
490502
workflowName: "sleep-overwrite-stale-available-at",
491503
version: null,
492504
idempotencyKey: null,
505+
concurrencyKey: null,
506+
concurrencyLimit: null,
493507
input: null,
494508
config: {},
495509
context: null,
@@ -579,6 +593,8 @@ describe("BackendPostgres concurrency claim atomicity", () => {
579593
input: null,
580594
config: {},
581595
context: null,
596+
parentStepAttemptNamespaceId: null,
597+
parentStepAttemptId: null,
582598
availableAt: null,
583599
deadlineAt: null,
584600
});

packages/openworkflow/postgres/backend.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -293,9 +293,11 @@ export class BackendPostgres implements Backend {
293293
AND "workflow_name" = ${params.workflowName}
294294
AND "version" IS NOT DISTINCT FROM ${params.version}
295295
AND "concurrency_key" IS NOT DISTINCT FROM ${params.key}
296-
-- Sleeping runs are excluded so long sleeps do not pin historical
297-
-- limits and block new run creation after config changes.
298-
AND "status" IN ('pending', 'running')
296+
-- Parked/sleeping runs (worker_id IS NULL, status 'running') are excluded
297+
-- so long sleeps do not pin historical limits and block new run creation
298+
-- after config changes. Pending runs are included since they're not yet
299+
-- leased but will be soon.
300+
AND ("status" = 'pending' OR ("status" = 'running' AND "worker_id" IS NOT NULL))
299301
AND "concurrency_limit" IS DISTINCT FROM ${params.limit}
300302
LIMIT 1
301303
`;
@@ -452,6 +454,7 @@ export class BackendPostgres implements Backend {
452454
AND active."version" IS NOT DISTINCT FROM wr."version"
453455
AND active."concurrency_key" IS NOT DISTINCT FROM wr."concurrency_key"
454456
AND active."status" = 'running'
457+
AND active."worker_id" IS NOT NULL
455458
-- Candidates require available_at <= NOW(); active leased runs
456459
-- require available_at > NOW(). Keep explicit self-exclusion
457460
-- for readability/safety.

packages/openworkflow/sqlite/backend.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ describe("BackendSqlite.setStepAttemptChildWorkflowRun error handling", () => {
175175
workflowName: randomUUID(),
176176
version: null,
177177
idempotencyKey: null,
178+
concurrencyKey: null,
179+
concurrencyLimit: null,
178180
config: {},
179181
context: null,
180182
input: null,
@@ -205,6 +207,8 @@ describe("BackendSqlite.setStepAttemptChildWorkflowRun error handling", () => {
205207
workflowName: randomUUID(),
206208
version: null,
207209
idempotencyKey: null,
210+
concurrencyKey: null,
211+
concurrencyLimit: null,
208212
config: {},
209213
context: null,
210214
input: null,
@@ -255,6 +259,8 @@ describe("BackendSqlite legacy sleeping compatibility", () => {
255259
workflowName: "legacy-sleeping-claim",
256260
version: null,
257261
idempotencyKey: null,
262+
concurrencyKey: null,
263+
concurrencyLimit: null,
258264
config: {},
259265
context: null,
260266
input: null,
@@ -309,6 +315,8 @@ describe("BackendSqlite workflow wake-up reconciliation", () => {
309315
workflowName: "workflow-parent-reconcile",
310316
version: null,
311317
idempotencyKey: null,
318+
concurrencyKey: null,
319+
concurrencyLimit: null,
312320
input: null,
313321
config: {},
314322
context: null,
@@ -341,6 +349,8 @@ describe("BackendSqlite workflow wake-up reconciliation", () => {
341349
workflowName: "workflow-child-reconcile",
342350
version: null,
343351
idempotencyKey: null,
352+
concurrencyKey: null,
353+
concurrencyLimit: null,
344354
input: null,
345355
config: {},
346356
context: null,
@@ -404,6 +414,8 @@ describe("BackendSqlite workflow wake-up reconciliation", () => {
404414
workflowName: "workflow-parent-no-wake-after-failed-workflow",
405415
version: null,
406416
idempotencyKey: null,
417+
concurrencyKey: null,
418+
concurrencyLimit: null,
407419
input: null,
408420
config: {},
409421
context: null,
@@ -436,6 +448,8 @@ describe("BackendSqlite workflow wake-up reconciliation", () => {
436448
workflowName: "workflow-child-no-wake-after-failed-workflow",
437449
version: null,
438450
idempotencyKey: null,
451+
concurrencyKey: null,
452+
concurrencyLimit: null,
439453
input: null,
440454
config: {},
441455
context: null,
@@ -513,6 +527,8 @@ describe("BackendSqlite workflow wake-up reconciliation", () => {
513527
workflowName: "sleep-overwrite-stale-available-at",
514528
version: null,
515529
idempotencyKey: null,
530+
concurrencyKey: null,
531+
concurrencyLimit: null,
516532
input: null,
517533
config: {},
518534
context: null,

packages/openworkflow/sqlite/backend.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ export class BackendSqlite implements Backend {
179179
"created_at",
180180
"updated_at"
181181
)
182-
VALUES (?, ?, ?, ?, 'pending', ?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?)
182+
VALUES (?, ?, ?, ?, 'pending', ?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?, ?, ?)
183183
`);
184184

185185
stmt.run(
@@ -260,9 +260,10 @@ export class BackendSqlite implements Backend {
260260
"concurrency_key" = ?
261261
OR ("concurrency_key" IS NULL AND ? IS NULL)
262262
)
263-
-- Sleeping runs are excluded so long sleeps do not pin historical
264-
-- limits and block new run creation after config changes.
265-
AND "status" IN ('pending', 'running')
263+
-- Parked/sleeping runs (worker_id IS NULL, status 'running') are excluded
264+
-- so long sleeps do not pin historical limits and block new run creation
265+
-- after config changes.
266+
AND ("status" = 'pending' OR ("status" = 'running' AND "worker_id" IS NOT NULL))
266267
-- "params.limit" is always non-null because this is called only when
267268
-- toConcurrencyBucket() returns a constrained bucket.
268269
AND ("concurrency_limit" <> ? OR "concurrency_limit" IS NULL)
@@ -366,6 +367,7 @@ export class BackendSqlite implements Backend {
366367
)
367368
)
368369
AND active."status" = 'running'
370+
AND active."worker_id" IS NOT NULL
369371
-- Candidates require available_at <= now; active leased runs
370372
-- require available_at > now. Keep explicit self-exclusion
371373
-- for readability/safety.

packages/openworkflow/testing/backend.testsuite.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ export function testBackend(options: TestBackendOptions): void {
153153
input: null,
154154
config: {},
155155
context: null,
156+
parentStepAttemptNamespaceId: null,
157+
parentStepAttemptId: null,
156158
availableAt: null,
157159
deadlineAt: null,
158160
});
@@ -196,6 +198,8 @@ export function testBackend(options: TestBackendOptions): void {
196198
...base,
197199
concurrencyKey: "tenant:acme",
198200
concurrencyLimit: null,
201+
parentStepAttemptNamespaceId: null,
202+
parentStepAttemptId: null,
199203
};
200204
await expect(
201205
Promise.resolve().then(() => backend.createWorkflowRun(keyOnly)),
@@ -220,6 +224,8 @@ export function testBackend(options: TestBackendOptions): void {
220224
...base,
221225
concurrencyKey: null,
222226
concurrencyLimit: 1,
227+
parentStepAttemptNamespaceId: null,
228+
parentStepAttemptId: null,
223229
};
224230
const created = await backend.createWorkflowRun(limitOnly);
225231
expect(created.concurrencyKey).toBeNull();
@@ -299,6 +305,8 @@ export function testBackend(options: TestBackendOptions): void {
299305
input: null,
300306
config: {},
301307
context: null,
308+
parentStepAttemptNamespaceId: null,
309+
parentStepAttemptId: null,
302310
availableAt: null,
303311
deadlineAt: null,
304312
}),
@@ -328,6 +336,8 @@ export function testBackend(options: TestBackendOptions): void {
328336
input: null,
329337
config: {},
330338
context: null,
339+
parentStepAttemptNamespaceId: null,
340+
parentStepAttemptId: null,
331341
availableAt: null,
332342
deadlineAt: null,
333343
}),
@@ -371,6 +381,8 @@ export function testBackend(options: TestBackendOptions): void {
371381
input: null,
372382
config: {},
373383
context: null,
384+
parentStepAttemptNamespaceId: null,
385+
parentStepAttemptId: null,
374386
availableAt: null,
375387
deadlineAt: null,
376388
});
@@ -414,6 +426,8 @@ export function testBackend(options: TestBackendOptions): void {
414426
input: null,
415427
config: {},
416428
context: null,
429+
parentStepAttemptNamespaceId: null,
430+
parentStepAttemptId: null,
417431
availableAt: null,
418432
deadlineAt: null,
419433
});
@@ -455,6 +469,8 @@ export function testBackend(options: TestBackendOptions): void {
455469
workflowName: randomUUID(),
456470
version: null,
457471
idempotencyKey: null,
472+
concurrencyKey: null,
473+
concurrencyLimit: null,
458474
input: { key: "val" },
459475
config: {},
460476
context: null,
@@ -1598,7 +1614,7 @@ export function testBackend(options: TestBackendOptions): void {
15981614
workerId,
15991615
availableAt: new Date(Date.now() + 200),
16001616
});
1601-
expect(sleeping.status).toBe("sleeping");
1617+
expect(sleeping.status).toBe("running");
16021618

16031619
const secondClaimed = await backend.claimWorkflowRun({
16041620
workerId: randomUUID(),
@@ -1907,6 +1923,8 @@ export function testBackend(options: TestBackendOptions): void {
19071923
workflowName: randomUUID(),
19081924
version: null,
19091925
idempotencyKey: null,
1926+
concurrencyKey: null,
1927+
concurrencyLimit: null,
19101928
input: null,
19111929
config: {},
19121930
context: null,
@@ -1993,6 +2011,8 @@ export function testBackend(options: TestBackendOptions): void {
19932011
workflowName: randomUUID(),
19942012
version: null,
19952013
idempotencyKey: null,
2014+
concurrencyKey: null,
2015+
concurrencyLimit: null,
19962016
input: null,
19972017
config: {},
19982018
context: null,
@@ -2158,6 +2178,8 @@ export function testBackend(options: TestBackendOptions): void {
21582178
workflowName: randomUUID(),
21592179
version: null,
21602180
idempotencyKey: null,
2181+
concurrencyKey: null,
2182+
concurrencyLimit: null,
21612183
input: null,
21622184
config: {},
21632185
context: null,
@@ -2316,6 +2338,8 @@ export function testBackend(options: TestBackendOptions): void {
23162338
workflowName: randomUUID(),
23172339
version: null,
23182340
idempotencyKey: null,
2341+
concurrencyKey: null,
2342+
concurrencyLimit: null,
23192343
input: null,
23202344
config: {},
23212345
context: null,
@@ -2357,6 +2381,8 @@ export function testBackend(options: TestBackendOptions): void {
23572381
workflowName: randomUUID(),
23582382
version: null,
23592383
idempotencyKey: null,
2384+
concurrencyKey: null,
2385+
concurrencyLimit: null,
23602386
input: null,
23612387
config: {},
23622388
context: null,
@@ -2397,6 +2423,8 @@ export function testBackend(options: TestBackendOptions): void {
23972423
workflowName: randomUUID(),
23982424
version: null,
23992425
idempotencyKey: null,
2426+
concurrencyKey: null,
2427+
concurrencyLimit: null,
24002428
input: null,
24012429
config: {},
24022430
context: null,

packages/openworkflow/worker/execution.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2663,6 +2663,8 @@ function createMockWorkflowRun(
26632663
version: null,
26642664
status: "running",
26652665
idempotencyKey: null,
2666+
concurrencyKey: null,
2667+
concurrencyLimit: null,
26662668
config: {},
26672669
context: null,
26682670
input: null,

packages/openworkflow/worker/execution.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,8 @@ class StepExecutor implements StepApi {
642642
workflowName: request.workflowSpec.name,
643643
version: request.workflowSpec.version ?? null,
644644
idempotencyKey: buildWorkflowIdempotencyKey(attempt),
645+
concurrencyKey: null,
646+
concurrencyLimit: null,
645647
config: {},
646648
context: null,
647649
input: normalizeStepOutput(parsedInput),

0 commit comments

Comments
 (0)