From b164a2cd0a823c30460f6382d011d791eefe5523 Mon Sep 17 00:00:00 2001 From: Robert von Burg Date: Fri, 21 Jan 2022 17:14:54 +0100 Subject: [PATCH] [New] ReservationExecution now has a new semaphore mode This allows the execution policy to make sure that only x activities of a type are in execution --- .../policy/ReservationExecution.java | 47 ++++++++++++++++--- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/li.strolch.service/src/main/java/li/strolch/execution/policy/ReservationExecution.java b/li.strolch.service/src/main/java/li/strolch/execution/policy/ReservationExecution.java index 278831dab..c8fdc03c2 100644 --- a/li.strolch.service/src/main/java/li/strolch/execution/policy/ReservationExecution.java +++ b/li.strolch.service/src/main/java/li/strolch/execution/policy/ReservationExecution.java @@ -5,24 +5,38 @@ import static li.strolch.model.StrolchModelConstants.PolicyConstants.*; import li.strolch.exception.StrolchModelException; import li.strolch.model.Resource; +import li.strolch.model.StrolchModelConstants; import li.strolch.model.activity.Action; +import li.strolch.model.activity.Activity; import li.strolch.model.parameter.BooleanParameter; +import li.strolch.model.parameter.IntegerParameter; +import li.strolch.model.parameter.StringListParameter; import li.strolch.persistence.api.StrolchTransaction; import li.strolch.runtime.StrolchConstants; /** + *

This reservation execution policy has two modes of functioning:

+ * + * *

- * This extension of the {@link DurationExecution} overrides the {@link #isExecutable(Action)} method and validates that - * the {@link Resource} to which the {@link Action} is attached, has a {@link BooleanParameter} reserved - * and only allows execution if the value is false, in which case the {@link #toExecution(Action)} method sets the value - * to true, and the {@link #toExecuted(Action)} method returns the value to false. + * The rules are enforced in the {@link #isExecutable(Action)} method, and simply executed in the {@link #toExecuted(Action)} method *

* *

- * Note: the reservation is done for {@link Action} of type {@link StrolchConstants.PolicyConstants#TYPE_RESERVE} + * Note 1: the reservation is done for {@link Action} of type {@link StrolchConstants.PolicyConstants#TYPE_RESERVE} * and releasing is done for {@link Action} of type {@link StrolchConstants.PolicyConstants#TYPE_RELEASE} *

* + *

Note 2: the semaphore is done of {@link Action Actions} of type {@link StrolchModelConstants.PolicyConstants#TYPE_JOB_COUNT_SEMAPHORE}

+ * * @author Robert von Burg */ public class ReservationExecution extends DurationExecution { @@ -36,6 +50,8 @@ public class ReservationExecution extends DurationExecution { return switch (action.getType()) { case TYPE_RESERVE -> !isReserved(tx(), action); case TYPE_RELEASE -> true; + case TYPE_JOB_COUNT_SEMAPHORE -> jobCountSemaphoreSatisfied(action); + default -> super.isExecutable(action); }; } @@ -43,7 +59,7 @@ public class ReservationExecution extends DurationExecution { @Override public void toExecution(Action action) { switch (action.getType()) { - case TYPE_RESERVE, TYPE_RELEASE -> toExecuted(action); + case TYPE_RESERVE, TYPE_RELEASE, TYPE_JOB_COUNT_SEMAPHORE -> toExecuted(action); default -> super.toExecution(action); } } @@ -81,4 +97,23 @@ public class ReservationExecution extends DurationExecution { // save changes tx.update(resource); } + + protected boolean jobCountSemaphoreSatisfied(Action action) { + StringListParameter jobCountSemaphoreTypesP = action.findParameter(BAG_OBJECTIVES, + PARAM_JOB_COUNT_SEMAPHORE_TYPES, false); + String[] types = jobCountSemaphoreTypesP == null ? + new String[] { action.getRootElement().getType() } : + jobCountSemaphoreTypesP.getValue().toArray(String[]::new); + + long nrOfActivitiesInExecution = tx().streamActivities(types).filter(Activity::inExecutionPlanningPhase) + .count(); + + IntegerParameter jobCountSemaphoreP = action.findParameter(BAG_OBJECTIVES, PARAM_JOB_COUNT_SEMAPHORE, true); + if (nrOfActivitiesInExecution < jobCountSemaphoreP.getValue()) + return true; + + logger.error("Action " + action.getLocator() + " is not executable as there are " + nrOfActivitiesInExecution + + " activities in execution with type(s): " + jobCountSemaphoreP.getValueAsString()); + return false; + } }