Align dynamic action behaviour with the static ones (#1764)
Signed-off-by: Marinov Avgustin <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -497,6 +497,14 @@ public interface DeploymentManagement {
|
|||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||||
long startScheduledActionsByRolloutGroupParent(long rolloutId, long distributionSetId, Long rolloutGroupParentId);
|
long startScheduledActionsByRolloutGroupParent(long rolloutId, long distributionSetId, Long rolloutGroupParentId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the target assignments. Shall be part of same group
|
||||||
|
*
|
||||||
|
* @param rolloutGroupActions rollouts group actions part of a same group
|
||||||
|
*/
|
||||||
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||||
|
void startScheduledActions(final List<Action> rolloutGroupActions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@link DistributionSet} that is assigned to given {@link Target}.
|
* Returns {@link DistributionSet} that is assigned to given {@link Target}.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import java.lang.reflect.InvocationTargetException;
|
|||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -711,7 +712,7 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
|||||||
do {
|
do {
|
||||||
// Add up to TRANSACTION_TARGETS actions of the left targets
|
// Add up to TRANSACTION_TARGETS actions of the left targets
|
||||||
// In case a TransactionException is thrown this loop aborts
|
// In case a TransactionException is thrown this loop aborts
|
||||||
final long createdActions = createActionsForDynamicGroupInNewTransaction(rollout, group, groupTargetFilter,
|
final int createdActions = createActionsForDynamicGroupInNewTransaction(rollout, group, groupTargetFilter,
|
||||||
Math.min(TRANSACTION_TARGETS, targetsLeftToAdd));
|
Math.min(TRANSACTION_TARGETS, targetsLeftToAdd));
|
||||||
if (createdActions == 0) {
|
if (createdActions == 0) {
|
||||||
break; // no more to assign
|
break; // no more to assign
|
||||||
@@ -781,9 +782,9 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
|||||||
((JpaRolloutManagement) rolloutManagement).publishRolloutGroupCreatedEventAfterCommit(savedGroup, rollout);
|
((JpaRolloutManagement) rolloutManagement).publishRolloutGroupCreatedEventAfterCommit(savedGroup, rollout);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Long createActionsForDynamicGroupInNewTransaction(final JpaRollout rollout, final RolloutGroup group,
|
private int createActionsForDynamicGroupInNewTransaction(final JpaRollout rollout, final RolloutGroup group,
|
||||||
final String targetFilter, final long limit) {
|
final String targetFilter, final long limit) {
|
||||||
return DeploymentHelper.runInNewTransaction(txManager, "createActionsForRolloutDynamicGroup", status -> {
|
final List<Action> newActions = DeploymentHelper.runInNewTransaction(txManager, "createActionsForRolloutDynamicGroup", status -> {
|
||||||
final PageRequest pageRequest = PageRequest.of(0, Math.toIntExact(limit));
|
final PageRequest pageRequest = PageRequest.of(0, Math.toIntExact(limit));
|
||||||
final Slice<Target> targets = targetManagement.findByNotInGEGroupAndNotInActiveActionGEWeightOrInRolloutAndTargetFilterQueryAndCompatibleAndUpdatable(
|
final Slice<Target> targets = targetManagement.findByNotInGEGroupAndNotInActiveActionGEWeightOrInRolloutAndTargetFilterQueryAndCompatibleAndUpdatable(
|
||||||
pageRequest,
|
pageRequest,
|
||||||
@@ -791,15 +792,21 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
|||||||
rolloutGroupRepository.findByRolloutOrderByIdAsc(rollout).get(0).getId(),
|
rolloutGroupRepository.findByRolloutOrderByIdAsc(rollout).get(0).getId(),
|
||||||
targetFilter, rollout.getDistributionSet().getType());
|
targetFilter, rollout.getDistributionSet().getType());
|
||||||
|
|
||||||
if (targets.getNumberOfElements() > 0) {
|
if (targets.getNumberOfElements() == 0) {
|
||||||
final DistributionSet distributionSet = rollout.getDistributionSet();
|
return Collections.emptyList();
|
||||||
final ActionType actionType = rollout.getActionType();
|
|
||||||
final long forceTime = rollout.getForcedTime();
|
|
||||||
createActions(targets.getContent(), distributionSet, actionType, forceTime, rollout, group);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Long.valueOf(targets.getNumberOfElements());
|
final DistributionSet distributionSet = rollout.getDistributionSet();
|
||||||
|
final ActionType actionType = rollout.getActionType();
|
||||||
|
final long forceTime = rollout.getForcedTime();
|
||||||
|
return createActions(targets.getContent(), distributionSet, actionType, forceTime, rollout, group);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!newActions.isEmpty()) {
|
||||||
|
deploymentManagement.startScheduledActions(newActions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newActions.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -867,7 +874,7 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
|||||||
* scheduled actions the scheduled actions gets canceled. A scheduled action
|
* scheduled actions the scheduled actions gets canceled. A scheduled action
|
||||||
* is created in-active for static and running for dynamic groups.
|
* is created in-active for static and running for dynamic groups.
|
||||||
*/
|
*/
|
||||||
private void createActions(final Collection<Target> targets, final DistributionSet distributionSet,
|
private List<Action> createActions(final Collection<Target> targets, final DistributionSet distributionSet,
|
||||||
final ActionType actionType, final Long forcedTime, final Rollout rollout,
|
final ActionType actionType, final Long forcedTime, final Rollout rollout,
|
||||||
final RolloutGroup rolloutGroup) {
|
final RolloutGroup rolloutGroup) {
|
||||||
// cancel all current scheduled actions for this target. E.g. an action
|
// cancel all current scheduled actions for this target. E.g. an action
|
||||||
@@ -876,22 +883,27 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
|||||||
// created.
|
// created.
|
||||||
final List<Long> targetIds = targets.stream().map(Target::getId).collect(Collectors.toList());
|
final List<Long> targetIds = targets.stream().map(Target::getId).collect(Collectors.toList());
|
||||||
deploymentManagement.cancelInactiveScheduledActionsForTargets(targetIds);
|
deploymentManagement.cancelInactiveScheduledActionsForTargets(targetIds);
|
||||||
targets.forEach(target -> {
|
return targets.stream()
|
||||||
assertActionsPerTargetQuota(target, 1);
|
.map(target -> {
|
||||||
|
assertActionsPerTargetQuota(target, 1);
|
||||||
|
|
||||||
final JpaAction action = new JpaAction();
|
final JpaAction action = new JpaAction();
|
||||||
action.setTarget(target);
|
action.setTarget(target);
|
||||||
action.setActive(rolloutGroup.isDynamic());
|
action.setActive(false);
|
||||||
action.setDistributionSet(distributionSet);
|
action.setDistributionSet(distributionSet);
|
||||||
action.setActionType(actionType);
|
action.setActionType(actionType);
|
||||||
action.setForcedTime(forcedTime);
|
action.setForcedTime(forcedTime);
|
||||||
action.setStatus(rolloutGroup.isDynamic() ? Status.RUNNING : Status.SCHEDULED);
|
action.setStatus(Status.SCHEDULED);
|
||||||
action.setRollout(rollout);
|
action.setRollout(rollout);
|
||||||
action.setRolloutGroup(rolloutGroup);
|
action.setRolloutGroup(rolloutGroup);
|
||||||
action.setInitiatedBy(rollout.getCreatedBy());
|
action.setInitiatedBy(rollout.getCreatedBy());
|
||||||
rollout.getWeight().ifPresent(action::setWeight);
|
rollout.getWeight().ifPresent(action::setWeight);
|
||||||
actionRepository.save(action);
|
actionRepository.save(action);
|
||||||
});
|
|
||||||
|
return action;
|
||||||
|
})
|
||||||
|
.map(Action.class::cast)
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
|||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||||
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
|
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
|
||||||
import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository;
|
import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository;
|
||||||
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository;
|
|
||||||
import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository;
|
import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository;
|
||||||
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
|
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
|
||||||
import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications;
|
import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications;
|
||||||
@@ -645,44 +644,43 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
|||||||
long totalActionsCount = 0L;
|
long totalActionsCount = 0L;
|
||||||
long lastStartedActionsCount;
|
long lastStartedActionsCount;
|
||||||
do {
|
do {
|
||||||
lastStartedActionsCount = startScheduledActionsByRolloutGroupParentInNewTransaction(rolloutId,
|
lastStartedActionsCount = DeploymentHelper.runInNewTransaction(
|
||||||
distributionSetId, rolloutGroupParentId, ACTION_PAGE_LIMIT);
|
txManager,
|
||||||
|
"startScheduledActions-" + rolloutId,
|
||||||
|
status -> {
|
||||||
|
final Page<Action> rolloutGroupActions = findActionsByRolloutAndRolloutGroupParent(
|
||||||
|
rolloutId, rolloutGroupParentId, ACTION_PAGE_LIMIT);
|
||||||
|
|
||||||
|
if (rolloutGroupActions.getContent().isEmpty()) {
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
// self invocation won't check @PreAuthorize but it is already checked for the method
|
||||||
|
startScheduledActions(rolloutGroupActions.getContent());
|
||||||
|
|
||||||
|
return rolloutGroupActions.getTotalElements();
|
||||||
|
});
|
||||||
totalActionsCount += lastStartedActionsCount;
|
totalActionsCount += lastStartedActionsCount;
|
||||||
} while (lastStartedActionsCount > 0);
|
} while (lastStartedActionsCount > 0);
|
||||||
|
|
||||||
return totalActionsCount;
|
return totalActionsCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long startScheduledActionsByRolloutGroupParentInNewTransaction(final Long rolloutId,
|
|
||||||
final Long distributionSetId, final Long rolloutGroupParentId, final int limit) {
|
|
||||||
return DeploymentHelper.runInNewTransaction(txManager, "startScheduledActions-" + rolloutId, status -> {
|
|
||||||
final Page<Action> rolloutGroupActions = findActionsByRolloutAndRolloutGroupParent(rolloutId,
|
|
||||||
rolloutGroupParentId, limit);
|
|
||||||
|
|
||||||
if (rolloutGroupActions.getContent().isEmpty()) {
|
@Override
|
||||||
return 0L;
|
public void startScheduledActions(final List<Action> rolloutGroupActions) {
|
||||||
}
|
|
||||||
|
|
||||||
final List<Action> newTargetAssignments = handleTargetAssignments(rolloutGroupActions);
|
|
||||||
|
|
||||||
if (!newTargetAssignments.isEmpty()) {
|
|
||||||
onlineDsAssignmentStrategy.sendDeploymentEvents(distributionSetId, newTargetAssignments);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rolloutGroupActions.getTotalElements();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Action> handleTargetAssignments(final Page<Action> rolloutGroupActions) {
|
|
||||||
// Close actions already assigned and collect pending assignments
|
// Close actions already assigned and collect pending assignments
|
||||||
final List<JpaAction> pendingTargetAssignments = rolloutGroupActions.getContent().stream()
|
final List<JpaAction> pendingTargetAssignments = rolloutGroupActions.stream()
|
||||||
.map(JpaAction.class::cast).map(this::closeActionIfSetWasAlreadyAssigned).filter(Objects::nonNull)
|
.map(JpaAction.class::cast).map(this::closeActionIfSetWasAlreadyAssigned).filter(Objects::nonNull)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
if (pendingTargetAssignments.isEmpty()) {
|
if (pendingTargetAssignments.isEmpty()) {
|
||||||
return new ArrayList<>(pendingTargetAssignments);
|
return;
|
||||||
}
|
}
|
||||||
// check if old actions needs to be canceled first
|
// check if old actions needs to be canceled first
|
||||||
return startScheduledActionsAndHandleOpenCancellationFirst(pendingTargetAssignments);
|
final List<Action> newTargetAssignments = startScheduledActionsAndHandleOpenCancellationFirst(pendingTargetAssignments);
|
||||||
|
if (!newTargetAssignments.isEmpty()) {
|
||||||
|
onlineDsAssignmentStrategy.sendDeploymentEvents(newTargetAssignments.get(0).getDistributionSet().getId(), newTargetAssignments);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Page<Action> findActionsByRolloutAndRolloutGroupParent(final Long rolloutId,
|
private Page<Action> findActionsByRolloutAndRolloutGroupParent(final Long rolloutId,
|
||||||
|
|||||||
Reference in New Issue
Block a user