From d82bff441a41f36f5f616dd86f0b484c23d6046c Mon Sep 17 00:00:00 2001 From: hhhhsc701 <56435672+hhhhsc701@users.noreply.github.com> Date: Mon, 22 Dec 2025 19:30:41 +0800 Subject: [PATCH] fix: prevent deletion of predefined operators and improve error handling (#192) * fix: prevent deletion of predefined operators and improve error handling * fix: prevent deletion of predefined operators and improve error handling --- Makefile | 2 +- .../operator/application/OperatorService.java | 3 ++ .../domain/contants/OperatorConstant.java | 2 + .../CategoryRelationRepository.java | 2 + .../exception/OperatorErrorCode.java | 4 +- .../Impl/CategoryRelationRepositoryImpl.java | 9 ++++ backend/services/pom.xml | 6 +++ frontend/src/components/ActionDropdown.tsx | 2 + .../Detail/components/FileTable.tsx | 38 ++++++++++++++++ .../OperatorMarket/Home/components/List.tsx | 45 +------------------ runtime/datamate-python/app/core/config.py | 2 +- .../filter/remove_duplicate_file/process.py | 2 +- .../remove_duplicate_file/sql/sql_config.json | 2 +- .../python-executor/datamate/core/base_op.py | 29 +++++++++--- .../python-executor/datamate/core/dataset.py | 5 ++- 15 files changed, 98 insertions(+), 55 deletions(-) diff --git a/Makefile b/Makefile index 1837593..9e34676 100644 --- a/Makefile +++ b/Makefile @@ -155,7 +155,7 @@ endef # ========== Build Targets ========== # Valid build targets -VALID_BUILD_TARGETS := backend database frontend runtime backend-python deer-flow mineru mineru-npu +VALID_BUILD_TARGETS := backend database frontend runtime backend-python deer-flow mineru mineru-npu gateway # Generic docker build target with service name as parameter # Automatically prefixes image names with "datamate-" unless it's deer-flow diff --git a/backend/services/operator-market-service/src/main/java/com/datamate/operator/application/OperatorService.java b/backend/services/operator-market-service/src/main/java/com/datamate/operator/application/OperatorService.java index 87ed433..1542ea2 100644 --- a/backend/services/operator-market-service/src/main/java/com/datamate/operator/application/OperatorService.java +++ b/backend/services/operator-market-service/src/main/java/com/datamate/operator/application/OperatorService.java @@ -95,6 +95,9 @@ public class OperatorService { if (operatorRepo.operatorInTemplateOrRunning(id)) { throw BusinessException.of(OperatorErrorCode.OPERATOR_IN_INSTANCE); } + if (relationRepo.operatorIsPredefined(id)) { + throw BusinessException.of(OperatorErrorCode.CANT_DELETE_PREDEFINED_OPERATOR); + } operatorRepo.deleteOperator(id); relationRepo.deleteByOperatorId(id); } diff --git a/backend/services/operator-market-service/src/main/java/com/datamate/operator/domain/contants/OperatorConstant.java b/backend/services/operator-market-service/src/main/java/com/datamate/operator/domain/contants/OperatorConstant.java index 144389e..7c88041 100644 --- a/backend/services/operator-market-service/src/main/java/com/datamate/operator/domain/contants/OperatorConstant.java +++ b/backend/services/operator-market-service/src/main/java/com/datamate/operator/domain/contants/OperatorConstant.java @@ -30,6 +30,8 @@ public class OperatorConstant { public static String CATEGORY_STAR_ID = "51847c24-bba9-11f0-888b-5b143cb738aa"; + public static String CATEGORY_PREDEFINED_ID = "96a3b07a-3439-4557-a835-525faad60ca3"; + public static Map CATEGORY_MAP = new HashMap<>(); static { diff --git a/backend/services/operator-market-service/src/main/java/com/datamate/operator/domain/repository/CategoryRelationRepository.java b/backend/services/operator-market-service/src/main/java/com/datamate/operator/domain/repository/CategoryRelationRepository.java index bd719a8..146363b 100644 --- a/backend/services/operator-market-service/src/main/java/com/datamate/operator/domain/repository/CategoryRelationRepository.java +++ b/backend/services/operator-market-service/src/main/java/com/datamate/operator/domain/repository/CategoryRelationRepository.java @@ -15,4 +15,6 @@ public interface CategoryRelationRepository extends IRepository categories); void deleteByOperatorId(String operatorId); + + boolean operatorIsPredefined(String operatorId); } diff --git a/backend/services/operator-market-service/src/main/java/com/datamate/operator/infrastructure/exception/OperatorErrorCode.java b/backend/services/operator-market-service/src/main/java/com/datamate/operator/infrastructure/exception/OperatorErrorCode.java index f94511b..4a76768 100644 --- a/backend/services/operator-market-service/src/main/java/com/datamate/operator/infrastructure/exception/OperatorErrorCode.java +++ b/backend/services/operator-market-service/src/main/java/com/datamate/operator/infrastructure/exception/OperatorErrorCode.java @@ -18,7 +18,9 @@ public enum OperatorErrorCode implements ErrorCode { SETTINGS_PARSE_FAILED("op.0004", "settings字段解析失败"), - OPERATOR_IN_INSTANCE("op.0005", "算子已被编排在模板或未完成的任务中"); + OPERATOR_IN_INSTANCE("op.0005", "算子已被编排在模板或未完成的任务中"), + + CANT_DELETE_PREDEFINED_OPERATOR("op.0006", "预置算子无法删除"); private final String code; private final String message; diff --git a/backend/services/operator-market-service/src/main/java/com/datamate/operator/infrastructure/persistence/Impl/CategoryRelationRepositoryImpl.java b/backend/services/operator-market-service/src/main/java/com/datamate/operator/infrastructure/persistence/Impl/CategoryRelationRepositoryImpl.java index 47fdc14..9701e20 100644 --- a/backend/services/operator-market-service/src/main/java/com/datamate/operator/infrastructure/persistence/Impl/CategoryRelationRepositoryImpl.java +++ b/backend/services/operator-market-service/src/main/java/com/datamate/operator/infrastructure/persistence/Impl/CategoryRelationRepositoryImpl.java @@ -2,6 +2,7 @@ package com.datamate.operator.infrastructure.persistence.Impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.repository.CrudRepository; +import com.datamate.operator.domain.contants.OperatorConstant; import com.datamate.operator.domain.model.CategoryRelation; import com.datamate.operator.domain.repository.CategoryRelationRepository; import com.datamate.operator.infrastructure.converter.CategoryRelationConverter; @@ -48,4 +49,12 @@ public class CategoryRelationRepositoryImpl extends CrudRepository queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(CategoryRelation::getOperatorId, operatorId) + .eq(CategoryRelation::getCategoryId, OperatorConstant.CATEGORY_PREDEFINED_ID); + return this.exists(queryWrapper); + } } diff --git a/backend/services/pom.xml b/backend/services/pom.xml index fd40146..1e599f2 100644 --- a/backend/services/pom.xml +++ b/backend/services/pom.xml @@ -64,6 +64,12 @@ + + org.springframework.boot + spring-boot-starter-log4j2 + ${spring-boot.version} + + com.baomidou mybatis-plus-spring-boot3-starter diff --git a/frontend/src/components/ActionDropdown.tsx b/frontend/src/components/ActionDropdown.tsx index ae4e039..9fe696b 100644 --- a/frontend/src/components/ActionDropdown.tsx +++ b/frontend/src/components/ActionDropdown.tsx @@ -68,6 +68,7 @@ const ActionDropdown = ({ + + + + ), + onFilter: (value: string, record: any) => + record.destName.toLowerCase().includes(value.toLowerCase()), + render: (text: string) => ( + {text?.replace(/\.[^/.]+$/, "")} + ), + }, { title: "文件类型", dataIndex: "srcType", diff --git a/frontend/src/pages/OperatorMarket/Home/components/List.tsx b/frontend/src/pages/OperatorMarket/Home/components/List.tsx index ea81148..e0d4f3d 100644 --- a/frontend/src/pages/OperatorMarket/Home/components/List.tsx +++ b/frontend/src/pages/OperatorMarket/Home/components/List.tsx @@ -1,54 +1,13 @@ -import { Button, List, Tag, Badge } from "antd"; -import { StarFilled } from "@ant-design/icons"; -import { Zap, Settings, X } from "lucide-react"; -import { useState } from "react"; +import { Button, List, Tag } from "antd"; import { useNavigate } from "react-router"; import { Operator } from "../../operator.model"; export function ListView({ operators = [], pagination, operations }) { const navigate = useNavigate(); - const [favoriteOperators, setFavoriteOperators] = useState>( - new Set([1, 3, 6]) - ); - const handleUpdateOperator = (operator: Operator) => { - navigate(`/data/operator-market/create/${operator.id}`); - }; + const handleViewOperator = (operator: Operator) => { navigate(`/data/operator-market/plugin-detail/${operator.id}`); }; - const handleToggleFavorite = (operatorId: number) => { - setFavoriteOperators((prev) => { - const newFavorites = new Set(prev); - if (newFavorites.has(operatorId)) { - newFavorites.delete(operatorId); - } else { - newFavorites.add(operatorId); - } - return newFavorites; - }); - }; - const getStatusBadge = (status: string) => { - const statusConfig = { - active: { - label: "活跃", - color: "green", - icon: , - }, - beta: { - label: "测试版", - color: "blue", - icon: , - }, - deprecated: { - label: "已弃用", - color: "gray", - icon: , - }, - }; - return ( - statusConfig[status as keyof typeof statusConfig] || statusConfig.active - ); - }; return ( Dict[str, Any]: sample[self.data_key] = bytes(sample[self.data_key]) diff --git a/runtime/python-executor/datamate/core/dataset.py b/runtime/python-executor/datamate/core/dataset.py index 1857524..1058ed2 100644 --- a/runtime/python-executor/datamate/core/dataset.py +++ b/runtime/python-executor/datamate/core/dataset.py @@ -5,6 +5,7 @@ from __future__ import annotations import os import importlib import sys +import uuid from abc import ABC, abstractmethod import pyarrow as pa @@ -119,12 +120,14 @@ class RayDataset(BasicDataset): # 加载Ops module temp_ops = self.load_ops_module(op_name) + operators_cls_list.append(temp_ops) + if index == 0: init_kwargs["is_first_op"] = True if index == len(cfg_process) - 1: init_kwargs["is_last_op"] = True - operators_cls_list.append(temp_ops) + init_kwargs["instance_id"] = kwargs.get("instance_id", str(uuid.uuid4())) init_kwargs_list.append(init_kwargs) for cls_id, operators_cls in enumerate(operators_cls_list):