( executionId: string )
| 41 | |
| 42 | /** Writes the durable key first, then publishes — so a late subscriber still sees the flag on backstop check. */ |
| 43 | export async function markExecutionCancelled( |
| 44 | executionId: string |
| 45 | ): Promise<ExecutionCancellationRecordResult> { |
| 46 | const redis = getRedisClient() |
| 47 | if (!redis) { |
| 48 | getCancellationChannel().publish({ executionId }) |
| 49 | return { durablyRecorded: false, reason: 'redis_unavailable' } |
| 50 | } |
| 51 | |
| 52 | try { |
| 53 | await redis.set(`${EXECUTION_CANCEL_PREFIX}${executionId}`, '1', 'EX', EXECUTION_CANCEL_EXPIRY) |
| 54 | logger.info('Marked execution as cancelled', { executionId }) |
| 55 | getCancellationChannel().publish({ executionId }) |
| 56 | return { durablyRecorded: true, reason: 'recorded' } |
| 57 | } catch (error) { |
| 58 | logger.error('Failed to mark execution as cancelled', { executionId, error }) |
| 59 | getCancellationChannel().publish({ executionId }) |
| 60 | return { durablyRecorded: false, reason: 'redis_write_failed' } |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | export async function isExecutionCancelled(executionId: string): Promise<boolean> { |
| 65 | const redis = getRedisClient() |
no test coverage detected