From bf7c0287c2e0694625636c91c5a6ef2ef00ec773 Mon Sep 17 00:00:00 2001 From: canonical Date: Sun, 8 Dec 2024 19:41:01 +0800 Subject: [PATCH] =?UTF-8?q?task=E5=A2=9E=E5=8A=A0input=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../demo/_vfs/batch/batch-gen-demo.task.xml | 6 +-- .../main/java/io/nop/task/ITaskRuntime.java | 4 ++ .../src/main/java/io/nop/task/TaskErrors.java | 5 +++ .../io/nop/task/builder/TaskStepEnhancer.java | 2 +- .../main/java/io/nop/task/impl/TaskImpl.java | 37 ++++++++++++++++++- .../io/nop/task/step/TaskStepExecution.java | 16 +++++++- 6 files changed, 61 insertions(+), 9 deletions(-) diff --git a/nop-cli/demo/_vfs/batch/batch-gen-demo.task.xml b/nop-cli/demo/_vfs/batch/batch-gen-demo.task.xml index 05ca55ba2..e662b49b9 100644 --- a/nop-cli/demo/_vfs/batch/batch-gen-demo.task.xml +++ b/nop-cli/demo/_vfs/batch/batch-gen-demo.task.xml @@ -1,14 +1,10 @@ + xmlns:task="task" x:dump="true" defaultUseParentScope="true" xmlns:xpl="xpl"> - - - - diff --git a/nop-task/nop-task-core/src/main/java/io/nop/task/ITaskRuntime.java b/nop-task/nop-task-core/src/main/java/io/nop/task/ITaskRuntime.java index 628df3d7f..92a0c8841 100644 --- a/nop-task/nop-task-core/src/main/java/io/nop/task/ITaskRuntime.java +++ b/nop-task/nop-task-core/src/main/java/io/nop/task/ITaskRuntime.java @@ -124,6 +124,10 @@ default Map getTaskVars() { Set getAttributeKeys(); + default Object getInput(String name) { + return getEvalScope().getValue(name); + } + default void setInput(String name, Object value) { getEvalScope().setLocalValue(name, value); } diff --git a/nop-task/nop-task-core/src/main/java/io/nop/task/TaskErrors.java b/nop-task/nop-task-core/src/main/java/io/nop/task/TaskErrors.java index 844f15f8c..99169a950 100644 --- a/nop-task/nop-task-core/src/main/java/io/nop/task/TaskErrors.java +++ b/nop-task/nop-task-core/src/main/java/io/nop/task/TaskErrors.java @@ -44,6 +44,8 @@ public interface TaskErrors { String ARG_CUSTOM_TYPE = "customType"; + String ARG_INPUT_NAME = "inputName"; + ErrorCode ERR_TASK_STEP_NOT_RESTARTABLE = define("nop.err.task.step.not-restartable", "步骤[{stepName}]不允许多次执行", ARG_TASK_NAME, ARG_STEP_NAME); @@ -123,4 +125,7 @@ public interface TaskErrors { ErrorCode ERR_TASK_INVALID_CUSTOM_TYPE = define("nop.err.task.invalid-custom-type", "节点的扩展类型属性必须包含名字空间,例如customType='gpt:simple'", ARG_CUSTOM_TYPE); + + ErrorCode ERR_TASK_MANDATORY_INPUT_NOT_ALLOW_EMPTY = define("nop.err.task.mandatory-input-not-allow-empty", + "步骤[{stepPath}]的输入[{input}]不允许为空", ARG_STEP_PATH, ARG_INPUT_NAME); } diff --git a/nop-task/nop-task-core/src/main/java/io/nop/task/builder/TaskStepEnhancer.java b/nop-task/nop-task-core/src/main/java/io/nop/task/builder/TaskStepEnhancer.java index ad56bc157..cbdb43a1a 100644 --- a/nop-task/nop-task-core/src/main/java/io/nop/task/builder/TaskStepEnhancer.java +++ b/nop-task/nop-task-core/src/main/java/io/nop/task/builder/TaskStepEnhancer.java @@ -65,7 +65,7 @@ private TaskStepExecution enhancedTaskStep(TaskStepModel stepModel, ITaskStep st List inputs = new ArrayList<>(stepModel.getInputs().size()); for (TaskInputModel inputModel : stepModel.getInputs()) { inputs.add(new TaskStepExecution.InputConfig(inputModel.getLocation(), inputModel.getName(), - inputModel.getSource(), inputModel.isFromTaskScope())); + inputModel.getSource(), inputModel.isFromTaskScope(), inputModel.isMandatory())); } List outputs = new ArrayList<>(stepModel.getOutputs().size() + 1); diff --git a/nop-task/nop-task-core/src/main/java/io/nop/task/impl/TaskImpl.java b/nop-task/nop-task-core/src/main/java/io/nop/task/impl/TaskImpl.java index 2179cf2cc..29778e5b4 100644 --- a/nop-task/nop-task-core/src/main/java/io/nop/task/impl/TaskImpl.java +++ b/nop-task/nop-task-core/src/main/java/io/nop/task/impl/TaskImpl.java @@ -3,6 +3,7 @@ import io.nop.api.core.exceptions.NopException; import io.nop.api.core.ioc.IBeanContainer; import io.nop.api.core.util.Guard; +import io.nop.commons.util.StringHelper; import io.nop.task.ITask; import io.nop.task.ITaskRuntime; import io.nop.task.ITaskStep; @@ -13,9 +14,15 @@ import io.nop.task.model.ITaskInputModel; import io.nop.task.model.ITaskOutputModel; +import java.util.Collections; import java.util.List; import java.util.Set; +import static io.nop.task.TaskErrors.ARG_INPUT_NAME; +import static io.nop.task.TaskErrors.ARG_STEP_PATH; +import static io.nop.task.TaskErrors.ARG_TASK_NAME; +import static io.nop.task.TaskErrors.ERR_TASK_MANDATORY_INPUT_NOT_ALLOW_EMPTY; + public class TaskImpl implements ITask { private final String taskName; private final long taskVersion; @@ -33,8 +40,8 @@ public class TaskImpl implements ITask { public TaskImpl(String taskName, long taskVersion, ITaskStep mainStep, boolean recordMetrics, ITaskStepFlagOperation flagOperation, ITaskBeanContainerFactory taskBeanContainerFactory, List inputs, List outputs) { - this.inputs = inputs; - this.outputs = outputs; + this.inputs = inputs == null ? Collections.emptyList() : inputs; + this.outputs = outputs == null ? Collections.emptyList() : outputs; this.flagOperation = flagOperation; this.taskName = Guard.notEmpty(taskName, "taskName"); this.taskVersion = taskVersion; @@ -84,6 +91,8 @@ public TaskStepReturn execute(ITaskRuntime taskRt, Set outputNames) { ITaskFlowMetrics metrics = recordMetrics ? taskRt.getMetrics() : null; Object meter = metrics == null ? null : metrics.beginTask(); try { + checkInputs(taskRt); + // 如果设置了任务专用的beanContainer IBeanContainer beanContainer = createBeanContainer(taskRt); if (beanContainer != null) { @@ -107,4 +116,28 @@ public TaskStepReturn execute(ITaskRuntime taskRt, Set outputNames) { throw NopException.adapt(err); }); } + + void checkInputs(ITaskRuntime taskRt) { + for (ITaskInputModel input : inputs) { + String name = input.getName(); + Object value = taskRt.getInput(name); + if (value == null) { + // value为null可能是没有设置input,这里强制设置一下,确保scope中的input变量一定存在 + taskRt.setInput(name, null); + } else if (input.getType() != null) { + Object castedValue = input.getType().getStdDataType().convert(value, + err -> new NopException(err).param(ARG_TASK_NAME, taskRt.getTaskName()) + .param(ARG_INPUT_NAME, input.getName())); + if (castedValue != value) + taskRt.setInput(name, castedValue); + } + + if (input.isMandatory() && StringHelper.isEmptyObject(value)) { + throw new NopException(ERR_TASK_MANDATORY_INPUT_NOT_ALLOW_EMPTY) + .param(ARG_TASK_NAME, taskRt.getTaskName()) + .param(ARG_STEP_PATH, mainStep.getStepType()) + .param(ARG_INPUT_NAME, input.getName()); + } + } + } } \ No newline at end of file diff --git a/nop-task/nop-task-core/src/main/java/io/nop/task/step/TaskStepExecution.java b/nop-task/nop-task-core/src/main/java/io/nop/task/step/TaskStepExecution.java index 1efca0fdd..4662797d8 100644 --- a/nop-task/nop-task-core/src/main/java/io/nop/task/step/TaskStepExecution.java +++ b/nop-task/nop-task-core/src/main/java/io/nop/task/step/TaskStepExecution.java @@ -5,6 +5,7 @@ import io.nop.api.core.time.CoreMetrics; import io.nop.api.core.util.Guard; import io.nop.api.core.util.SourceLocation; +import io.nop.commons.util.StringHelper; import io.nop.core.exceptions.ErrorMessageManager; import io.nop.core.lang.eval.IEvalAction; import io.nop.core.lang.eval.IEvalPredicate; @@ -27,7 +28,10 @@ import java.util.Map; import java.util.Set; +import static io.nop.task.TaskErrors.ARG_INPUT_NAME; +import static io.nop.task.TaskErrors.ARG_STEP_PATH; import static io.nop.task.TaskErrors.ERR_TASK_CANCELLED; +import static io.nop.task.TaskErrors.ERR_TASK_MANDATORY_INPUT_NOT_ALLOW_EMPTY; public class TaskStepExecution implements ITaskStepExecution { static final Logger LOG = LoggerFactory.getLogger(TaskStepExecution.class); @@ -37,13 +41,19 @@ public static class InputConfig { private final String name; private final IEvalAction expr; private final boolean fromTaskScope; + private final boolean mandatory; public InputConfig(SourceLocation loc, String name, IEvalAction expr, - boolean fromTaskScope) { + boolean fromTaskScope, boolean mandatory) { this.location = loc; this.name = name; this.expr = expr; this.fromTaskScope = fromTaskScope; + this.mandatory = mandatory; + } + + public boolean isMandatory() { + return mandatory; } public SourceLocation getLocation() { @@ -289,6 +299,10 @@ private void initInputs(ITaskStepRuntime stepRt, IEvalScope parentScope, ITaskRu IEvalScope scope = inputConfig.isFromTaskScope() ? taskRt.getEvalScope() : parentScope; IEvalAction expr = inputConfig.getExpr(); Object value = expr == null ? parentScope.getValue(name) : expr.invoke(scope); + if (inputConfig.isMandatory() && !StringHelper.isEmptyObject(value)) + throw new NopException(ERR_TASK_MANDATORY_INPUT_NOT_ALLOW_EMPTY) + .param(ARG_STEP_PATH, stepRt.getStepPath()) + .param(ARG_INPUT_NAME, name); stepRt.setValue(name, value); }); }