fix: gracefully handle missing logic functions during workflow destroy (#21362)
## Summary - Wraps `deleteOneWithSource` calls in `.catch()` during workflow/step destruction so that a missing logic function (valid UUID but already deleted) no longer crashes the entire destroy operation - Adds a `Logger` to `WorkflowVersionStepOperationsWorkspaceService` for the warning - Fixes test mock to return a resolved Promise and use a valid UUID ## Context When a CODE step references a `logicFunctionId` that is a valid UUID but the logic function no longer exists (e.g. deleted by a previous operation or orphaned), the destroy fails with "Logic function with id X not found". This blocks users from cleaning up workflows. ## Test plan - [x] Destroy a workflow with CODE steps whose logic functions already exist → succeeds as before - [ ] Destroy a workflow with CODE steps referencing a deleted/non-existent logic function → succeeds with a warning log instead of crashing
This commit is contained in:
+20
-4
@@ -10,6 +10,10 @@ import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object
|
||||
import { buildObjectIdByNameMaps } from 'src/engine/metadata-modules/flat-object-metadata/utils/build-object-id-by-name-maps.util';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { LogicFunctionFromSourceService } from 'src/engine/metadata-modules/logic-function/services/logic-function-from-source.service';
|
||||
import {
|
||||
LogicFunctionException,
|
||||
LogicFunctionExceptionCode,
|
||||
} from 'src/engine/metadata-modules/logic-function/logic-function.exception';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { type WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
|
||||
import { buildSystemAuthContext } from 'src/engine/twenty-orm/utils/build-system-auth-context.util';
|
||||
@@ -387,10 +391,22 @@ export class WorkflowCommonWorkspaceService {
|
||||
continue;
|
||||
}
|
||||
|
||||
await this.logicFunctionFromSourceService.deleteOneWithSource({
|
||||
id: logicFunctionId,
|
||||
workspaceId,
|
||||
});
|
||||
await this.logicFunctionFromSourceService
|
||||
.deleteOneWithSource({
|
||||
id: logicFunctionId,
|
||||
workspaceId,
|
||||
})
|
||||
.catch((error) => {
|
||||
if (
|
||||
error instanceof LogicFunctionException &&
|
||||
error.code ===
|
||||
LogicFunctionExceptionCode.LOGIC_FUNCTION_NOT_FOUND
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -91,7 +91,7 @@ describe('WorkflowVersionStepOperationsWorkspaceService', () => {
|
||||
} as unknown as jest.Mocked<CodeStepBuildService>;
|
||||
|
||||
logicFunctionFromSourceService = {
|
||||
deleteOneWithSource: jest.fn(),
|
||||
deleteOneWithSource: jest.fn().mockResolvedValue(undefined),
|
||||
} as unknown as jest.Mocked<LogicFunctionFromSourceService>;
|
||||
|
||||
agentService = {
|
||||
|
||||
+19
-4
@@ -22,6 +22,10 @@ import { AiAgentRoleService } from 'src/engine/metadata-modules/ai/ai-agent-role
|
||||
import { AgentService } from 'src/engine/metadata-modules/ai/ai-agent/agent.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { LogicFunctionFromSourceService } from 'src/engine/metadata-modules/logic-function/services/logic-function-from-source.service';
|
||||
import {
|
||||
LogicFunctionException,
|
||||
LogicFunctionExceptionCode,
|
||||
} from 'src/engine/metadata-modules/logic-function/logic-function.exception';
|
||||
import { findFlatLogicFunctionOrThrow } from 'src/engine/metadata-modules/logic-function/utils/find-flat-logic-function-or-throw.util';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
|
||||
@@ -95,10 +99,21 @@ export class WorkflowVersionStepOperationsWorkspaceService {
|
||||
break;
|
||||
}
|
||||
|
||||
await this.logicFunctionFromSourceService.deleteOneWithSource({
|
||||
id: step.settings.input.logicFunctionId,
|
||||
workspaceId,
|
||||
});
|
||||
await this.logicFunctionFromSourceService
|
||||
.deleteOneWithSource({
|
||||
id: step.settings.input.logicFunctionId,
|
||||
workspaceId,
|
||||
})
|
||||
.catch((error) => {
|
||||
if (
|
||||
error instanceof LogicFunctionException &&
|
||||
error.code === LogicFunctionExceptionCode.LOGIC_FUNCTION_NOT_FOUND
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw error;
|
||||
});
|
||||
break;
|
||||
}
|
||||
case WorkflowActionType.AI_AGENT: {
|
||||
|
||||
Reference in New Issue
Block a user