[New] Extending execution policies for warning task

This commit is contained in:
Robert von Burg 2022-10-11 15:53:50 +02:00
parent 7f3bfd8fac
commit 0ce29fb2a1
Signed by: eitch
GPG Key ID: 75DB9C85C74331F7
4 changed files with 142 additions and 38 deletions

View File

@ -1,9 +1,13 @@
package li.strolch.execution;
import java.time.Duration;
import java.util.concurrent.ScheduledFuture;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.execution.policy.ExecutionPolicy;
import li.strolch.model.Locator;
import li.strolch.model.activity.Action;
import li.strolch.utils.time.PeriodDuration;
/**
* A decoupling of {@link ExecutionPolicy ExecutionPolicies} so that the execution can be performed after a certain
@ -14,6 +18,26 @@ import li.strolch.model.activity.Action;
*/
public interface DelayedExecutionTimer {
/**
* Delays the execution of the given {@link Runnable} by the given {@link PeriodDuration}
*
* @param duration
* the duration before calling the {@link Runnable}
* @param runnable
* the action to call after the given delay
*/
ScheduledFuture<?> delay(PeriodDuration duration, Runnable runnable);
/**
* Delays the execution of the given {@link Runnable} by the given {@link Duration}
*
* @param duration
* the duration before calling the {@link Runnable}
* @param runnable
* the action to call after the given delay
*/
ScheduledFuture<?> delay(Duration duration, Runnable runnable);
/**
* Delays the execution of the given {@link Runnable} by the given milliseconds
*
@ -22,7 +46,7 @@ public interface DelayedExecutionTimer {
* @param runnable
* the action to call after the given delay
*/
void delay(long duration, Runnable runnable);
ScheduledFuture<?> delay(long duration, Runnable runnable);
/**
* Completes the execution of the given {@link Action} {@link Locator} after the given duration in milliseconds

View File

@ -2,6 +2,7 @@ package li.strolch.execution;
import static li.strolch.runtime.StrolchConstants.SYSTEM_USER_AGENT;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@ -17,6 +18,7 @@ import li.strolch.model.Locator;
import li.strolch.model.log.LogMessage;
import li.strolch.model.log.LogMessageState;
import li.strolch.model.log.LogSeverity;
import li.strolch.utils.time.PeriodDuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -49,8 +51,18 @@ public class SimpleDurationExecutionTimer implements DelayedExecutionTimer {
}
@Override
public void delay(long duration, Runnable runnable) {
getExecutor().schedule(runnable, duration, TimeUnit.MILLISECONDS);
public ScheduledFuture<?> delay(PeriodDuration duration, Runnable runnable) {
return delay(duration.toMillis(), runnable);
}
@Override
public ScheduledFuture<?> delay(Duration duration, Runnable runnable) {
return delay(duration.toMillis(), runnable);
}
@Override
public ScheduledFuture<?> delay(long duration, Runnable runnable) {
return getExecutor().schedule(runnable, duration, TimeUnit.MILLISECONDS);
}
@Override
@ -93,8 +105,9 @@ public class SimpleDurationExecutionTimer implements DelayedExecutionTimer {
logger.error("Failed to set " + locator + " to executed due to " + e.getMessage(), e);
if (this.agent.getContainer().hasComponent(OperationsLog.class)) {
this.agent.getContainer().getComponent(OperationsLog.class).addMessage(
new LogMessage(realm, SYSTEM_USER_AGENT, locator, LogSeverity.Exception,
this.agent.getContainer()
.getComponent(OperationsLog.class)
.addMessage(new LogMessage(realm, SYSTEM_USER_AGENT, locator, LogSeverity.Exception,
LogMessageState.Information, ResourceBundle.getBundle("strolch-service"),
"execution.handler.failed.executed").withException(e).value("reason", e));
}

View File

@ -16,6 +16,7 @@ import li.strolch.execution.Controller;
import li.strolch.execution.DelayedExecutionTimer;
import li.strolch.execution.ExecutionHandler;
import li.strolch.model.Locator;
import li.strolch.model.Resource;
import li.strolch.model.State;
import li.strolch.model.activity.Action;
import li.strolch.model.activity.Activity;
@ -50,6 +51,7 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
protected String realm;
protected String actionType;
protected Locator resourceLoc;
protected Locator actionLoc;
/**
@ -65,7 +67,8 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
}
/**
* <p>Set the {@link Controller} for this execution policy. Usually called by the controller itself, when instantiating this instance</p>
* <p>Set the {@link Controller} for this execution policy. Usually called by the controller itself, when
* instantiating this instance</p>
*
* <p><b>Note:</b> This is used as execution policies can have a longer lifecycle than its transaction.</p>
*
@ -89,6 +92,22 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
return this.controller;
}
/**
* Returns the type of the {@link Resource} for this action. Can only be called after {@link #initialize(Action)}
* was called.
*/
protected String getResourceType() {
return this.resourceLoc.get(1);
}
/**
* Returns the id of the {@link Resource} for this action. Can only be called after {@link #initialize(Action)} was
* called.
*/
protected String getResourceId() {
return this.resourceLoc.get(2);
}
/**
* Returns the {@link ExecutionHandler}
*
@ -144,8 +163,8 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
}
/**
* Performs any initialization of this {@link ExecutionPolicy} for the given action, this method stores the {@link
* Locator} of the action and its type
* Performs any initialization of this {@link ExecutionPolicy} for the given action, this method stores the
* {@link Locator} of the action and its type
*
* @param action
* the action for which to initialize
@ -153,6 +172,7 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
public void initialize(Action action) {
this.actionType = action.getType();
this.actionLoc = action.getLocator();
this.resourceLoc = action.getResourceLocator();
}
/**
@ -172,8 +192,8 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
public abstract void toExecuted(Action action);
/**
* Stops the execution of this {@link Action} without completing its execution, i.e. sets the state to {@link
* State#STOPPED}
* Stops the execution of this {@link Action} without completing its execution, i.e. sets the state to
* {@link State#STOPPED}
*
* @param action
* the action to stop execution for
@ -181,8 +201,8 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
public abstract void toStopped(Action action);
/**
* Sets this {@link Action} which should be in execution to an error state, i.e. sets the state to {@link
* State#ERROR}
* Sets this {@link Action} which should be in execution to an error state, i.e. sets the state to
* {@link State#ERROR}
*
* @param action
* the action to set to error state
@ -190,8 +210,8 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
public abstract void toError(Action action);
/**
* Sets this {@link Action} which should be in execution to a warning state, i.e. sets the state to {@link
* State#WARNING}
* Sets this {@link Action} which should be in execution to a warning state, i.e. sets the state to
* {@link State#WARNING}
*
* @param action
* the action to set to warning state
@ -219,7 +239,8 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
}
/**
* Updates the state of the given {@link Action} to the given {@link State} and updates the {@link Activity} for persisting on the TX
* Updates the state of the given {@link Action} to the given {@link State} and updates the {@link Activity} for
* persisting on the TX
*
* @param action
* the action to change
@ -241,6 +262,16 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
logger.info(msg);
}
/**
* Finds the duration of the given {@link Action} by searching the activity hierarchy using
* {@link Action#findParameter(String, String, boolean)} using #BAG_OBJECTIVES and #PARAM_DURATION.
*
* @return the {@link DurationParameter}
*/
protected DurationParameter findActionDuration(Action action) {
return action.findParameter(BAG_OBJECTIVES, PARAM_DURATION, true);
}
/**
* Delays the given {@link Runnable} by the given {@link Duration}
*
@ -255,15 +286,16 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
}
/**
* Async method to delay setting the given {@link Action} to executed by the duration defined by the {@link DurationParameter} found by calling {@link Action#findParameter(String, String, boolean)}
* Async method to delay setting the given {@link Action} to executed by the duration defined by the
* {@link DurationParameter} found by calling {@link Action#findParameter(String, String, boolean)}
*/
protected void delayToExecuted(Action action) {
DurationParameter durationP = action.findParameter(BAG_OBJECTIVES, PARAM_DURATION, true);
delayToExecutedBy(durationP);
delayToExecutedBy(findActionDuration(action));
}
/**
* Async method to delay setting the {@link Action} to executed by the duration defined by the given {@link DurationParameter}
* Async method to delay setting the {@link Action} to executed by the duration defined by the given
* {@link DurationParameter}
*/
protected void delayToExecutedBy(DurationParameter durationP) {
long duration = durationP.getValue().toMillis();
@ -278,8 +310,8 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
}
/**
* Async method to delay setting the {@link Action} to executed by the given duration,
* but randomly changing the duration in milliseconds by the given min and max factors
* Async method to delay setting the {@link Action} to executed by the given duration, but randomly changing the
* duration in milliseconds by the given min and max factors
*/
protected void delayToExecutedByRandom(Duration duration, double minFactor, double maxFactor) {
long durationMs = duration.toMillis();
@ -287,19 +319,17 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
}
/**
* Async method to delay setting the given {@link Action} to executed by the duration defined
* by the {@link DurationParameter} found by calling {@link Action#findParameter(String, String, boolean)},
* but randomly changing the duration in milliseconds by the given min and max factors
* Async method to delay setting the given {@link Action} to executed by the duration defined by the
* {@link DurationParameter} found by calling {@link Action#findParameter(String, String, boolean)}, but randomly
* changing the duration in milliseconds by the given min and max factors
*/
protected void delayToExecutedByRandom(Action action, double minFactor, double maxFactor) {
DurationParameter durationP = action.findParameter(BAG_OBJECTIVES, PARAM_DURATION, true);
delayToExecutedByRandom(durationP, minFactor, maxFactor);
delayToExecutedByRandom(findActionDuration(action), minFactor, maxFactor);
}
/**
* Async method to delay setting the {@link Action} to executed
* by the duration defined by the given {@link DurationParameter},
* but randomly changing the duration in milliseconds by the given min and max factors
* Async method to delay setting the {@link Action} to executed by the duration defined by the given
* {@link DurationParameter}, but randomly changing the duration in milliseconds by the given min and max factors
*/
protected void delayToExecutedByRandom(DurationParameter durationP, double minFactor, double maxFactor) {
long duration = durationP.getValue().toMillis();
@ -307,16 +337,16 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
}
/**
* Async method to delay setting the {@link Action} to executed by the given duration,
* but randomly changing the duration in milliseconds by the given min and max factors
* Async method to delay setting the {@link Action} to executed by the given duration, but randomly changing the
* duration in milliseconds by the given min and max factors
*/
protected void delayToExecutedByRandom(long duration, double minFactor, double maxFactor, TimeUnit delayUnit) {
delayToExecutedByRandom((long) (duration * minFactor), (long) (duration * maxFactor), delayUnit);
}
/**
* Async method to delay setting the {@link Action} to executed by randomly choosing a value
* by calling {@link ThreadLocalRandom#nextLong(long, long)} passing min and max as origin and bound respectively
* Async method to delay setting the {@link Action} to executed by randomly choosing a value by calling
* {@link ThreadLocalRandom#nextLong(long, long)} passing min and max as origin and bound respectively
*/
protected void delayToExecutedByRandom(long min, long max, TimeUnit delayUnit) {
long delay = ThreadLocalRandom.current().nextLong(min, max + 1);
@ -345,13 +375,14 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
* @return the {@link DelayedExecutionTimer} to simplify the delayed execution of an {@link Action}, e.g. for
* simulated execution or simple wait tasks
*/
private DelayedExecutionTimer getDelayedExecutionTimer() {
protected DelayedExecutionTimer getDelayedExecutionTimer() {
return getComponent(ExecutionHandler.class).getDelayedExecutionTimer();
}
/**
* Opens a {@link StrolchTransaction} where the realm retrieved using {@link ComponentContainer#getRealm(Certificate)}.
* This transaction should be used in a try-with-resource clause so it is properly closed.
* Opens a {@link StrolchTransaction} where the realm retrieved using
* {@link ComponentContainer#getRealm(Certificate)}. This transaction should be used in a try-with-resource clause
* so it is properly closed.
*
* @param ctx
* the privilege context
@ -387,8 +418,8 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
}
/**
* Performs the given {@link PrivilegedRunnableWithResult} as the system user {@link
* StrolchConstants#SYSTEM_USER_AGENT}
* Performs the given {@link PrivilegedRunnableWithResult} as the system user
* {@link StrolchConstants#SYSTEM_USER_AGENT}
*
* @param runnable
* the runnable to perform

View File

@ -1,7 +1,9 @@
package li.strolch.execution.policy;
import java.util.concurrent.ScheduledFuture;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import li.strolch.exception.StrolchException;
import li.strolch.execution.ExecutionHandler;
@ -9,10 +11,12 @@ import li.strolch.handler.operationslog.OperationsLog;
import li.strolch.model.State;
import li.strolch.model.activity.Action;
import li.strolch.model.log.LogMessage;
import li.strolch.model.parameter.DurationParameter;
import li.strolch.model.timevalue.impl.FloatValue;
import li.strolch.model.timevalue.impl.ValueChange;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.utils.time.PeriodDuration;
/**
* <p>
@ -23,10 +27,36 @@ import li.strolch.privilege.model.PrivilegeContext;
*/
public class SimpleExecution extends ExecutionPolicy {
private ScheduledFuture<?> warningTask;
public SimpleExecution(StrolchTransaction tx) {
super(tx);
}
protected void startWarningTask(Action action, Supplier<LogMessage> handler) {
DurationParameter durationP = findActionDuration(action);
startWarningTask(durationP.getValue(), action, handler);
}
protected void startWarningTask(PeriodDuration duration, Action action, Supplier<LogMessage> handler) {
if (this.warningTask != null) {
logger.warn("There is already a warning task registered, for action " + action.getLocator()
+ ". Cancelling and creating a new task...");
this.warningTask.cancel(true);
this.warningTask = null;
}
DurationParameter durationP = findActionDuration(action);
this.warningTask = getDelayedExecutionTimer().delay(durationP.getValue(), () -> toWarning(handler.get()));
}
protected void cancelWarningTask() {
if (this.warningTask != null) {
this.warningTask.cancel(true);
this.warningTask = null;
}
}
@Override
public void toExecution(Action action) {
setActionState(action, State.EXECUTION);
@ -42,6 +72,7 @@ public class SimpleExecution extends ExecutionPolicy {
@Override
public void toExecuted(Action action) {
cancelWarningTask();
stop();
setActionState(action, State.EXECUTED);
@ -52,6 +83,7 @@ public class SimpleExecution extends ExecutionPolicy {
@Override
public void toStopped(Action action) {
cancelWarningTask();
stop();
setActionState(action, State.STOPPED);
@ -62,6 +94,7 @@ public class SimpleExecution extends ExecutionPolicy {
@Override
public void toError(Action action) {
cancelWarningTask();
stop();
setActionState(action, State.ERROR);
@ -78,12 +111,14 @@ public class SimpleExecution extends ExecutionPolicy {
}
protected void toExecuted() throws Exception {
cancelWarningTask();
stop();
getController().toExecuted(this.actionLoc);
getComponent(ExecutionHandler.class).triggerExecution(this.realm);
}
protected void toError(LogMessage message) {
cancelWarningTask();
stop();
logger.error("Action " + message.getLocator() + " failed because of: " + message.formatMessage());
addMessage(message);
@ -91,6 +126,7 @@ public class SimpleExecution extends ExecutionPolicy {
}
protected void toWarning(LogMessage message) {
cancelWarningTask();
stop();
addMessage(message);
getController().asyncToWarning(message.getLocator());