Skip to content

Commit 79b437b

Browse files
authored
Add workflow deletion signal (#1880)
Part of OPS-3195 ## Additional notes - Add a cache-based mechanism to detect workflow deletion requests and stop workflow executions early. - Add helpers to signal and detect workflow deletion using a cache key (workflow:deleted:<flowId>) - This ensures in-progress and future runs don’t continue executing after a workflow deletion is requested, avoiding wasted work and inconsistent state.
1 parent 2ae29a4 commit 79b437b

3 files changed

Lines changed: 49 additions & 0 deletions

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { logger, wasWorkflowDeletionRequested } from '@openops/server-shared';
2+
import { FlowId } from '@openops/shared';
3+
4+
const defaultMessage =
5+
'Workflow deletion was requested. Stopping workflow executions.';
6+
7+
export class WorkflowDeletionRequestedError extends Error {
8+
constructor(message = defaultMessage) {
9+
super(message);
10+
this.name = 'WorkflowDeletionRequestedError';
11+
}
12+
}
13+
14+
export async function throwIfWorkflowDeletionRequested(
15+
flowId: FlowId,
16+
): Promise<void> {
17+
const wasDeletionRequested = await wasWorkflowDeletionRequested(flowId);
18+
19+
if (wasDeletionRequested) {
20+
logger.info(defaultMessage);
21+
throw new WorkflowDeletionRequestedError();
22+
}
23+
}

packages/server/shared/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,4 @@ export * from './lib/system';
3131
export * from './lib/truncation-utils';
3232
export * from './lib/webhook-secrets-util';
3333
export * from './lib/workflow-cancellation-manager';
34+
export * from './lib/workflow-deletion-manager';
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { FlowId } from '@openops/shared';
2+
import { cacheWrapper } from './cache/cache-wrapper';
3+
4+
const DELETED_PREFIX = 'workflow:deleted:';
5+
6+
function buildCancellationKey(flowId: FlowId): string {
7+
return `${DELETED_PREFIX}${flowId}`;
8+
}
9+
10+
export async function signalWorkflowDeletion(flowId: FlowId): Promise<void> {
11+
const key = buildCancellationKey(flowId);
12+
await cacheWrapper.setKey(key, 'true');
13+
}
14+
15+
export async function wasWorkflowDeletionRequested(
16+
flowId: FlowId,
17+
): Promise<boolean> {
18+
const key = buildCancellationKey(flowId);
19+
const value: string | null = await cacheWrapper.getKey(key);
20+
if (value === null) {
21+
return false;
22+
}
23+
24+
return value === 'true';
25+
}

0 commit comments

Comments
 (0)