/** * @vitest-environment node */ import { dbChainMock, dbChainMockFns, resetDbChainMock } from '@sim/testing' import { beforeEach, describe, expect, it, vi } from 'vitest' import { writeExecutionsPatch } from '@/lib/table/rows/executions' import type { RowExecutionMetadata } from '@/lib/table/types' const EXECUTION_STATE: RowExecutionMetadata = { status: 'running', executionId: 'execution-1', jobId: null, workflowId: 'workflow-1', error: null, } function renderCondition(value: unknown): string { if (!value || typeof value !== 'object') return '' const record = value as Record const strings = Array.isArray(record.strings) ? record.strings.filter((entry): entry is string => typeof entry === 'string').join('') : '' const conditions = Array.isArray(record.conditions) ? record.conditions.map(renderCondition).join(' ') : '' return `${strings} ${conditions}`.trim() } describe('writeExecutionsPatch guards', () => { beforeEach(() => { vi.clearAllMocks() resetDbChainMock() }) it('rejects a worker write when the atomic stale-or-cancel predicate returns no row', async () => { dbChainMockFns.returning.mockResolvedValueOnce([]) await expect( writeExecutionsPatch( dbChainMock.db as unknown as Parameters[0], 'table-1', 'row-1', { 'group-1': EXECUTION_STATE }, { groupId: 'group-1', executionId: 'execution-1' } ) ).resolves.toBe('guard-rejected') const conflict = dbChainMockFns.onConflictDoUpdate.mock.calls[0]?.[0] as | { where?: unknown } | undefined const condition = renderCondition(conflict?.where) expect(condition).toContain("<> 'cancelled'") expect(condition).toContain('IS NULL OR') }) it('keeps queued takeover and late-same-run protection in the SQL predicate', async () => { dbChainMockFns.returning.mockResolvedValueOnce([]) await expect( writeExecutionsPatch( dbChainMock.db as unknown as Parameters[0], 'table-1', 'row-1', { 'group-1': { ...EXECUTION_STATE, status: 'queued' } }, { groupId: 'group-1', executionId: 'execution-1', allowNewExecution: true, } ) ).resolves.toBe('guard-rejected') const conflict = dbChainMockFns.onConflictDoUpdate.mock.calls[0]?.[0] as | { where?: unknown } | undefined const condition = renderCondition(conflict?.where) expect(condition).toContain('IS DISTINCT FROM') expect(condition).toContain("= 'pending'") }) it('guards usage-limit deletion against cancelled and newer execution rows', async () => { dbChainMockFns.returning.mockResolvedValueOnce([]) await expect( writeExecutionsPatch( dbChainMock.db as unknown as Parameters[0], 'table-1', 'row-1', { 'group-1': null }, { groupId: 'group-1', executionId: 'execution-1' } ) ).resolves.toBe('guard-rejected') const condition = renderCondition(dbChainMockFns.where.mock.calls.at(-1)?.[0]) expect(condition).toContain("<> 'cancelled'") expect(condition).toContain('IS NULL OR') }) it('deletes the usage-limit pre-stamp only when its execution guard wins', async () => { dbChainMockFns.returning.mockResolvedValueOnce([{ rowId: 'row-1' }]) await expect( writeExecutionsPatch( dbChainMock.db as unknown as Parameters[0], 'table-1', 'row-1', { 'group-1': null }, { groupId: 'group-1', executionId: 'execution-1' } ) ).resolves.toBe('wrote') }) })