Fix dynamic rollouts when there are finished actions from previous rollouts (#2434)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -647,7 +647,7 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
||||
rollout.getRolloutGroups(), RolloutGroupStatus.READY, group);
|
||||
final Slice<Target> targets;
|
||||
if (!RolloutHelper.isRolloutRetried(rollout.getTargetFilterQuery())) {
|
||||
targets = targetManagement.findByTargetFilterQueryAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
||||
targets = targetManagement.findByTargetFilterQueryAndNotInRolloutAndCompatibleAndUpdatable(
|
||||
pageRequest, readyGroups, targetFilter, rollout.getDistributionSet().getType());
|
||||
} else {
|
||||
targets = targetManagement.findByFailedRolloutAndNotInRolloutGroups(
|
||||
@@ -771,7 +771,7 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
||||
final String targetFilter, final long limit) {
|
||||
return DeploymentHelper.runInNewTransaction(txManager, "createActionsForRolloutDynamicGroup", status -> {
|
||||
final PageRequest pageRequest = PageRequest.of(0, Math.toIntExact(limit));
|
||||
final Slice<Target> targets = targetManagement.findByNotInGEGroupAndNotInActiveActionGEWeightOrInRolloutAndTargetFilterQueryAndCompatibleAndUpdatable(
|
||||
final Slice<Target> targets = targetManagement.findByTargetFilterQueryAndNoOverridingActionsAndNotInRolloutAndCompatibleAndUpdatable(
|
||||
pageRequest,
|
||||
rollout.getId(), rollout.getWeight().orElse(1000), // Dynamic rollouts shall always have weight!
|
||||
rolloutGroupRepository.findByRolloutOrderByIdAsc(rollout).get(0).getId(),
|
||||
|
||||
@@ -12,7 +12,6 @@ package org.eclipse.hawkbit.repository.jpa.management;
|
||||
import static org.eclipse.hawkbit.repository.jpa.JpaManagementHelper.combineWithAnd;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -135,7 +134,6 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
@Override
|
||||
public long countByAssignedDistributionSet(final long distributionSetId) {
|
||||
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException((distributionSetId));
|
||||
|
||||
return targetRepository.count(TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId()));
|
||||
}
|
||||
|
||||
@@ -148,29 +146,29 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
@Override
|
||||
public long countByInstalledDistributionSet(final long distributionSetId) {
|
||||
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException((distributionSetId));
|
||||
|
||||
return targetRepository.count(TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsByInstalledOrAssignedDistributionSet(final long distributionSetId) {
|
||||
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException((distributionSetId));
|
||||
|
||||
return targetRepository
|
||||
.exists(TargetSpecifications.hasInstalledOrAssignedDistributionSet(validDistSet.getId()));
|
||||
return targetRepository.exists(TargetSpecifications.hasInstalledOrAssignedDistributionSet(validDistSet.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByRsql(final String targetFilterQuery) {
|
||||
return JpaManagementHelper.countBySpec(targetRepository, List.of(RSQLUtility
|
||||
.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database)));
|
||||
return JpaManagementHelper.countBySpec(
|
||||
targetRepository,
|
||||
List.of(RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByRsqlAndUpdatable(String targetFilterQuery) {
|
||||
final List<Specification<JpaTarget>> specList = List.of(RSQLUtility.buildRsqlSpecification(targetFilterQuery,
|
||||
TargetFields.class, virtualPropertyReplacer, database));
|
||||
return targetRepository.count(AccessController.Operation.UPDATE, combineWithAnd(specList));
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database));
|
||||
return targetRepository.count(
|
||||
AccessController.Operation.UPDATE,
|
||||
combineWithAnd(specList));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -197,7 +195,8 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
|
||||
@Override
|
||||
public long countByTargetFilterQuery(final long targetFilterQueryId) {
|
||||
final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository.findById(targetFilterQueryId)
|
||||
final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository
|
||||
.findById(targetFilterQueryId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId));
|
||||
return countByRsql(targetFilterQuery.getQuery());
|
||||
}
|
||||
@@ -221,8 +220,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public List<Target> create(final Collection<TargetCreate> targets) {
|
||||
final List<JpaTarget> targetList = targets.stream().map(JpaTargetCreate.class::cast).map(JpaTargetCreate::build)
|
||||
.toList();
|
||||
final List<JpaTarget> targetList = targets.stream().map(JpaTargetCreate.class::cast).map(JpaTargetCreate::build).toList();
|
||||
return Collections.unmodifiableList(targetRepository.saveAll(AccessController.Operation.CREATE, targetList));
|
||||
}
|
||||
|
||||
@@ -236,7 +234,6 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
throw new EntityNotFoundException(Target.class, ids,
|
||||
targets.stream().map(Target::getId).filter(id -> !ids.contains(id)).toList());
|
||||
}
|
||||
|
||||
targetRepository.deleteAll(targets);
|
||||
}
|
||||
|
||||
@@ -255,10 +252,10 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
final Long distSetTypeId = jpaDistributionSet.getType().getId();
|
||||
|
||||
return targetRepository
|
||||
.findAllWithoutCount(AccessController.Operation.UPDATE,
|
||||
.findAllWithoutCount(
|
||||
AccessController.Operation.UPDATE,
|
||||
combineWithAnd(List.of(
|
||||
RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class,
|
||||
virtualPropertyReplacer, database),
|
||||
RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database),
|
||||
TargetSpecifications.hasNotDistributionSetInActions(distributionSetId),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId))),
|
||||
pageRequest)
|
||||
@@ -266,8 +263,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByRsqlAndNonDSAndCompatibleAndUpdatable(final long distributionSetId,
|
||||
final String targetFilterQuery) {
|
||||
public long countByRsqlAndNonDSAndCompatibleAndUpdatable(final long distributionSetId, final String targetFilterQuery) {
|
||||
final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
|
||||
final Long distSetTypeId = jpaDistributionSet.getType().getId();
|
||||
|
||||
@@ -281,14 +277,12 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice<Target> findByTargetFilterQueryAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
||||
final Pageable pageRequest, final Collection<Long> groups, final String targetFilterQuery,
|
||||
final DistributionSetType dsType) {
|
||||
public Slice<Target> findByTargetFilterQueryAndNotInRolloutAndCompatibleAndUpdatable(
|
||||
final Pageable pageRequest, final Collection<Long> groups, final String targetFilterQuery, final DistributionSetType dsType) {
|
||||
return targetRepository
|
||||
.findAllWithoutCount(AccessController.Operation.UPDATE,
|
||||
combineWithAnd(List.of(
|
||||
RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class,
|
||||
virtualPropertyReplacer, database),
|
||||
RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database),
|
||||
TargetSpecifications.isNotInRolloutGroups(groups),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()))),
|
||||
pageRequest)
|
||||
@@ -296,16 +290,14 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice<Target> findByNotInGEGroupAndNotInActiveActionGEWeightOrInRolloutAndTargetFilterQueryAndCompatibleAndUpdatable(
|
||||
public Slice<Target> findByTargetFilterQueryAndNoOverridingActionsAndNotInRolloutAndCompatibleAndUpdatable(
|
||||
final Pageable pageRequest, final long rolloutId, final int weight, final long firstGroupId, final String targetFilterQuery,
|
||||
final DistributionSetType distributionSetType) {
|
||||
return targetRepository
|
||||
.findAllWithoutCount(AccessController.Operation.UPDATE,
|
||||
combineWithAnd(List.of(
|
||||
RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class,
|
||||
virtualPropertyReplacer, database),
|
||||
TargetSpecifications.isNotInGERolloutGroup(firstGroupId),
|
||||
TargetSpecifications.hasNoActiveActionWithGEWeightOrInRollout(weight, rolloutId),
|
||||
RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database),
|
||||
TargetSpecifications.hasNoOverridingActionsAndNotInRollout(weight, rolloutId),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetType.getId()))),
|
||||
pageRequest)
|
||||
.map(Target.class::cast);
|
||||
@@ -319,7 +311,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
@Override
|
||||
public Slice<Target> findByFailedRolloutAndNotInRolloutGroups(Pageable pageRequest, Collection<Long> groups,
|
||||
String rolloutId) {
|
||||
final List<Specification<JpaTarget>> specList = Arrays.asList(
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
TargetSpecifications.failedActionsForRollout(rolloutId),
|
||||
TargetSpecifications.isNotInRolloutGroups(groups));
|
||||
|
||||
@@ -327,22 +319,20 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(final String targetFilterQuery, final Collection<Long> groups,
|
||||
final DistributionSetType dsType) {
|
||||
public long countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
||||
final String targetFilterQuery, final Collection<Long> groups, final DistributionSetType dsType) {
|
||||
return targetRepository.count(AccessController.Operation.UPDATE,
|
||||
combineWithAnd(List.of(
|
||||
RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class,
|
||||
virtualPropertyReplacer, database),
|
||||
RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database),
|
||||
TargetSpecifications.isNotInRolloutGroups(groups),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByFailedRolloutAndNotInRolloutGroups(String rolloutId, Collection<Long> groups) {
|
||||
final List<Specification<JpaTarget>> specList = Arrays.asList(
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
TargetSpecifications.failedActionsForRollout(rolloutId),
|
||||
TargetSpecifications.isNotInRolloutGroups(groups));
|
||||
|
||||
return JpaManagementHelper.countBySpec(targetRepository, specList);
|
||||
}
|
||||
|
||||
@@ -352,22 +342,21 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
throw new EntityNotFoundException(RolloutGroup.class, group);
|
||||
}
|
||||
|
||||
return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageRequest,
|
||||
List.of(TargetSpecifications.hasNoActionInRolloutGroup(group)));
|
||||
return JpaManagementHelper.findAllWithoutCountBySpec(
|
||||
targetRepository, pageRequest, List.of(TargetSpecifications.hasNoActionInRolloutGroup(group)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Target> findByAssignedDistributionSet(final Pageable pageReq, final long distributionSetId) {
|
||||
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(targetRepository,
|
||||
List.of(TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId())), pageReq
|
||||
);
|
||||
return JpaManagementHelper.findAllWithCountBySpec(
|
||||
targetRepository,
|
||||
List.of(TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId())), pageReq);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Target> findByAssignedDistributionSetAndRsql(final Pageable pageReq, final long distributionSetId,
|
||||
final String rsqlParam) {
|
||||
public Page<Target> findByAssignedDistributionSetAndRsql(final Pageable pageReq, final long distributionSetId, final String rsqlParam) {
|
||||
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
|
||||
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
@@ -379,8 +368,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
|
||||
@Override
|
||||
public List<Target> getByControllerID(final Collection<String> controllerIDs) {
|
||||
return Collections.unmodifiableList(
|
||||
targetRepository.findAll(TargetSpecifications.byControllerIdWithAssignedDsInJoin(controllerIDs)));
|
||||
return Collections.unmodifiableList(targetRepository.findAll(TargetSpecifications.byControllerIdWithAssignedDsInJoin(controllerIDs)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -403,14 +391,12 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
public Page<Target> findByInstalledDistributionSet(final Pageable pageReq, final long distributionSetId) {
|
||||
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(targetRepository,
|
||||
List.of(TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId())), pageReq
|
||||
);
|
||||
return JpaManagementHelper.findAllWithCountBySpec(
|
||||
targetRepository, List.of(TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId())), pageReq);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Target> findByInstalledDistributionSetAndRsql(final Pageable pageable, final long distributionSetId,
|
||||
final String rsqlParam) {
|
||||
public Page<Target> findByInstalledDistributionSetAndRsql(final Pageable pageable, final long distributionSetId, final String rsqlParam) {
|
||||
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
|
||||
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
@@ -422,9 +408,8 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
|
||||
@Override
|
||||
public Page<Target> findByUpdateStatus(final Pageable pageable, final TargetUpdateStatus status) {
|
||||
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, List.of(TargetSpecifications.hasTargetUpdateStatus(status)),
|
||||
pageable
|
||||
);
|
||||
return JpaManagementHelper.findAllWithCountBySpec(
|
||||
targetRepository, List.of(TargetSpecifications.hasTargetUpdateStatus(status)), pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -434,8 +419,9 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
|
||||
@Override
|
||||
public Slice<Target> findByRsql(final Pageable pageable, final String targetFilterQuery) {
|
||||
return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable, List.of(RSQLUtility
|
||||
.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database)));
|
||||
return JpaManagementHelper.findAllWithoutCountBySpec(
|
||||
targetRepository, pageable,
|
||||
List.of(RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -443,24 +429,23 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository.findById(targetFilterQueryId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId));
|
||||
|
||||
return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable,
|
||||
List.of(RSQLUtility.buildRsqlSpecification(targetFilterQuery.getQuery(), TargetFields.class,
|
||||
virtualPropertyReplacer, database)));
|
||||
return JpaManagementHelper.findAllWithoutCountBySpec(
|
||||
targetRepository, pageable,
|
||||
List.of(RSQLUtility.buildRsqlSpecification(
|
||||
targetFilterQuery.getQuery(), TargetFields.class, virtualPropertyReplacer, database)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Target> findByTag(final Pageable pageable, final long tagId) {
|
||||
throwEntityNotFoundExceptionIfTagDoesNotExist(tagId);
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, List.of(TargetSpecifications.hasTag(tagId)), pageable
|
||||
);
|
||||
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, List.of(TargetSpecifications.hasTag(tagId)), pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Target> findByRsqlAndTag(final Pageable pageable, final String rsqlParam, final long tagId) {
|
||||
throwEntityNotFoundExceptionIfTagDoesNotExist(tagId);
|
||||
|
||||
final List<Specification<JpaTarget>> specList = Arrays.asList(
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database),
|
||||
TargetSpecifications.hasTag(tagId));
|
||||
|
||||
@@ -472,20 +457,19 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public TargetTypeAssignmentResult assignType(final Collection<String> controllerIds, final Long typeId) {
|
||||
final JpaTargetType type = targetTypeRepository.findById(typeId)
|
||||
final JpaTargetType type = targetTypeRepository
|
||||
.findById(typeId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(TargetType.class, typeId));
|
||||
|
||||
final List<JpaTarget> targetsWithSameType = findTargetsByInSpecification(controllerIds,
|
||||
TargetSpecifications.hasTargetType(typeId));
|
||||
|
||||
final List<JpaTarget> targetsWithoutSameType = findTargetsByInSpecification(controllerIds,
|
||||
TargetSpecifications.hasTargetTypeNot(typeId));
|
||||
final List<JpaTarget> targetsWithSameType = findTargetsByInSpecification(controllerIds, TargetSpecifications.hasTargetType(typeId));
|
||||
final List<JpaTarget> targetsWithoutSameType =
|
||||
findTargetsByInSpecification(controllerIds, TargetSpecifications.hasTargetTypeNot(typeId));
|
||||
|
||||
// set new target type to all targets without that type
|
||||
targetsWithoutSameType.forEach(target -> target.setTargetType(type));
|
||||
|
||||
final TargetTypeAssignmentResult result = new TargetTypeAssignmentResult(targetsWithSameType.size(),
|
||||
targetRepository.saveAll(targetsWithoutSameType), Collections.emptyList(), type);
|
||||
final TargetTypeAssignmentResult result = new TargetTypeAssignmentResult(
|
||||
targetsWithSameType.size(), targetRepository.saveAll(targetsWithoutSameType), Collections.emptyList(), type);
|
||||
|
||||
// no reason to persist the type
|
||||
entityManager.detach(type);
|
||||
@@ -500,8 +484,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
final List<JpaTarget> allTargets = findTargetsByInSpecification(controllerIds, null);
|
||||
|
||||
if (allTargets.size() < controllerIds.size()) {
|
||||
throw new EntityNotFoundException(Target.class, controllerIds,
|
||||
allTargets.stream().map(Target::getControllerId).toList());
|
||||
throw new EntityNotFoundException(Target.class, controllerIds, allTargets.stream().map(Target::getControllerId).toList());
|
||||
}
|
||||
|
||||
// set new target type to null for all targets
|
||||
@@ -514,8 +497,8 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public List<Target> assignTag(final Collection<String> controllerIds, final long targetTagId,
|
||||
final Consumer<Collection<String>> notFoundHandler) {
|
||||
public List<Target> assignTag(
|
||||
final Collection<String> controllerIds, final long targetTagId, final Consumer<Collection<String>> notFoundHandler) {
|
||||
return assignTag0(controllerIds, targetTagId, notFoundHandler);
|
||||
}
|
||||
|
||||
@@ -527,8 +510,8 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
return assignTag0(controllerIds, targetTagId, null);
|
||||
}
|
||||
|
||||
private List<Target> assignTag0(final Collection<String> controllerIds, final long targetTagId,
|
||||
final Consumer<Collection<String>> notFoundHandler) {
|
||||
private List<Target> assignTag0(
|
||||
final Collection<String> controllerIds, final long targetTagId, final Consumer<Collection<String>> notFoundHandler) {
|
||||
return updateTag(controllerIds, targetTagId, notFoundHandler, (tag, target) -> {
|
||||
if (target.getTags().contains(tag)) {
|
||||
return target;
|
||||
@@ -543,8 +526,8 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public List<Target> unassignTag(final Collection<String> controllerIds, final long targetTagId,
|
||||
final Consumer<Collection<String>> notFoundHandler) {
|
||||
public List<Target> unassignTag(
|
||||
final Collection<String> controllerIds, final long targetTagId, final Consumer<Collection<String>> notFoundHandler) {
|
||||
return unassignTag0(controllerIds, targetTagId, notFoundHandler);
|
||||
}
|
||||
|
||||
@@ -556,8 +539,8 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
return unassignTag0(controllerIds, targetTagId, null);
|
||||
}
|
||||
|
||||
private List<Target> unassignTag0(final Collection<String> controllerIds, final long targetTagId,
|
||||
final Consumer<Collection<String>> notFoundHandler) {
|
||||
private List<Target> unassignTag0(
|
||||
final Collection<String> controllerIds, final long targetTagId, final Consumer<Collection<String>> notFoundHandler) {
|
||||
return updateTag(controllerIds, targetTagId, notFoundHandler, (tag, target) -> {
|
||||
if (target.getTags().contains(tag)) {
|
||||
target.removeTag(tag);
|
||||
@@ -630,13 +613,13 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(final String controllerId,
|
||||
final long distributionSetId, final String targetFilterQuery) {
|
||||
public boolean isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(
|
||||
final String controllerId, final long distributionSetId, final String targetFilterQuery) {
|
||||
RSQLUtility.validateRsqlFor(targetFilterQuery, TargetFields.class, JpaTarget.class, virtualPropertyReplacer, entityManager);
|
||||
final DistributionSet ds = distributionSetManagement.get(distributionSetId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, distributionSetId));
|
||||
final Long distSetTypeId = ds.getType().getId();
|
||||
final List<Specification<JpaTarget>> specList = Arrays.asList(
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database),
|
||||
TargetSpecifications.hasNotDistributionSetInActions(distributionSetId),
|
||||
TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId),
|
||||
@@ -830,8 +813,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
return specList;
|
||||
}
|
||||
|
||||
private List<JpaTarget> findTargetsByInSpecification(final Collection<String> controllerIds,
|
||||
final Specification<JpaTarget> specification) {
|
||||
private List<JpaTarget> findTargetsByInSpecification(final Collection<String> controllerIds, final Specification<JpaTarget> specification) {
|
||||
return ListUtils.partition(new ArrayList<>(controllerIds), Constants.MAX_ENTRIES_IN_STATEMENT).stream()
|
||||
.map(ids -> targetRepository.findAll(TargetSpecifications.hasControllerIdIn(ids).and(specification)))
|
||||
.flatMap(List::stream).toList();
|
||||
@@ -873,4 +855,4 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
throw new EntityNotFoundException(TargetTag.class, tagId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,15 +119,13 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link JpaTarget}s including
|
||||
* {@link JpaTarget#getAssignedDistributionSet()}.
|
||||
* {@link Specification} for retrieving {@link JpaTarget}s including {@link JpaTarget#getAssignedDistributionSet()}.
|
||||
*
|
||||
* @param controllerIDs to search for
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> byControllerIdWithAssignedDsInJoin(final Collection<String> controllerIDs) {
|
||||
return (targetRoot, query, cb) -> {
|
||||
|
||||
final Predicate predicate = targetRoot.get(JpaTarget_.controllerId).in(controllerIDs);
|
||||
targetRoot.fetch(JpaTarget_.assignedDistributionSet, JoinType.LEFT);
|
||||
return predicate;
|
||||
@@ -135,8 +133,7 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by "equal to any
|
||||
* given {@link TargetUpdateStatus}".
|
||||
* {@link Specification} for retrieving {@link Target}s by "equal to any given {@link TargetUpdateStatus}".
|
||||
*
|
||||
* @param updateStatus to be filtered on
|
||||
* @return the {@link Target} {@link Specification}
|
||||
@@ -146,8 +143,7 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by "equal to given
|
||||
* {@link TargetUpdateStatus}".
|
||||
* {@link Specification} for retrieving {@link Target}s by "equal to given {@link TargetUpdateStatus}".
|
||||
*
|
||||
* @param updateStatus to be filtered on
|
||||
* @return the {@link Target} {@link Specification}
|
||||
@@ -157,8 +153,7 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by "not equal to
|
||||
* given {@link TargetUpdateStatus}".
|
||||
* {@link Specification} for retrieving {@link Target}s by "not equal to given {@link TargetUpdateStatus}".
|
||||
*
|
||||
* @param updateStatus to be filtered on
|
||||
* @return the {@link Target} {@link Specification}
|
||||
@@ -168,17 +163,13 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s that are overdue. A
|
||||
* target is overdue if it did not respond during the configured
|
||||
* {@link Specification} for retrieving {@link Target}s that are overdue. A target is overdue if it did not respond during the configured
|
||||
* intervals:<br>
|
||||
* <em>poll_itvl + overdue_itvl</em>
|
||||
*
|
||||
* @param overdueTimestamp the calculated timestamp to compare with the last respond of a
|
||||
* target (lastTargetQuery).<br>
|
||||
* The <code>overdueTimestamp</code> has to be calculated with
|
||||
* the following expression:<br>
|
||||
* <em>overdueTimestamp = nowTimestamp - poll_itvl -
|
||||
* overdue_itvl</em>
|
||||
* @param overdueTimestamp the calculated timestamp to compare with the last response of a target (lastTargetQuery).<br>
|
||||
* The <code>overdueTimestamp</code> has to be calculated with the following expression:<br>
|
||||
* <em>overdueTimestamp = nowTimestamp - poll_itvl - overdue_itvl</em>
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> isOverdue(final long overdueTimestamp) {
|
||||
@@ -187,8 +178,7 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by "like
|
||||
* controllerId or like name".
|
||||
* {@link Specification} for retrieving {@link Target}s by "like controllerId or like name".
|
||||
*
|
||||
* @param searchText to be filtered on
|
||||
* @return the {@link Target} {@link Specification}
|
||||
@@ -202,8 +192,7 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by "like
|
||||
* controllerId".
|
||||
* {@link Specification} for retrieving {@link Target}s by "like controllerId".
|
||||
*
|
||||
* @param distributionId to be filtered on
|
||||
* @return the {@link Target} {@link Specification}
|
||||
@@ -228,8 +217,7 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s based on a
|
||||
* {@link TargetTag} name.
|
||||
* {@link Specification} for retrieving {@link Target}s based on a {@link TargetTag} name.
|
||||
*
|
||||
* @param tagName to search for
|
||||
* @return the {@link Target} {@link Specification}
|
||||
@@ -242,8 +230,7 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by "has no tag
|
||||
* names"or "has at least on of the given tag names".
|
||||
* {@link Specification} for retrieving {@link Target}s by "has no tag names"or "has at least on of the given tag names".
|
||||
*
|
||||
* @param tagNames to be filtered on
|
||||
* @param selectTargetWithNoTag flag to get targets with no tag assigned
|
||||
@@ -258,8 +245,7 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by assigned
|
||||
* distribution set.
|
||||
* {@link Specification} for retrieving {@link Target}s by assigned distribution set.
|
||||
*
|
||||
* @param distributionSetId the ID of the distribution set which must be assigned
|
||||
* @return the {@link Target} {@link Specification}
|
||||
@@ -270,8 +256,7 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s that don't have the
|
||||
* given distribution set in their action history
|
||||
* {@link Specification} for retrieving {@link Target}s that don't have the given distribution set in their action history
|
||||
*
|
||||
* @param distributionSetId the ID of the distribution set which must not be assigned
|
||||
* @return the {@link Target} {@link Specification}
|
||||
@@ -285,10 +270,9 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s that are compatible
|
||||
* with given {@link DistributionSetType}. Compatibility is evaluated by
|
||||
* checking the {@link TargetType} of a target. Targets that don't have a
|
||||
* {@link TargetType} are compatible with all {@link DistributionSetType}
|
||||
* {@link Specification} for retrieving {@link Target}s that are compatible with given {@link DistributionSetType}. Compatibility is
|
||||
* evaluated by checking the {@link TargetType} of a target. Targets that don't have a {@link TargetType} are compatible with all
|
||||
* {@link DistributionSetType}
|
||||
*
|
||||
* @param distributionSetTypeId the ID of the distribution set type which must be compatible
|
||||
* @return the {@link Target} {@link Specification}
|
||||
@@ -302,10 +286,8 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s that are NOT
|
||||
* compatible with given {@link DistributionSetType}. Compatibility is
|
||||
* evaluated by checking the {@link TargetType} of a target. Targets that
|
||||
* don't have a {@link TargetType} are compatible with all
|
||||
* {@link Specification} for retrieving {@link Target}s that are NOT compatible with given {@link DistributionSetType}. Compatibility is
|
||||
* evaluated by checking the {@link TargetType} of a target. Targets that don't have a {@link TargetType} are compatible with all
|
||||
* {@link DistributionSetType}
|
||||
*
|
||||
* @param distributionSetTypeId the ID of the distribution set type which must be incompatible
|
||||
@@ -329,23 +311,20 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s that are in a given
|
||||
* {@link RolloutGroup}
|
||||
* {@link Specification} for retrieving {@link Target}s that are in a given {@link RolloutGroup}
|
||||
*
|
||||
* @param group the {@link RolloutGroup}
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> isInRolloutGroup(final Long group) {
|
||||
return (targetRoot, query, cb) -> {
|
||||
final ListJoin<JpaTarget, RolloutTargetGroup> targetGroupJoin = targetRoot
|
||||
.join(JpaTarget_.rolloutTargetGroup);
|
||||
final ListJoin<JpaTarget, RolloutTargetGroup> targetGroupJoin = targetRoot.join(JpaTarget_.rolloutTargetGroup);
|
||||
return cb.equal(targetGroupJoin.get(RolloutTargetGroup_.rolloutGroup).get(AbstractJpaBaseEntity_.id), group);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s that are in an
|
||||
* action for a given {@link RolloutGroup}
|
||||
* {@link Specification} for retrieving {@link Target}s that are in an action for a given {@link RolloutGroup}
|
||||
*
|
||||
* @param group the {@link RolloutGroup}
|
||||
* @return the {@link Target} {@link Specification}
|
||||
@@ -358,41 +337,21 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s that are not in the
|
||||
* given {@link RolloutGroup}s
|
||||
* {@link Specification} for retrieving {@link Target}s that are not in the given {@link RolloutGroup}s
|
||||
*
|
||||
* @param groups the {@link RolloutGroup}s
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> isNotInRolloutGroups(final Collection<Long> groups) {
|
||||
return (targetRoot, query, cb) -> {
|
||||
final ListJoin<JpaTarget, RolloutTargetGroup> rolloutTargetJoin = targetRoot
|
||||
.join(JpaTarget_.rolloutTargetGroup, JoinType.LEFT);
|
||||
rolloutTargetJoin.on(rolloutTargetJoin.get(RolloutTargetGroup_.rolloutGroup)
|
||||
.get(AbstractJpaBaseEntity_.id).in(groups));
|
||||
final ListJoin<JpaTarget, RolloutTargetGroup> rolloutTargetJoin = targetRoot.join(JpaTarget_.rolloutTargetGroup, JoinType.LEFT);
|
||||
rolloutTargetJoin.on(rolloutTargetJoin.get(RolloutTargetGroup_.rolloutGroup).get(AbstractJpaBaseEntity_.id).in(groups));
|
||||
return cb.isNull(rolloutTargetJoin.get(RolloutTargetGroup_.target));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s that are not in
|
||||
* any {@link RolloutGroup}s
|
||||
*
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> isNotInGERolloutGroup(final long groupId) {
|
||||
return (targetRoot, query, cb) -> {
|
||||
final ListJoin<JpaTarget, RolloutTargetGroup> rolloutTargetJoin = targetRoot
|
||||
.join(JpaTarget_.rolloutTargetGroup, JoinType.LEFT);
|
||||
rolloutTargetJoin.on(cb.ge(rolloutTargetJoin.get(RolloutTargetGroup_.rolloutGroup)
|
||||
.get(AbstractJpaBaseEntity_.id), groupId));
|
||||
return cb.isNull(rolloutTargetJoin.get(RolloutTargetGroup_.target));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s that have no Action
|
||||
* of the {@link RolloutGroup}.
|
||||
* {@link Specification} for retrieving {@link Target}s that have no Action of the {@link RolloutGroup}.
|
||||
*
|
||||
* @param group the {@link RolloutGroup}
|
||||
* @return the {@link Target} {@link Specification}
|
||||
@@ -412,8 +371,7 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by assigned
|
||||
* distribution set.
|
||||
* {@link Specification} for retrieving {@link Target}s by assigned distribution set.
|
||||
*
|
||||
* @param distributionSetId the ID of the distribution set which must be assigned
|
||||
* @return the {@link Target} {@link Specification}
|
||||
@@ -448,8 +406,7 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by target type id is
|
||||
* equal to null
|
||||
* {@link Specification} for retrieving {@link Target}s by target type id is equal to null
|
||||
*
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
@@ -458,8 +415,7 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s that don't have
|
||||
* target type assigned
|
||||
* {@link Specification} for retrieving {@link Target}s that don't have target type assigned
|
||||
*
|
||||
* @param typeId the id of the target type
|
||||
* @return the {@link Target} {@link Specification}
|
||||
@@ -471,9 +427,7 @@ public final class TargetSpecifications {
|
||||
|
||||
public static Specification<JpaTarget> failedActionsForRollout(final String rolloutId) {
|
||||
return (targetRoot, query, cb) -> {
|
||||
Join<JpaTarget, Action> targetActions =
|
||||
targetRoot.join("actions");
|
||||
|
||||
final Join<JpaTarget, Action> targetActions = targetRoot.join("actions");
|
||||
return cb.and(
|
||||
cb.equal(targetActions.get("rollout").get("id"), rolloutId),
|
||||
cb.equal(targetActions.get("status"), Action.Status.ERROR));
|
||||
@@ -481,34 +435,31 @@ public final class TargetSpecifications {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s that have no active (non-finished) action
|
||||
* with great or equal weight (GEWeight.
|
||||
* {@link Specification} for retrieving {@link Target}s that have:
|
||||
* <ul>
|
||||
* <li>no active (non-finished) actions with greater weight in the older rollouts</li>
|
||||
* <li>or have actions in the current rollout</li>
|
||||
* <li>or have actions with great or equal weight in the newer rollouts</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param weight the referent weight
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> hasNoActiveActionWithGEWeightOrInRollout(final int weight, final long rolloutId) {
|
||||
public static Specification<JpaTarget> hasNoOverridingActionsAndNotInRollout(final int weight, final long rolloutId) {
|
||||
return (targetRoot, query, cb) -> {
|
||||
final ListJoin<JpaTarget, JpaAction> actionsJoin = targetRoot.join(JpaTarget_.actions, JoinType.LEFT);
|
||||
actionsJoin.on(
|
||||
cb.or(
|
||||
cb.gt(actionsJoin.get(JpaAction_.weight), weight),
|
||||
cb.and(
|
||||
cb.equal(actionsJoin.get(JpaAction_.weight), weight),
|
||||
cb.ge(actionsJoin.get(JpaAction_.ROLLOUT).get(AbstractJpaBaseEntity_.ID), rolloutId))));
|
||||
// another, but probably heavier variant
|
||||
// actionsJoin.on(
|
||||
// cb.or(
|
||||
// // in rollout
|
||||
// cb.equal(actionsJoin.get(JpaAction_.ROLLOUT).get(AbstractJpaBaseEntity_.ID), rolloutId),
|
||||
// // or, in newer rollout with greater or equal weight
|
||||
// cb.and(
|
||||
// cb.gt(actionsJoin.get(JpaAction_.ROLLOUT).get(AbstractJpaBaseEntity_.ID), rolloutId),
|
||||
// cb.ge(actionsJoin.get(JpaAction_.weight), weight)),
|
||||
// // or, in older with greater status
|
||||
// cb.and(
|
||||
// cb.lt(actionsJoin.get(JpaAction_.ROLLOUT).get(AbstractJpaBaseEntity_.ID), rolloutId),
|
||||
// cb.gt(actionsJoin.get(JpaAction_.weight), weight))));
|
||||
cb.and(
|
||||
cb.lt(actionsJoin.get(JpaAction_.rollout).get(AbstractJpaBaseEntity_.id), rolloutId),
|
||||
cb.gt(actionsJoin.get(JpaAction_.weight), weight)),
|
||||
cb.or(
|
||||
cb.equal(actionsJoin.get(JpaAction_.active), true),
|
||||
cb.equal(actionsJoin.get(JpaAction_.status), Action.Status.SCHEDULED))),
|
||||
cb.and(
|
||||
cb.ge(actionsJoin.get(JpaAction_.rollout).get(AbstractJpaBaseEntity_.id), rolloutId),
|
||||
cb.ge(actionsJoin.get(JpaAction_.weight), weight))));
|
||||
return cb.isNull(actionsJoin.get(AbstractJpaBaseEntity_.id));
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user