From ae1b7fc033f63a7080c0317443b47d2707be8751 Mon Sep 17 00:00:00 2001 From: slhafzjw Date: Sat, 7 Mar 2026 15:30:25 +0800 Subject: [PATCH] refactor(ActionScheduler): support receiving single data that implements Schedulable and Action in ActionScheduler --- .../action/executor/ActionExecutor.java | 3 +- .../modules/action/planner/ActionPlanner.java | 2 +- .../action/scheduler/ActionScheduler.kt | 18 +++++------ .../executor/ActionSchedulerTest.kt | 32 ++++++++----------- 4 files changed, 24 insertions(+), 31 deletions(-) diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/executor/ActionExecutor.java b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/executor/ActionExecutor.java index 8c39699e..0926ee37 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/executor/ActionExecutor.java +++ b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/executor/ActionExecutor.java @@ -16,7 +16,6 @@ import work.slhaf.partner.module.modules.action.scheduler.ActionScheduler; import java.util.ArrayList; import java.util.List; -import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Phaser; @@ -160,7 +159,7 @@ public class ActionExecutor extends AbstractAgentModule.Standalone { // 如果是 ScheduledActionData, 则重置 ActionData 内容,记录执行历史与最终结果 if (executableAction instanceof SchedulableExecutableAction scheduledActionData) { scheduledActionData.recordAndReset(); - actionScheduler.schedule(Set.of(scheduledActionData)); + actionScheduler.schedule(scheduledActionData); } else { executableAction.setStatus(Action.Status.SUCCESS); } diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/ActionPlanner.java b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/ActionPlanner.java index 58494687..f8649fed 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/ActionPlanner.java +++ b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/planner/ActionPlanner.java @@ -152,7 +152,7 @@ public class ActionPlanner extends PreRunningAbstractAgentModuleAbstract { } // execute or schedule it immediately switch (executableAction) { - case SchedulableExecutableAction action -> actionScheduler.schedule(Set.of(action)); + case SchedulableExecutableAction action -> actionScheduler.schedule(action); case ImmediateExecutableAction action -> actionExecutor.execute(action); default -> log.error("unknown executable action type: {}", executableAction.getClass().getSimpleName()); } diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/scheduler/ActionScheduler.kt b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/scheduler/ActionScheduler.kt index 979edb16..d78d88c6 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/scheduler/ActionScheduler.kt +++ b/Partner-Core/src/main/java/work/slhaf/partner/module/modules/action/scheduler/ActionScheduler.kt @@ -70,16 +70,14 @@ class ActionScheduler : AbstractAgentModule.Standalone() { // TODO any implementations of Action should be record into ActionCore // TODO the method in ActionCapability should be compatible with different Action types - fun schedule(input: Set) = schedulerScope.launch { - for (schedulableData in input) { - if (!schedulableData.enabled) { - continue - } - log.debug("New data to schedule: {}", schedulableData) - timeWheel.schedule(schedulableData) - if (schedulableData is SchedulableExecutableAction) { - actionCapability.putAction(schedulableData) - } + fun schedule(schedulableAction: T) where T : Action, T : Schedulable = schedulerScope.launch { + if (!schedulableAction.enabled) { + return@launch + } + log.debug("New data to schedule: {}", schedulableAction) + timeWheel.schedule(schedulableAction) + if (schedulableAction is SchedulableExecutableAction) { + actionCapability.putAction(schedulableAction) } } diff --git a/Partner-Core/src/test/java/work/slhaf/partner/module/modules/action/dispatcher/executor/ActionSchedulerTest.kt b/Partner-Core/src/test/java/work/slhaf/partner/module/modules/action/dispatcher/executor/ActionSchedulerTest.kt index 368c6055..c002f191 100644 --- a/Partner-Core/src/test/java/work/slhaf/partner/module/modules/action/dispatcher/executor/ActionSchedulerTest.kt +++ b/Partner-Core/src/test/java/work/slhaf/partner/module/modules/action/dispatcher/executor/ActionSchedulerTest.kt @@ -14,11 +14,11 @@ import org.mockito.Mockito.verify import org.mockito.junit.jupiter.MockitoExtension import org.slf4j.LoggerFactory import work.slhaf.partner.core.action.ActionCapability +import work.slhaf.partner.core.action.entity.Action import work.slhaf.partner.core.action.entity.ExecutableAction import work.slhaf.partner.core.action.entity.Schedulable import work.slhaf.partner.core.action.entity.SchedulableExecutableAction import work.slhaf.partner.module.modules.action.executor.ActionExecutor -import work.slhaf.partner.module.modules.action.executor.entity.ActionExecutorInput import work.slhaf.partner.module.modules.action.scheduler.ActionScheduler import java.time.ZonedDateTime import java.time.temporal.ChronoUnit @@ -83,10 +83,8 @@ class ActionSchedulerTest { .thenReturn(actions as Set) Mockito.`when`(actionExecutor.execute(any())) .thenAnswer { - val input = it.arguments[0] as ActionExecutorInput - for (actionData in input.actions) { - log.info("Executed action $actionData at ${ZonedDateTime.now()}") - } + val actionData = it.arguments[0] as ExecutableAction + log.info("Executed action $actionData at ${ZonedDateTime.now()}") null } actionScheduler.init() @@ -94,11 +92,7 @@ class ActionSchedulerTest { val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default + CoroutineName("ActionSchedulerTest")) scope.launch { - actionScheduler.schedule( - setOf( - buildAction(now.plusSeconds(5)), - ) - ) + actionScheduler.schedule(buildAction(now.plusSeconds(5))) } readlnOrNull() } @@ -112,7 +106,7 @@ class ActionSchedulerTest { ZonedDateTime.now().plusHours(1).toString() ) - actionScheduler.schedule(setOf(action)) + actionScheduler.schedule(action) verify(actionCapability, times(1)).putAction(action) val timeWheel = timeWheel() @@ -128,7 +122,7 @@ class ActionSchedulerTest { type = Schedulable.ScheduleType.ONCE ) - actionScheduler.schedule(setOf(action)) + actionScheduler.schedule(action) verify(actionCapability, times(1)).putAction(action) val allScheduled = allScheduledActions(timeWheel()) @@ -143,7 +137,7 @@ class ActionSchedulerTest { type = Schedulable.ScheduleType.ONCE ) - actionScheduler.schedule(setOf(action)) + actionScheduler.schedule(action) val allScheduled = allScheduledActions(timeWheel()) assertFalse(allScheduled.contains(action)) @@ -158,7 +152,7 @@ class ActionSchedulerTest { scheduleContentOverride = "invalid-cron" ) - actionScheduler.schedule(setOf(action)) + actionScheduler.schedule(action) val allScheduled = allScheduledActions(timeWheel()) assertFalse(allScheduled.contains(action)) @@ -176,7 +170,7 @@ class ActionSchedulerTest { .putAction(action) assertThrows(RuntimeException::class.java) { - actionScheduler.schedule(setOf(action)) + actionScheduler.schedule(action) } } @@ -194,7 +188,7 @@ class ActionSchedulerTest { setCurrentHour(timeWheel, actionHour) setWheelState(timeWheel, "SLEEPING") - actionScheduler.schedule(setOf(action)) + actionScheduler.schedule(action) assertEquals("ACTIVE", wheelStateName(timeWheel)) } @@ -211,13 +205,15 @@ class ActionSchedulerTest { type = Schedulable.ScheduleType.ONCE, scheduleContentOverride = ZonedDateTime.now().plusMinutes(2).toString() ) - nonPrepare.status = ExecutableAction.Status.FAILED + nonPrepare.status = Action.Status.FAILED val invalid = buildScheduledAction( type = Schedulable.ScheduleType.CYCLE, scheduleContentOverride = "invalid-cron" ) - actionScheduler.schedule(setOf(ok, nonPrepare, invalid)) + actionScheduler.schedule(ok) + actionScheduler.schedule(nonPrepare) + actionScheduler.schedule(invalid) verify(actionCapability, times(1)).putAction(ok) verify(actionCapability, times(1)).putAction(nonPrepare)