mirror of
https://github.com/slhaf/Partner.git
synced 2026-05-12 08:43:02 +08:00
refactor(ActionData): migrate to Kotlin sealed class and data classes, update planner/scheduler usage
This commit is contained in:
@@ -1,80 +1,143 @@
|
|||||||
package work.slhaf.partner.core.action.entity;
|
package work.slhaf.partner.core.action.entity
|
||||||
|
|
||||||
import lombok.Data;
|
import work.slhaf.partner.module.modules.action.dispatcher.executor.entity.HistoryAction
|
||||||
import work.slhaf.partner.module.modules.action.dispatcher.executor.entity.HistoryAction;
|
import java.time.ZonedDateTime
|
||||||
|
import java.util.*
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 行动模块传递的行动数据,包含行动uuid、倾向、状态、行动链、结果、发起原因、行动描述等信息。
|
* 行动模块传递的行动数据,包含行动uuid、倾向、状态、行动链、结果、发起原因、行动描述等信息。
|
||||||
*/
|
*/
|
||||||
@Data
|
sealed class ActionData {
|
||||||
public abstract class ActionData {
|
|
||||||
/**
|
/**
|
||||||
* 行动ID
|
* 行动ID
|
||||||
*/
|
*/
|
||||||
protected String uuid;
|
val uuid: String = UUID.randomUUID().toString()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 行动倾向
|
* 行动倾向
|
||||||
*/
|
*/
|
||||||
protected String tendency;
|
abstract val tendency: String
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 行动状态
|
* 行动状态
|
||||||
*/
|
*/
|
||||||
protected ActionStatus status;
|
var status: ActionStatus = ActionStatus.PREPARE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 行动链
|
* 行动链
|
||||||
*/
|
*/
|
||||||
protected Map<Integer, List<MetaAction>> actionChain;
|
abstract val actionChain: MutableMap<Int, MutableList<MetaAction>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 行动阶段(当前阶段)
|
* 行动阶段(当前阶段)
|
||||||
*/
|
*/
|
||||||
protected int executingStage;
|
var executingStage: Int = 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 行动结果
|
* 行动结果
|
||||||
*/
|
*/
|
||||||
protected String result;
|
lateinit var result: String
|
||||||
protected Map<Integer, List<HistoryAction>> history = new HashMap<>();
|
|
||||||
|
val history: MutableMap<Int, MutableList<HistoryAction>> = mutableMapOf()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修复上下文
|
* 修复上下文
|
||||||
*/
|
*/
|
||||||
protected Map<Integer, List<String>> additionalContext;
|
val additionalContext: MutableMap<Int, MutableList<String>> = mutableMapOf()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 行动原因
|
* 行动原因
|
||||||
*/
|
*/
|
||||||
protected String reason;
|
abstract val reason: String
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 行动描述
|
* 行动描述
|
||||||
*/
|
*/
|
||||||
protected String description;
|
abstract val description: String
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 行动来源
|
* 行动来源
|
||||||
*/
|
*/
|
||||||
protected String source;
|
abstract val source: String
|
||||||
|
|
||||||
public enum ActionStatus {
|
enum class ActionStatus {
|
||||||
/**
|
/**
|
||||||
* 执行成功
|
* 执行成功
|
||||||
*/
|
*/
|
||||||
SUCCESS,
|
SUCCESS,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行失败
|
* 执行失败
|
||||||
*/
|
*/
|
||||||
FAILED,
|
FAILED,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行中
|
* 执行中
|
||||||
*/
|
*/
|
||||||
EXECUTING,
|
EXECUTING,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 暂时中断
|
* 暂时中断
|
||||||
*/
|
*/
|
||||||
INTERRUPTED,
|
INTERRUPTED,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 预备执行
|
* 预备执行
|
||||||
*/
|
*/
|
||||||
PREPARE
|
PREPARE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计划行动数据类,继承自{@link ActionData},扩展了属性{@link ScheduledActionData#type}和{@link ScheduledActionData#scheduleContent},用于标识计划类型(单次还是周期性任务)和计划内容
|
||||||
|
*/
|
||||||
|
data class ScheduledActionData(
|
||||||
|
override val tendency: String,
|
||||||
|
override val actionChain: MutableMap<Int, MutableList<MetaAction>>,
|
||||||
|
override val reason: String,
|
||||||
|
override val description: String,
|
||||||
|
override val source: String,
|
||||||
|
val scheduleType: ScheduleType,
|
||||||
|
val scheduleContent: String,
|
||||||
|
) : ActionData() {
|
||||||
|
|
||||||
|
val scheduleHistories = ArrayList<ScheduleHistory>()
|
||||||
|
|
||||||
|
fun recordAndReset() {
|
||||||
|
val newHistory = ScheduleHistory(ZonedDateTime.now(), result, history.toMap())
|
||||||
|
scheduleHistories.add(newHistory)
|
||||||
|
|
||||||
|
additionalContext.clear()
|
||||||
|
executingStage = 0
|
||||||
|
for (entry in actionChain) {
|
||||||
|
for (action in entry.value) {
|
||||||
|
action.params.clear()
|
||||||
|
action.result = MetaAction.Result()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status = ActionStatus.PREPARE
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ScheduleType {
|
||||||
|
CYCLE,
|
||||||
|
ONCE
|
||||||
|
}
|
||||||
|
|
||||||
|
data class ScheduleHistory(
|
||||||
|
val endTime: ZonedDateTime,
|
||||||
|
val result: String,
|
||||||
|
val history: Map<Int, List<HistoryAction>>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 即时行动数据类
|
||||||
|
*/
|
||||||
|
data class ImmediateActionData(
|
||||||
|
override val tendency: String,
|
||||||
|
override val actionChain: MutableMap<Int, MutableList<MetaAction>>,
|
||||||
|
override val reason: String,
|
||||||
|
override val description: String,
|
||||||
|
override val source: String,
|
||||||
|
) : ActionData()
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
package work.slhaf.partner.core.action.entity;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 即时行动数据类,继承自{@link ActionData}
|
|
||||||
*/
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
|
||||||
public class ImmediateActionData extends ActionData {
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package work.slhaf.partner.core.action.entity;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import work.slhaf.partner.module.modules.action.dispatcher.executor.entity.HistoryAction;
|
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 计划行动数据类,继承自{@link ActionData},扩展了属性{@link ScheduledActionData#type}和{@link ScheduledActionData#scheduleContent},用于标识计划类型(单次还是周期性任务)和计划内容
|
|
||||||
*/
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
|
||||||
public class ScheduledActionData extends ActionData {
|
|
||||||
private ScheduledType type;
|
|
||||||
private String scheduleContent; //如果为周期,则对应cron表达式,如果为一次性,则对应为ZonedDateTime字符串
|
|
||||||
private List<ScheduledHistory> scheduledHistories = new ArrayList<>();
|
|
||||||
|
|
||||||
public void recordAndReset() {
|
|
||||||
this.scheduledHistories.add(new ScheduledHistory(ZonedDateTime.now(), this.result, Map.copyOf(this.history)));
|
|
||||||
|
|
||||||
// 清理执行时内容
|
|
||||||
this.additionalContext.clear();
|
|
||||||
this.executingStage = 0;
|
|
||||||
this.getActionChain().forEach((stage, actions) -> {
|
|
||||||
for (MetaAction action : actions) {
|
|
||||||
action.getParams().clear();
|
|
||||||
action.setResult(new MetaAction.Result());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.setStatus(ActionStatus.PREPARE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ScheduledType {
|
|
||||||
CYCLE, ONCE
|
|
||||||
}
|
|
||||||
|
|
||||||
private record ScheduledHistory(ZonedDateTime endTime, String result, Map<Integer, List<HistoryAction>> history) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -90,7 +90,7 @@ class ActionScheduler : AgentRunningSubModule<Set<ScheduledActionData>, Void>()
|
|||||||
}
|
}
|
||||||
|
|
||||||
val parseToZonedDateTime = parseToZonedDateTime(
|
val parseToZonedDateTime = parseToZonedDateTime(
|
||||||
actionData.type,
|
actionData.scheduleType,
|
||||||
actionData.scheduleContent,
|
actionData.scheduleContent,
|
||||||
ZonedDateTime.now()
|
ZonedDateTime.now()
|
||||||
) ?: run {
|
) ?: run {
|
||||||
@@ -226,7 +226,7 @@ class ActionScheduler : AgentRunningSubModule<Set<ScheduledActionData>, Void>()
|
|||||||
for (actionData in primaryActions) {
|
for (actionData in primaryActions) {
|
||||||
val latestExecutingTime =
|
val latestExecutingTime =
|
||||||
parseToZonedDateTime(
|
parseToZonedDateTime(
|
||||||
actionData.type,
|
actionData.scheduleType,
|
||||||
actionData.scheduleContent,
|
actionData.scheduleContent,
|
||||||
now
|
now
|
||||||
) ?: run {
|
) ?: run {
|
||||||
@@ -250,12 +250,13 @@ class ActionScheduler : AgentRunningSubModule<Set<ScheduledActionData>, Void>()
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun parseToZonedDateTime(
|
private fun parseToZonedDateTime(
|
||||||
scheduleType: ScheduledActionData.ScheduledType,
|
scheduleType: ScheduledActionData.ScheduleType,
|
||||||
scheduleContent: String,
|
scheduleContent: String,
|
||||||
now: ZonedDateTime
|
now: ZonedDateTime
|
||||||
): ZonedDateTime? {
|
): ZonedDateTime? {
|
||||||
return when (scheduleType) {
|
return when (scheduleType) {
|
||||||
ScheduledActionData.ScheduledType.CYCLE -> {
|
ScheduledActionData.ScheduleType.CYCLE
|
||||||
|
-> {
|
||||||
val cron = try {
|
val cron = try {
|
||||||
cronParser.parse(scheduleContent).validate()
|
cronParser.parse(scheduleContent).validate()
|
||||||
} catch (_: Exception) {
|
} catch (_: Exception) {
|
||||||
@@ -265,7 +266,7 @@ class ActionScheduler : AgentRunningSubModule<Set<ScheduledActionData>, Void>()
|
|||||||
executionTime.nextExecution(now).getOrNull()
|
executionTime.nextExecution(now).getOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
ScheduledActionData.ScheduledType.ONCE -> {
|
ScheduledActionData.ScheduleType.ONCE -> {
|
||||||
val executionTime = try {
|
val executionTime = try {
|
||||||
ZonedDateTime.parse(scheduleContent)
|
ZonedDateTime.parse(scheduleContent)
|
||||||
} catch (_: Exception) {
|
} catch (_: Exception) {
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ public class ActionPlanner extends PreRunningModule {
|
|||||||
|
|
||||||
private void putActionData(List<EvaluatorResult> evaluatorResults, PartnerRunningFlowContext context) {
|
private void putActionData(List<EvaluatorResult> evaluatorResults, PartnerRunningFlowContext context) {
|
||||||
for (EvaluatorResult evaluatorResult : evaluatorResults) {
|
for (EvaluatorResult evaluatorResult : evaluatorResults) {
|
||||||
ActionData actionData = assemblyHelper.buildActionData(evaluatorResult);
|
ActionData actionData = assemblyHelper.buildActionData(evaluatorResult, context.getUserId());
|
||||||
if (evaluatorResult.isNeedConfirm()) {
|
if (evaluatorResult.isNeedConfirm()) {
|
||||||
actionCapability.putPendingActions(context.getUserId(), actionData);
|
actionCapability.putPendingActions(context.getUserId(), actionData);
|
||||||
} else {
|
} else {
|
||||||
@@ -231,24 +231,25 @@ public class ActionPlanner extends PreRunningModule {
|
|||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ActionData buildActionData(EvaluatorResult evaluatorResult) {
|
private ActionData buildActionData(EvaluatorResult evaluatorResult, String userId) {
|
||||||
Map<Integer, List<MetaAction>> actionChain = getActionChain(evaluatorResult);
|
Map<Integer, List<MetaAction>> actionChain = getActionChain(evaluatorResult);
|
||||||
return switch (evaluatorResult.getType()) {
|
return switch (evaluatorResult.getType()) {
|
||||||
case PLANNING -> {
|
case PLANNING -> new ScheduledActionData(
|
||||||
ScheduledActionData actionInfo = new ScheduledActionData();
|
evaluatorResult.getTendency(),
|
||||||
actionInfo.setActionChain(actionChain);
|
actionChain,
|
||||||
actionInfo.setScheduleContent(evaluatorResult.getScheduleContent());
|
evaluatorResult.getReason(),
|
||||||
actionInfo.setStatus(ActionData.ActionStatus.PREPARE);
|
evaluatorResult.getDescription(),
|
||||||
actionInfo.setUuid(UUID.randomUUID().toString());
|
userId,
|
||||||
yield actionInfo;
|
evaluatorResult.getScheduleType(),
|
||||||
}
|
evaluatorResult.getScheduleContent()
|
||||||
case IMMEDIATE -> {
|
);
|
||||||
ImmediateActionData actionInfo = new ImmediateActionData();
|
case IMMEDIATE -> new ImmediateActionData(
|
||||||
actionInfo.setActionChain(actionChain);
|
evaluatorResult.getTendency(),
|
||||||
actionInfo.setStatus(ActionData.ActionStatus.PREPARE);
|
actionChain,
|
||||||
actionInfo.setUuid(UUID.randomUUID().toString());
|
evaluatorResult.getReason(),
|
||||||
yield actionInfo;
|
evaluatorResult.getDescription(),
|
||||||
}
|
userId
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package work.slhaf.partner.module.modules.action.planner.evaluator.entity;
|
package work.slhaf.partner.module.modules.action.planner.evaluator.entity;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import work.slhaf.partner.core.action.entity.ScheduledActionData;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -11,8 +12,11 @@ public class EvaluatorResult {
|
|||||||
private boolean needConfirm;
|
private boolean needConfirm;
|
||||||
private ActionType type;
|
private ActionType type;
|
||||||
private String scheduleContent;
|
private String scheduleContent;
|
||||||
|
private ScheduledActionData.ScheduleType scheduleType;
|
||||||
private Map<Integer, List<String>> primaryActionChain;
|
private Map<Integer, List<String>> primaryActionChain;
|
||||||
private String tendency;
|
private String tendency;
|
||||||
|
private String reason;
|
||||||
|
private String description;
|
||||||
|
|
||||||
public enum ActionType {
|
public enum ActionType {
|
||||||
IMMEDIATE, PLANNING
|
IMMEDIATE, PLANNING
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package work.slhaf.partner.module.modules.action.dispatcher.executor;
|
package work.slhaf.partner.module.modules.action.dispatcher.executor;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import lombok.val;
|
||||||
import org.junit.jupiter.api.*;
|
import org.junit.jupiter.api.*;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
@@ -373,15 +374,15 @@ class ActionExecutorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ImmediateActionData buildActionData(Map<Integer, List<MetaAction>> actionChain) {
|
private ImmediateActionData buildActionData(Map<Integer, List<MetaAction>> actionChain) {
|
||||||
ImmediateActionData actionData = new ImmediateActionData();
|
val immediateActionData = new ImmediateActionData(
|
||||||
actionData.setStatus(ActionData.ActionStatus.PREPARE);
|
"tendency",
|
||||||
actionData.setActionChain(actionChain);
|
actionChain,
|
||||||
actionData.setAdditionalContext(initAdditionalContext(actionChain));
|
"reason",
|
||||||
actionData.setReason("reason");
|
"desc",
|
||||||
actionData.setDescription("desc");
|
"source"
|
||||||
actionData.setSource("source");
|
);
|
||||||
actionData.setTendency("tendency");
|
immediateActionData.getAdditionalContext().putAll(initAdditionalContext(actionChain));
|
||||||
return actionData;
|
return immediateActionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Integer, List<MetaAction>> singleStageChain(boolean io) {
|
private Map<Integer, List<MetaAction>> singleStageChain(boolean io) {
|
||||||
|
|||||||
Reference in New Issue
Block a user