diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java index 3845a0c5a..c18cb5865 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java @@ -21,6 +21,7 @@ import javax.persistence.EntityManager; import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.OffsetBasedPageRequest; import org.eclipse.hawkbit.repository.RolloutFields; +import org.eclipse.hawkbit.repository.RolloutGroupManagement; import org.eclipse.hawkbit.repository.RolloutManagement; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException; @@ -32,7 +33,6 @@ import org.eclipse.hawkbit.repository.jpa.model.RolloutTargetGroup; import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupActionEvaluator; import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupConditionEvaluator; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; -import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -47,6 +47,7 @@ import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetWithActionType; import org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; +import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; @@ -100,6 +101,9 @@ public class JpaRolloutManagement implements RolloutManagement { @Autowired private RolloutTargetGroupRepository rolloutTargetGroupRepository; + @Autowired + private RolloutGroupManagement rolloutGroupManagement; + @Autowired private ActionRepository actionRepository; @@ -404,18 +408,19 @@ public class JpaRolloutManagement implements RolloutManagement { for (final JpaRollout rollout : rolloutsToCheck) { LOGGER.debug("Checking rollout {}", rollout); - final List rolloutGroups = rolloutGroupRepository.findByRolloutAndStatus(rollout, + + final List rolloutGroupsRunning = rolloutGroupRepository.findByRolloutAndStatus(rollout, RolloutGroupStatus.RUNNING); - if (rolloutGroups.isEmpty()) { + if (rolloutGroupsRunning.isEmpty()) { // no running rollouts, probably there was an error // somewhere at the latest group. And the latest group has // been switched from running into error state. So we need // to find the latest group which executeLatestRolloutGroup(rollout); } else { - LOGGER.debug("Rollout {} has {} running groups", rollout.getId(), rolloutGroups.size()); - executeRolloutGroups(rollout, rolloutGroups); + LOGGER.debug("Rollout {} has {} running groups", rollout.getId(), rolloutGroupsRunning.size()); + executeRolloutGroups(rollout, rolloutGroupsRunning); } if (isRolloutComplete(rollout)) { @@ -458,6 +463,9 @@ public class JpaRolloutManagement implements RolloutManagement { private void executeRolloutGroups(final JpaRollout rollout, final List rolloutGroups) { for (final JpaRolloutGroup rolloutGroup : rolloutGroups) { + + checkIfTargetsOfRolloutGroupDeleted(rolloutGroup); + // error state check, do we need to stop the whole // rollout because of error? final RolloutGroupErrorCondition errorCondition = rolloutGroup.getErrorCondition(); @@ -478,6 +486,27 @@ public class JpaRolloutManagement implements RolloutManagement { } } + private void checkIfTargetsOfRolloutGroupDeleted(final JpaRolloutGroup rolloutGroup) { + + final long countTargetsOfRolloutGroup = rolloutGroupManagement + .findRolloutGroupTargets(rolloutGroup, new OffsetBasedPageRequest(0, 1, null)).getTotalElements(); + + if (rolloutGroup.getTotalTargets() != countTargetsOfRolloutGroup) { + // targets have been deleted and we have to update the + // total target count in the rollout and the rollout group + final JpaRollout jpaRollout = (JpaRollout) rolloutGroup.getRollout(); + final long updatedTargetCount = jpaRollout.getTotalTargets() + - (rolloutGroup.getTotalTargets() - countTargetsOfRolloutGroup); + jpaRollout.setTotalTargets(updatedTargetCount); + final JpaRolloutGroup jpaRolloutGroup = rolloutGroup; + jpaRolloutGroup.setTotalTargets((int) countTargetsOfRolloutGroup); + + rolloutRepository.save(jpaRollout); + rolloutGroupRepository.save(jpaRolloutGroup); + } + + } + private void executeLatestRolloutGroup(final JpaRollout rollout) { final List latestRolloutGroup = rolloutGroupRepository .findByRolloutAndStatusNotOrderByIdDesc(rollout, RolloutGroupStatus.SCHEDULED); @@ -656,7 +685,7 @@ public class JpaRolloutManagement implements RolloutManagement { @Override public float getFinishedPercentForRunningGroup(final Long rolloutId, final RolloutGroup rolloutGroup) { - final int totalGroup = rolloutGroup.getTotalTargets(); + final long totalGroup = rolloutGroup.getTotalTargets(); final Long finished = actionRepository.countByRolloutIdAndRolloutGroupIdAndStatus(rolloutId, rolloutGroup.getId(), Action.Status.FINISHED); if (totalGroup == 0) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/ThresholdRolloutGroupSuccessCondition.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/ThresholdRolloutGroupSuccessCondition.java index 3c18b25ae..1a8c50ade 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/ThresholdRolloutGroupSuccessCondition.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/ThresholdRolloutGroupSuccessCondition.java @@ -8,17 +8,13 @@ */ package org.eclipse.hawkbit.repository.jpa.rollout.condition; -import org.eclipse.hawkbit.repository.OffsetBasedPageRequest; -import org.eclipse.hawkbit.repository.RolloutGroupManagement; import org.eclipse.hawkbit.repository.jpa.ActionRepository; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.RolloutGroup; -import org.eclipse.hawkbit.repository.model.Target; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; import org.springframework.stereotype.Component; /** @@ -29,9 +25,6 @@ import org.springframework.stereotype.Component; public class ThresholdRolloutGroupSuccessCondition implements RolloutGroupConditionEvaluator { private static final Logger LOGGER = LoggerFactory.getLogger(ThresholdRolloutGroupSuccessCondition.class); - @Autowired - private RolloutGroupManagement rolloutGroupManagement; - @Autowired private ActionRepository actionRepository; @@ -45,24 +38,17 @@ public class ThresholdRolloutGroupSuccessCondition implements RolloutGroupCondit return true; } - final long finishedByStatus = this.actionRepository.countByRolloutIdAndRolloutGroupIdAndStatus(rollout.getId(), + final long finished = this.actionRepository.countByRolloutIdAndRolloutGroupIdAndStatus(rollout.getId(), rolloutGroup.getId(), Action.Status.FINISHED); - final long finished = finishedByStatus + countDeletedTargets(rolloutGroup); - try { final Integer threshold = Integer.valueOf(expression); // calculate threshold - return ((float) finished / totalGroup) >= ((float) threshold / 100F); + return ((float) finished / (float) totalGroup) >= ((float) threshold / 100F); + } catch (final NumberFormatException e) { LOGGER.error("Cannot evaluate condition expression " + expression, e); return false; } } - private long countDeletedTargets(final RolloutGroup rolloutGroup) { - final Page targetsOfRolloutGroup = rolloutGroupManagement.findRolloutGroupTargets(rolloutGroup, - new OffsetBasedPageRequest(0, 1, null)); - return rolloutGroup.getTotalTargets() - targetsOfRolloutGroup.getTotalElements(); - } - } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java index 9ae9b5b1d..d036f1aa9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java @@ -170,7 +170,6 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest { final String errorCondition = "80"; final Rollout createdRollout = createSimpleTestRolloutWithTargetsAndDistributionSet(amountTargetsForRollout, amountOtherTargets, amountGroups, successCondition, errorCondition); - rolloutManagement.startRollout(createdRollout); // finish group one by finishing targets and deleting targets @@ -183,7 +182,6 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest { runningActions.get(4).getTarget().getId()); rolloutManagement.checkRunningRollouts(0); - // validate that the second group is in running state List runningRolloutGroups = rolloutGroupManagement.findRolloutGroupsByRolloutId( createdRollout.getId(), new OffsetBasedPageRequest(0, 10, new Sort(Direction.ASC, "id"))).getContent();