mirror of
https://github.com/slhaf/Partner.git
synced 2026-05-12 16:53:04 +08:00
refactor(ActionScheduler): support receiving single data that implements Schedulable and Action in ActionScheduler
This commit is contained in:
@@ -16,7 +16,6 @@ import work.slhaf.partner.module.modules.action.scheduler.ActionScheduler;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Phaser;
|
import java.util.concurrent.Phaser;
|
||||||
@@ -160,7 +159,7 @@ public class ActionExecutor extends AbstractAgentModule.Standalone {
|
|||||||
// 如果是 ScheduledActionData, 则重置 ActionData 内容,记录执行历史与最终结果
|
// 如果是 ScheduledActionData, 则重置 ActionData 内容,记录执行历史与最终结果
|
||||||
if (executableAction instanceof SchedulableExecutableAction scheduledActionData) {
|
if (executableAction instanceof SchedulableExecutableAction scheduledActionData) {
|
||||||
scheduledActionData.recordAndReset();
|
scheduledActionData.recordAndReset();
|
||||||
actionScheduler.schedule(Set.of(scheduledActionData));
|
actionScheduler.schedule(scheduledActionData);
|
||||||
} else {
|
} else {
|
||||||
executableAction.setStatus(Action.Status.SUCCESS);
|
executableAction.setStatus(Action.Status.SUCCESS);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ public class ActionPlanner extends PreRunningAbstractAgentModuleAbstract {
|
|||||||
}
|
}
|
||||||
// execute or schedule it immediately
|
// execute or schedule it immediately
|
||||||
switch (executableAction) {
|
switch (executableAction) {
|
||||||
case SchedulableExecutableAction action -> actionScheduler.schedule(Set.of(action));
|
case SchedulableExecutableAction action -> actionScheduler.schedule(action);
|
||||||
case ImmediateExecutableAction action -> actionExecutor.execute(action);
|
case ImmediateExecutableAction action -> actionExecutor.execute(action);
|
||||||
default -> log.error("unknown executable action type: {}", executableAction.getClass().getSimpleName());
|
default -> log.error("unknown executable action type: {}", executableAction.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,16 +70,14 @@ class ActionScheduler : AbstractAgentModule.Standalone() {
|
|||||||
|
|
||||||
// TODO any implementations of Action should be record into ActionCore
|
// TODO any implementations of Action should be record into ActionCore
|
||||||
// TODO the method in ActionCapability should be compatible with different Action types
|
// TODO the method in ActionCapability should be compatible with different Action types
|
||||||
fun schedule(input: Set<Schedulable>) = schedulerScope.launch {
|
fun <T> schedule(schedulableAction: T) where T : Action, T : Schedulable = schedulerScope.launch {
|
||||||
for (schedulableData in input) {
|
if (!schedulableAction.enabled) {
|
||||||
if (!schedulableData.enabled) {
|
return@launch
|
||||||
continue
|
}
|
||||||
}
|
log.debug("New data to schedule: {}", schedulableAction)
|
||||||
log.debug("New data to schedule: {}", schedulableData)
|
timeWheel.schedule(schedulableAction)
|
||||||
timeWheel.schedule(schedulableData)
|
if (schedulableAction is SchedulableExecutableAction) {
|
||||||
if (schedulableData is SchedulableExecutableAction) {
|
actionCapability.putAction(schedulableAction)
|
||||||
actionCapability.putAction(schedulableData)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ import org.mockito.Mockito.verify
|
|||||||
import org.mockito.junit.jupiter.MockitoExtension
|
import org.mockito.junit.jupiter.MockitoExtension
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import work.slhaf.partner.core.action.ActionCapability
|
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.ExecutableAction
|
||||||
import work.slhaf.partner.core.action.entity.Schedulable
|
import work.slhaf.partner.core.action.entity.Schedulable
|
||||||
import work.slhaf.partner.core.action.entity.SchedulableExecutableAction
|
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.ActionExecutor
|
||||||
import work.slhaf.partner.module.modules.action.executor.entity.ActionExecutorInput
|
|
||||||
import work.slhaf.partner.module.modules.action.scheduler.ActionScheduler
|
import work.slhaf.partner.module.modules.action.scheduler.ActionScheduler
|
||||||
import java.time.ZonedDateTime
|
import java.time.ZonedDateTime
|
||||||
import java.time.temporal.ChronoUnit
|
import java.time.temporal.ChronoUnit
|
||||||
@@ -83,10 +83,8 @@ class ActionSchedulerTest {
|
|||||||
.thenReturn(actions as Set<ExecutableAction>)
|
.thenReturn(actions as Set<ExecutableAction>)
|
||||||
Mockito.`when`(actionExecutor.execute(any()))
|
Mockito.`when`(actionExecutor.execute(any()))
|
||||||
.thenAnswer {
|
.thenAnswer {
|
||||||
val input = it.arguments[0] as ActionExecutorInput
|
val actionData = it.arguments[0] as ExecutableAction
|
||||||
for (actionData in input.actions) {
|
log.info("Executed action $actionData at ${ZonedDateTime.now()}")
|
||||||
log.info("Executed action $actionData at ${ZonedDateTime.now()}")
|
|
||||||
}
|
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
actionScheduler.init()
|
actionScheduler.init()
|
||||||
@@ -94,11 +92,7 @@ class ActionSchedulerTest {
|
|||||||
|
|
||||||
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default + CoroutineName("ActionSchedulerTest"))
|
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default + CoroutineName("ActionSchedulerTest"))
|
||||||
scope.launch {
|
scope.launch {
|
||||||
actionScheduler.schedule(
|
actionScheduler.schedule(buildAction(now.plusSeconds(5)))
|
||||||
setOf(
|
|
||||||
buildAction(now.plusSeconds(5)),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
readlnOrNull()
|
readlnOrNull()
|
||||||
}
|
}
|
||||||
@@ -112,7 +106,7 @@ class ActionSchedulerTest {
|
|||||||
ZonedDateTime.now().plusHours(1).toString()
|
ZonedDateTime.now().plusHours(1).toString()
|
||||||
)
|
)
|
||||||
|
|
||||||
actionScheduler.schedule(setOf(action))
|
actionScheduler.schedule(action)
|
||||||
|
|
||||||
verify(actionCapability, times(1)).putAction(action)
|
verify(actionCapability, times(1)).putAction(action)
|
||||||
val timeWheel = timeWheel()
|
val timeWheel = timeWheel()
|
||||||
@@ -128,7 +122,7 @@ class ActionSchedulerTest {
|
|||||||
type = Schedulable.ScheduleType.ONCE
|
type = Schedulable.ScheduleType.ONCE
|
||||||
)
|
)
|
||||||
|
|
||||||
actionScheduler.schedule(setOf(action))
|
actionScheduler.schedule(action)
|
||||||
|
|
||||||
verify(actionCapability, times(1)).putAction(action)
|
verify(actionCapability, times(1)).putAction(action)
|
||||||
val allScheduled = allScheduledActions(timeWheel())
|
val allScheduled = allScheduledActions(timeWheel())
|
||||||
@@ -143,7 +137,7 @@ class ActionSchedulerTest {
|
|||||||
type = Schedulable.ScheduleType.ONCE
|
type = Schedulable.ScheduleType.ONCE
|
||||||
)
|
)
|
||||||
|
|
||||||
actionScheduler.schedule(setOf(action))
|
actionScheduler.schedule(action)
|
||||||
|
|
||||||
val allScheduled = allScheduledActions(timeWheel())
|
val allScheduled = allScheduledActions(timeWheel())
|
||||||
assertFalse(allScheduled.contains(action))
|
assertFalse(allScheduled.contains(action))
|
||||||
@@ -158,7 +152,7 @@ class ActionSchedulerTest {
|
|||||||
scheduleContentOverride = "invalid-cron"
|
scheduleContentOverride = "invalid-cron"
|
||||||
)
|
)
|
||||||
|
|
||||||
actionScheduler.schedule(setOf(action))
|
actionScheduler.schedule(action)
|
||||||
|
|
||||||
val allScheduled = allScheduledActions(timeWheel())
|
val allScheduled = allScheduledActions(timeWheel())
|
||||||
assertFalse(allScheduled.contains(action))
|
assertFalse(allScheduled.contains(action))
|
||||||
@@ -176,7 +170,7 @@ class ActionSchedulerTest {
|
|||||||
.putAction(action)
|
.putAction(action)
|
||||||
|
|
||||||
assertThrows(RuntimeException::class.java) {
|
assertThrows(RuntimeException::class.java) {
|
||||||
actionScheduler.schedule(setOf(action))
|
actionScheduler.schedule(action)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,7 +188,7 @@ class ActionSchedulerTest {
|
|||||||
setCurrentHour(timeWheel, actionHour)
|
setCurrentHour(timeWheel, actionHour)
|
||||||
setWheelState(timeWheel, "SLEEPING")
|
setWheelState(timeWheel, "SLEEPING")
|
||||||
|
|
||||||
actionScheduler.schedule(setOf(action))
|
actionScheduler.schedule(action)
|
||||||
|
|
||||||
assertEquals("ACTIVE", wheelStateName(timeWheel))
|
assertEquals("ACTIVE", wheelStateName(timeWheel))
|
||||||
}
|
}
|
||||||
@@ -211,13 +205,15 @@ class ActionSchedulerTest {
|
|||||||
type = Schedulable.ScheduleType.ONCE,
|
type = Schedulable.ScheduleType.ONCE,
|
||||||
scheduleContentOverride = ZonedDateTime.now().plusMinutes(2).toString()
|
scheduleContentOverride = ZonedDateTime.now().plusMinutes(2).toString()
|
||||||
)
|
)
|
||||||
nonPrepare.status = ExecutableAction.Status.FAILED
|
nonPrepare.status = Action.Status.FAILED
|
||||||
val invalid = buildScheduledAction(
|
val invalid = buildScheduledAction(
|
||||||
type = Schedulable.ScheduleType.CYCLE,
|
type = Schedulable.ScheduleType.CYCLE,
|
||||||
scheduleContentOverride = "invalid-cron"
|
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(ok)
|
||||||
verify(actionCapability, times(1)).putAction(nonPrepare)
|
verify(actionCapability, times(1)).putAction(nonPrepare)
|
||||||
|
|||||||
Reference in New Issue
Block a user