|
| 1 | +import { idempotencyKey } from '@sim/db/schema' |
1 | 2 | import { |
2 | 3 | asyncJobsRegionMock, |
3 | 4 | asyncJobsRegionMockFns, |
4 | 5 | } from '@sim/testing/mocks/async-jobs-region.mock' |
5 | | -import { dbChainMockFns } from '@sim/testing/mocks/database.mock' |
| 6 | +import { dbChainMockFns, queueTableRows } from '@sim/testing/mocks/database.mock' |
6 | 7 | import { getMockLogger } from '@sim/testing/mocks/logger.mock' |
7 | 8 | import { |
8 | 9 | MockTriggerApiError as MockApiError, |
@@ -329,7 +330,7 @@ describe('TriggerDevJobQueue status mapping', () => { |
329 | 330 |
|
330 | 331 | describe('TriggerDevJobQueue cancellation', () => { |
331 | 332 | beforeEach(() => { |
332 | | - mockList.mockReturnValue( |
| 333 | + mockList.mockReset().mockReturnValue( |
333 | 334 | createListPage([ |
334 | 335 | { |
335 | 336 | id: 'run-1', |
@@ -476,6 +477,49 @@ describe('TriggerDevJobQueue cancellation', () => { |
476 | 477 | }) |
477 | 478 | }) |
478 | 479 |
|
| 480 | + it.each(['receipt', 'retrieve', 'cancel'] as const)( |
| 481 | + 'continues every discovery phase after a root %s failure', |
| 482 | + async (failurePhase) => { |
| 483 | + const failure = new Error(`root ${failurePhase} unavailable`) |
| 484 | + const payload = { workflowId: 'workflow-1', executionId: 'execution-1' } |
| 485 | + const cancelled = new Set<string>() |
| 486 | + if (failurePhase === 'receipt') { |
| 487 | + dbChainMockFns.limit.mockRejectedValueOnce(failure) |
| 488 | + } else { |
| 489 | + queueTableRows(idempotencyKey, [{ result: { runId: 'run_root' } }]) |
| 490 | + } |
| 491 | + mockRetrieve.mockImplementation(async (id: string) => { |
| 492 | + if (id === 'run_root' && failurePhase === 'retrieve') throw failure |
| 493 | + return { id, taskIdentifier: 'workflow-execution', status: 'QUEUED', payload } |
| 494 | + }) |
| 495 | + mockCancel.mockImplementation(async (id: string) => { |
| 496 | + if (id === 'run_root') throw failure |
| 497 | + cancelled.add(id) |
| 498 | + }) |
| 499 | + mockList |
| 500 | + .mockReturnValueOnce( |
| 501 | + createListPage([ |
| 502 | + { id: 'tagged', tags: ['workflowId:workflow-1', 'executionId:execution-1'] }, |
| 503 | + ]) |
| 504 | + ) |
| 505 | + .mockReturnValueOnce( |
| 506 | + createListPage([{ id: 'legacy-tagged', tags: ['workflowId:workflow-1'] }]) |
| 507 | + ) |
| 508 | + .mockReturnValueOnce(createListPage([{ id: 'legacy-untagged', tags: [] }])) |
| 509 | + |
| 510 | + await expect( |
| 511 | + new TriggerDevJobQueue().cancelByExecution( |
| 512 | + { |
| 513 | + ...payload, |
| 514 | + rootJobId: 'workflow-execution:execution-1', |
| 515 | + }, |
| 516 | + 'standalone' |
| 517 | + ) |
| 518 | + ).rejects.toBe(failure) |
| 519 | + expect(cancelled).toEqual(new Set(['tagged', 'legacy-tagged', 'legacy-untagged'])) |
| 520 | + } |
| 521 | + ) |
| 522 | + |
479 | 523 | it('cancels legacy workflow-tagged runs only after payload verification', async () => { |
480 | 524 | mockList.mockReturnValueOnce(createListPage([])).mockReturnValueOnce( |
481 | 525 | createListPage([ |
|
0 commit comments