Optimise rollout create - single save + groups saveAll (#2126)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2024-12-06 16:57:46 +02:00
committed by GitHub
parent 9d6720266f
commit 9de1bd2ae6
8 changed files with 123 additions and 124 deletions

View File

@@ -105,7 +105,8 @@ public interface RolloutManagement {
* exceeded. * exceeded.
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_CREATE) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_CREATE)
Rollout create(@NotNull @Valid RolloutCreate create, int amountGroup, boolean confirmationRequired, Rollout create(
@NotNull @Valid RolloutCreate create, int amountGroup, boolean confirmationRequired,
@NotNull RolloutGroupConditions conditions, DynamicRolloutGroupTemplate dynamicRolloutGroupTemplate); @NotNull RolloutGroupConditions conditions, DynamicRolloutGroupTemplate dynamicRolloutGroupTemplate);
/** /**

View File

@@ -850,7 +850,7 @@ public class JpaRolloutExecutor implements RolloutExecutor {
if (targets.getNumberOfElements() > 0) { if (targets.getNumberOfElements() > 0) {
final DistributionSet distributionSet = rollout.getDistributionSet(); final DistributionSet distributionSet = rollout.getDistributionSet();
entityManager.detach(distributionSet); // if lazy loaded with different session entityManager.detach(distributionSet); // LAZY_LOAD - if lazy loaded with different session
final ActionType actionType = rollout.getActionType(); final ActionType actionType = rollout.getActionType();
final long forceTime = rollout.getForcedTime(); final long forceTime = rollout.getForcedTime();
createActions(targets.getContent(), distributionSet, actionType, forceTime, rollout, group); createActions(targets.getContent(), distributionSet, actionType, forceTime, rollout, group);

View File

@@ -132,26 +132,26 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
} }
@Override @Override
public Page<TargetWithActionStatus> findAllTargetsOfRolloutGroupWithActionStatus(final Pageable pageRequest, public Page<TargetWithActionStatus> findAllTargetsOfRolloutGroupWithActionStatus(final Pageable pageRequest, final long rolloutGroupId) {
final long rolloutGroupId) {
throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId); throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId);
final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final CriteriaQuery<Object[]> query = cb.createQuery(Object[].class); final CriteriaQuery<Object[]> query = cb.createQuery(Object[].class);
final Root<RolloutTargetGroup> targetRoot = query.distinct(true).from(RolloutTargetGroup.class); final Root<RolloutTargetGroup> targetRoot = query.distinct(true).from(RolloutTargetGroup.class);
final Join<RolloutTargetGroup, JpaTarget> targetJoin = targetRoot.join(RolloutTargetGroup_.target); final Join<RolloutTargetGroup, JpaTarget> targetJoin = targetRoot.join(RolloutTargetGroup_.target);
final ListJoin<RolloutTargetGroup, JpaAction> actionJoin = targetRoot.join(RolloutTargetGroup_.actions, final ListJoin<RolloutTargetGroup, JpaAction> actionJoin = targetRoot.join(RolloutTargetGroup_.actions, JoinType.LEFT);
JoinType.LEFT);
final CriteriaQuery<Object[]> multiselect = query final CriteriaQuery<Object[]> multiselect = query
.multiselect(targetJoin, actionJoin.get(JpaAction_.status), .multiselect(targetJoin, actionJoin.get(JpaAction_.status), actionJoin.get(JpaAction_.lastActionStatusCode))
actionJoin.get(JpaAction_.lastActionStatusCode))
.where(getRolloutGroupTargetWithRolloutGroupJoinCondition(rolloutGroupId, cb, targetRoot)) .where(getRolloutGroupTargetWithRolloutGroupJoinCondition(rolloutGroupId, cb, targetRoot))
.orderBy(getOrderBy(pageRequest, cb, targetJoin, actionJoin)); .orderBy(getOrderBy(pageRequest, cb, targetJoin, actionJoin));
final List<TargetWithActionStatus> targetWithActionStatus = entityManager.createQuery(multiselect) final List<TargetWithActionStatus> targetWithActionStatus = entityManager.createQuery(multiselect)
.setFirstResult((int) pageRequest.getOffset()).setMaxResults(pageRequest.getPageSize()).getResultList() .setFirstResult((int) pageRequest.getOffset())
.stream().map(this::getTargetWithActionStatusFromQuery).collect(Collectors.toList()); .setMaxResults(pageRequest.getPageSize())
.getResultList()
.stream()
.map(this::getTargetWithActionStatusFromQuery)
.toList();
return new PageImpl<>(targetWithActionStatus, pageRequest, 0); return new PageImpl<>(targetWithActionStatus, pageRequest, 0);
} }

View File

@@ -183,7 +183,8 @@ public class JpaRolloutManagement implements RolloutManagement {
@Transactional @Transactional
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
backoff = @Backoff(delay = Constants.TX_RT_DELAY)) backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public Rollout create(final RolloutCreate rollout, final int amountGroup, final boolean confirmationRequired, public Rollout create(
final RolloutCreate rollout, final int amountGroup, final boolean confirmationRequired,
final RolloutGroupConditions conditions, final DynamicRolloutGroupTemplate dynamicRolloutGroupTemplate) { final RolloutGroupConditions conditions, final DynamicRolloutGroupTemplate dynamicRolloutGroupTemplate) {
if (amountGroup < 0) { if (amountGroup < 0) {
throw new ValidationException("The amount of groups cannot be lower than or equal to zero for static rollouts"); throw new ValidationException("The amount of groups cannot be lower than or equal to zero for static rollouts");
@@ -201,8 +202,8 @@ public class JpaRolloutManagement implements RolloutManagement {
throw new ValidationException("Dynamic group template is only allowed for dynamic rollouts"); throw new ValidationException("Dynamic group template is only allowed for dynamic rollouts");
} }
final JpaRollout savedRollout = createRollout(rolloutRequest, amountGroup == 0); return createRolloutGroups(
return createRolloutGroups(amountGroup, conditions, savedRollout, confirmationRequired, dynamicRolloutGroupTemplate); amountGroup, conditions, createRollout(rolloutRequest, amountGroup == 0), confirmationRequired, dynamicRolloutGroupTemplate);
} }
@Override @Override
@@ -224,9 +225,7 @@ public class JpaRolloutManagement implements RolloutManagement {
throw new ValidationException("The amount of groups cannot be 0"); throw new ValidationException("The amount of groups cannot be 0");
} }
RolloutHelper.verifyRolloutGroupAmount(groups.size(), quotaManagement); RolloutHelper.verifyRolloutGroupAmount(groups.size(), quotaManagement);
final JpaRollout rolloutRequest = (JpaRollout) rollout.build(); return createRolloutGroups(groups, conditions, createRollout((JpaRollout)rollout.build(), false));
final JpaRollout savedRollout = createRollout(rolloutRequest, false);
return createRolloutGroups(groups, conditions, savedRollout);
} }
@Override @Override
@@ -540,8 +539,10 @@ public class JpaRolloutManagement implements RolloutManagement {
private JpaRollout createRollout(final JpaRollout rollout, final boolean pureDynamic) { private JpaRollout createRollout(final JpaRollout rollout, final boolean pureDynamic) {
WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(rollout); WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(rollout);
final JpaDistributionSet distributionSet = (JpaDistributionSet) rollout.getDistributionSet();
rollout.setCreatedAt(System.currentTimeMillis());
final JpaDistributionSet distributionSet = rollout.getDistributionSet();
if (pureDynamic) { if (pureDynamic) {
rollout.setTotalTargets(0); rollout.setTotalTargets(0);
} else { } else {
@@ -571,15 +572,17 @@ public class JpaRolloutManagement implements RolloutManagement {
rollout.setWeight(repositoryProperties.getActionWeightIfAbsent()); rollout.setWeight(repositoryProperties.getActionWeightIfAbsent());
} }
contextAware.getCurrentContext().ifPresent(rollout::setAccessControlContext); contextAware.getCurrentContext().ifPresent(rollout::setAccessControlContext);
return rolloutRepository.save(rollout); return rollout;
} }
private Rollout createRolloutGroups(final int amountOfGroups, final RolloutGroupConditions conditions, private Rollout createRolloutGroups(
final int amountOfGroups, final RolloutGroupConditions conditions,
final JpaRollout rollout, final boolean isConfirmationRequired, final DynamicRolloutGroupTemplate dynamicRolloutGroupTemplate) { final JpaRollout rollout, final boolean isConfirmationRequired, final DynamicRolloutGroupTemplate dynamicRolloutGroupTemplate) {
RolloutHelper.verifyRolloutInStatus(rollout, RolloutStatus.CREATING); RolloutHelper.verifyRolloutInStatus(rollout, RolloutStatus.CREATING);
RolloutHelper.verifyRolloutGroupConditions(conditions); RolloutHelper.verifyRolloutGroupConditions(conditions);
JpaRolloutGroup lastSavedGroup = null; final List<JpaRolloutGroup> groups = new ArrayList<>();
JpaRolloutGroup lastGroup = null;
if (amountOfGroups == 0) { if (amountOfGroups == 0) {
if (dynamicRolloutGroupTemplate == null) { if (dynamicRolloutGroupTemplate == null) {
throw new ConstraintDeclarationException( throw new ConstraintDeclarationException(
@@ -596,24 +599,21 @@ public class JpaRolloutManagement implements RolloutManagement {
group.setName(nameAndDesc); group.setName(nameAndDesc);
group.setDescription(nameAndDesc); group.setDescription(nameAndDesc);
group.setRollout(rollout); group.setRollout(rollout);
group.setParent(lastSavedGroup); group.setParent(lastGroup);
group.setStatus(RolloutGroupStatus.CREATING); group.setStatus(RolloutGroupStatus.CREATING);
group.setConfirmationRequired(isConfirmationRequired); group.setConfirmationRequired(isConfirmationRequired);
addSuccessAndErrorConditionsAndActions(group, conditions); addSuccessAndErrorConditionsAndActions(group, conditions);
// total percent of the all devices. Before, it was relative percent - // total percent of the all devices. Before, it was relative percent - the percent of the "rest" of the devices. Thus,
// the percent of the "rest" of the devices. Thus, if you have // if you have first a group 10% (the rest is 90%) and the second group is 50% then the percent would be 50% of 90% - 45%.
// first a group 10% (the rest is 90%) and the second group is 50% // This is very unintuitive and is switched in order to be interpreted easier. The "new style" (vs "old style") rollouts could
// then the percent would be 50% of 90% - 45%. // be detected by JpaRollout#isNewStyleTargetPercent (which uses that old style rollouts have null as dynamic
// This is very unintuitive and is switched in order to be interpreted easier.
// the "new style" (vs "old style") rollouts could be detected by
// JpaRollout#isNewStyleTargetPercent (which uses that old style rollouts
// have null as dynamic
group.setTargetPercentage(100.0F / amountOfGroups); group.setTargetPercentage(100.0F / amountOfGroups);
lastSavedGroup = rolloutGroupRepository.save(group); groups.add(group);
publishRolloutGroupCreatedEventAfterCommit(lastSavedGroup, rollout); lastGroup = group;
publishRolloutGroupCreatedEventAfterCommit(lastGroup, rollout);
} }
} }
@@ -624,7 +624,7 @@ public class JpaRolloutManagement implements RolloutManagement {
group.setName(nameAndDesc); group.setName(nameAndDesc);
group.setDescription(nameAndDesc); group.setDescription(nameAndDesc);
group.setRollout(rollout); group.setRollout(rollout);
group.setParent(lastSavedGroup); group.setParent(lastGroup);
group.setDynamic(true); group.setDynamic(true);
group.setStatus(RolloutGroupStatus.READY); group.setStatus(RolloutGroupStatus.READY);
group.setConfirmationRequired(isConfirmationRequired); group.setConfirmationRequired(isConfirmationRequired);
@@ -634,44 +634,49 @@ public class JpaRolloutManagement implements RolloutManagement {
// for dynamic groups the target count is kept in target percentage // for dynamic groups the target count is kept in target percentage
group.setTargetPercentage(dynamicRolloutGroupTemplate.getTargetCount()); group.setTargetPercentage(dynamicRolloutGroupTemplate.getTargetCount());
lastSavedGroup = rolloutGroupRepository.save(group); groups.add(group);
publishRolloutGroupCreatedEventAfterCommit(lastSavedGroup, rollout); lastGroup = group;
publishRolloutGroupCreatedEventAfterCommit(lastGroup, rollout);
} }
// lastSavedGroup is never null! amountOfGroups > 0 (and has static groups) or dynamicRolloutGroupTemplate is // lastSavedGroup is never null! amountOfGroups > 0 (and has static groups) or dynamicRolloutGroupTemplate is
// not null (validated) and (validated) the rollout is dynamic, so has dynamic group // not null (validated) and (validated) the rollout is dynamic, so has dynamic group
rollout.setRolloutGroupsCreated(lastSavedGroup.isDynamic() ? amountOfGroups + 1 : amountOfGroups); rollout.setRolloutGroupsCreated(lastGroup.isDynamic() ? amountOfGroups + 1 : amountOfGroups);
return rolloutRepository.save(rollout); final JpaRollout savedRollout = rolloutRepository.save(rollout);
rolloutGroupRepository.saveAll(groups);
return savedRollout;
} }
private Rollout createRolloutGroups(final List<RolloutGroupCreate> groupList, private Rollout createRolloutGroups(
final RolloutGroupConditions conditions, final Rollout rollout) { final List<RolloutGroupCreate> groupList, final RolloutGroupConditions conditions, final JpaRollout rollout) {
RolloutHelper.verifyRolloutInStatus(rollout, RolloutStatus.CREATING); RolloutHelper.verifyRolloutInStatus(rollout, RolloutStatus.CREATING);
final JpaRollout savedRollout = (JpaRollout) rollout; final DistributionSetType distributionSetType = rollout.getDistributionSet().getType();
final DistributionSetType distributionSetType = savedRollout.getDistributionSet().getType();
// prepare the groups // prepare the groups
final List<RolloutGroup> groups = groupList.stream() final List<RolloutGroup> srcGroups = groupList.stream()
.map(group -> prepareRolloutGroupWithDefaultConditions(group, conditions)).collect(Collectors.toList()); .map(group -> prepareRolloutGroupWithDefaultConditions(group, conditions))
groups.forEach(RolloutHelper::verifyRolloutGroupHasConditions); .collect(Collectors.toList());
srcGroups.forEach(RolloutHelper::verifyRolloutGroupHasConditions);
RolloutHelper.verifyRemainingTargets(calculateRemainingTargets(groups, savedRollout.getTargetFilterQuery(), RolloutHelper.verifyRemainingTargets(calculateRemainingTargets(
savedRollout.getCreatedAt(), distributionSetType.getId())); srcGroups, rollout.getTargetFilterQuery(), rollout.getCreatedAt(), distributionSetType.getId()));
// check if we need to enforce the 'max targets per group' quota // check if we need to enforce the 'max targets per group' quota
if (quotaManagement.getMaxTargetsPerRolloutGroup() > 0) { if (quotaManagement.getMaxTargetsPerRolloutGroup() > 0) {
validateTargetsInGroups(groups, savedRollout.getTargetFilterQuery(), savedRollout.getCreatedAt(), validateTargetsInGroups(
srcGroups, rollout.getTargetFilterQuery(), rollout.getCreatedAt(),
distributionSetType.getId()).getTargetsPerGroup().forEach(this::assertTargetsPerRolloutGroupQuota); distributionSetType.getId()).getTargetsPerGroup().forEach(this::assertTargetsPerRolloutGroupQuota);
} }
// create and persist the groups (w/o filling them with targets) // create and persist the groups (w/o filling them with targets)
JpaRolloutGroup lastSavedGroup = null; final List<JpaRolloutGroup> groups = new ArrayList<>();
for (final RolloutGroup srcGroup : groups) { JpaRolloutGroup lastGroup = null;
for (final RolloutGroup srcGroup : srcGroups) {
final JpaRolloutGroup group = new JpaRolloutGroup(); final JpaRolloutGroup group = new JpaRolloutGroup();
group.setName(srcGroup.getName()); group.setName(srcGroup.getName());
group.setDescription(srcGroup.getDescription()); group.setDescription(srcGroup.getDescription());
group.setRollout(savedRollout); group.setRollout(rollout);
group.setParent(lastSavedGroup); group.setParent(lastGroup);
group.setStatus(RolloutGroupStatus.CREATING); group.setStatus(RolloutGroupStatus.CREATING);
group.setConfirmationRequired(srcGroup.isConfirmationRequired()); group.setConfirmationRequired(srcGroup.isConfirmationRequired());
@@ -687,12 +692,16 @@ public class JpaRolloutManagement implements RolloutManagement {
srcGroup.getErrorCondition(), srcGroup.getErrorConditionExp(), srcGroup.getErrorAction(), srcGroup.getErrorCondition(), srcGroup.getErrorConditionExp(), srcGroup.getErrorAction(),
srcGroup.getErrorActionExp()); srcGroup.getErrorActionExp());
lastSavedGroup = rolloutGroupRepository.save(group); groups.add(group);
publishRolloutGroupCreatedEventAfterCommit(lastSavedGroup, rollout); lastGroup = group;
publishRolloutGroupCreatedEventAfterCommit(lastGroup, rollout);
} }
savedRollout.setRolloutGroupsCreated(groups.size()); rollout.setRolloutGroupsCreated(groups.size());
return rolloutRepository.save(savedRollout);
final JpaRollout savedRollout = rolloutRepository.save(rollout);
rolloutGroupRepository.saveAll(groups);
return savedRollout;
} }
private JpaRollout getRolloutOrThrowExceptionIfNotFound(final Long rolloutId) { private JpaRollout getRolloutOrThrowExceptionIfNotFound(final Long rolloutId) {
@@ -803,36 +812,31 @@ public class JpaRolloutManagement implements RolloutManagement {
} }
} }
private long calculateRemainingTargets(final List<RolloutGroup> groups, final String targetFilter, private long calculateRemainingTargets(final List<RolloutGroup> groups, final String targetFilter, final Long createdAt, final Long dsTypeId) {
final Long createdAt, final Long dsTypeId) {
final TargetCount targets = calculateTargets(targetFilter, createdAt, dsTypeId); final TargetCount targets = calculateTargets(targetFilter, createdAt, dsTypeId);
long totalTargets = targets.total();
final String baseFilter = targets.filter();
final long totalTargets = targets.total();
if (totalTargets == 0) { if (totalTargets == 0) {
throw new ConstraintDeclarationException("Rollout target filter does not match any targets"); throw new ConstraintDeclarationException("Rollout target filter does not match any targets");
} }
final RolloutGroupsValidation validation = validateTargetsInGroups(groups, baseFilter, totalTargets, dsTypeId); final RolloutGroupsValidation validation = validateTargetsInGroups(groups, targets.filter(), totalTargets, dsTypeId);
return totalTargets - validation.getTargetsInGroups(); return totalTargets - validation.getTargetsInGroups();
} }
private TargetCount calculateTargets(final String targetFilter, final Long createdAt, final Long dsTypeId) { private TargetCount calculateTargets(final String targetFilter, final Long createdAt, final Long dsTypeId) {
String baseFilter; final String baseFilter;
long totalTargets; final long totalTargets;
if (!RolloutHelper.isRolloutRetried(targetFilter)) { if (!RolloutHelper.isRolloutRetried(targetFilter)) {
baseFilter = RolloutHelper.getTargetFilterQuery(targetFilter, createdAt); baseFilter = RolloutHelper.getTargetFilterQuery(targetFilter, createdAt);
totalTargets = targetManagement.countByRsqlAndCompatible(baseFilter, dsTypeId); totalTargets = targetManagement.countByRsqlAndCompatible(baseFilter, dsTypeId);
} else { } else {
totalTargets = targetManagement.countByFailedInRollout(
RolloutHelper.getIdFromRetriedTargetFilter(targetFilter), dsTypeId);
baseFilter = targetFilter; baseFilter = targetFilter;
totalTargets = targetManagement.countByFailedInRollout(RolloutHelper.getIdFromRetriedTargetFilter(targetFilter), dsTypeId);
} }
return new TargetCount(totalTargets, baseFilter); return new TargetCount(totalTargets, baseFilter);
} }
private record TargetCount(long total, String filter) {} private record TargetCount(long total, String filter) {}
} }

View File

@@ -198,26 +198,23 @@ public class JpaTargetManagement implements TargetManagement {
@Override @Override
public long countByRsqlAndCompatible(final String targetFilterQuery, final Long distributionSetIdTypeId) { public long countByRsqlAndCompatible(final String targetFilterQuery, final Long distributionSetIdTypeId) {
final List<Specification<JpaTarget>> specList = List.of(RSQLUtility.buildRsqlSpecification( final List<Specification<JpaTarget>> specList = List.of(
targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database), RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database),
TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetIdTypeId)); TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetIdTypeId));
return JpaManagementHelper.countBySpec(targetRepository, specList); return JpaManagementHelper.countBySpec(targetRepository, specList);
} }
@Override @Override
public long countByRsqlAndCompatibleAndUpdatable(String targetFilterQuery, Long distributionSetIdTypeId) { public long countByRsqlAndCompatibleAndUpdatable(String targetFilterQuery, Long distributionSetIdTypeId) {
final List<Specification<JpaTarget>> specList = List.of(RSQLUtility.buildRsqlSpecification( final List<Specification<JpaTarget>> specList = List.of(
targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database), RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database),
TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetIdTypeId)); TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetIdTypeId));
return targetRepository.count(AccessController.Operation.UPDATE, combineWithAnd(specList)); return targetRepository.count(AccessController.Operation.UPDATE, combineWithAnd(specList));
} }
@Override @Override
public long countByFailedInRollout(final String rolloutId, final Long dsTypeId) { public long countByFailedInRollout(final String rolloutId, final Long dsTypeId) {
final List<Specification<JpaTarget>> specList = List final List<Specification<JpaTarget>> specList = List.of(TargetSpecifications.failedActionsForRollout(rolloutId));
.of(TargetSpecifications.failedActionsForRollout(rolloutId));
return JpaManagementHelper.countBySpec(targetRepository, specList); return JpaManagementHelper.countBySpec(targetRepository, specList);
} }
@@ -225,7 +222,6 @@ public class JpaTargetManagement implements TargetManagement {
public long countByTargetFilterQuery(final long targetFilterQueryId) { public long countByTargetFilterQuery(final long targetFilterQueryId) {
final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository.findById(targetFilterQueryId) final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository.findById(targetFilterQueryId)
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId)); .orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId));
return countByRsql(targetFilterQuery.getQuery()); return countByRsql(targetFilterQuery.getQuery());
} }

View File

@@ -59,35 +59,27 @@ class RolloutGroupManagementTest extends AbstractJpaIntegrationTest {
@Description("Verifies that management queries react as specified on calls for non existing entities " + @Description("Verifies that management queries react as specified on calls for non existing entities " +
" by means of throwing EntityNotFoundException.") " by means of throwing EntityNotFoundException.")
@ExpectEvents({ @ExpectEvents({
@Expect(type = RolloutDeletedEvent.class, count = 0), @Expect(type = RolloutCreatedEvent.class, count = 1),
@Expect(type = RolloutUpdatedEvent.class, count = 1),
@Expect(type = RolloutGroupCreatedEvent.class, count = 5), @Expect(type = RolloutGroupCreatedEvent.class, count = 5),
@Expect(type = RolloutGroupUpdatedEvent.class, count = 5), @Expect(type = RolloutGroupUpdatedEvent.class, count = 5),
@Expect(type = RolloutDeletedEvent.class, count = 0),
@Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
@Expect(type = RolloutUpdatedEvent.class, count = 1), @Expect(type = TargetCreatedEvent.class, count = 125) })
@Expect(type = TargetCreatedEvent.class, count = 125),
@Expect(type = RolloutCreatedEvent.class, count = 1) })
void entityQueriesReferringToNotExistingEntitiesThrowsException() { void entityQueriesReferringToNotExistingEntitiesThrowsException() {
testdataFactory.createRollout(); testdataFactory.createRollout();
verifyThrownExceptionBy(() -> rolloutGroupManagement.countByRollout(NOT_EXIST_IDL), "Rollout"); verifyThrownExceptionBy(() -> rolloutGroupManagement.countByRollout(NOT_EXIST_IDL), "Rollout");
verifyThrownExceptionBy(() -> rolloutGroupManagement.countTargetsOfRolloutsGroup(NOT_EXIST_IDL), verifyThrownExceptionBy(() -> rolloutGroupManagement.countTargetsOfRolloutsGroup(NOT_EXIST_IDL), "RolloutGroup");
"RolloutGroup"); verifyThrownExceptionBy(() -> rolloutGroupManagement.findByRolloutWithDetailedStatus(PAGE, NOT_EXIST_IDL), "Rollout");
verifyThrownExceptionBy(() -> rolloutGroupManagement.findByRolloutWithDetailedStatus(PAGE, NOT_EXIST_IDL), verifyThrownExceptionBy(() -> rolloutGroupManagement.findAllTargetsOfRolloutGroupWithActionStatus(PAGE, NOT_EXIST_IDL), "RolloutGroup");
"Rollout"); verifyThrownExceptionBy(() -> rolloutGroupManagement.findByRolloutAndRsql(PAGE, NOT_EXIST_IDL, "name==*"), "Rollout");
verifyThrownExceptionBy(
() -> rolloutGroupManagement.findAllTargetsOfRolloutGroupWithActionStatus(PAGE, NOT_EXIST_IDL),
"RolloutGroup");
verifyThrownExceptionBy(() -> rolloutGroupManagement.findByRolloutAndRsql(PAGE, NOT_EXIST_IDL, "name==*"),
"Rollout");
verifyThrownExceptionBy(() -> rolloutGroupManagement.findTargetsOfRolloutGroup(PAGE, NOT_EXIST_IDL), verifyThrownExceptionBy(() -> rolloutGroupManagement.findTargetsOfRolloutGroup(PAGE, NOT_EXIST_IDL), "RolloutGroup");
"RolloutGroup"); verifyThrownExceptionBy(() -> rolloutGroupManagement.findTargetsOfRolloutGroupByRsql(PAGE, NOT_EXIST_IDL, "name==*"), "RolloutGroup");
verifyThrownExceptionBy(
() -> rolloutGroupManagement.findTargetsOfRolloutGroupByRsql(PAGE, NOT_EXIST_IDL, "name==*"),
"RolloutGroup");
} }
@Test @Test

View File

@@ -301,7 +301,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
@Expect(type = RolloutCreatedEvent.class, count = 1), @Expect(type = RolloutCreatedEvent.class, count = 1),
@Expect(type = RolloutUpdatedEvent.class, count = 1), @Expect(type = RolloutUpdatedEvent.class, count = 1),
@Expect(type = TargetCreatedEvent.class, count = 125) }) @Expect(type = TargetCreatedEvent.class, count = 125) })
void entityQueriesReferringToNotExistingEntitiesThrowsException() { void entityQueriesReferringToNotExistingEntitiesThrowsException() {
@@ -1411,7 +1411,6 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verify that a rollout cannot be created based on group definitions if the 'max targets per rollout group' quota is violated for one of the groups.") @Description("Verify that a rollout cannot be created based on group definitions if the 'max targets per rollout group' quota is violated for one of the groups.")
void createRolloutWithGroupDefinitionsFailsIfQuotaGroupQuotaIsViolated() { void createRolloutWithGroupDefinitionsFailsIfQuotaGroupQuotaIsViolated() {
final int maxTargets = quotaManagement.getMaxTargetsPerRolloutGroup(); final int maxTargets = quotaManagement.getMaxTargetsPerRolloutGroup();
final int amountTargetsForRollout = maxTargets * 2 + 2; final int amountTargetsForRollout = maxTargets * 2 + 2;
@@ -1422,43 +1421,45 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build(); final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build();
// create group definitions // create group definitions
final RolloutGroupCreate group1 = entityFactory.rolloutGroup().create().conditions(conditions).name("group1") final RolloutGroupCreate group1 = entityFactory.rolloutGroup().create().conditions(conditions).name("group1").targetPercentage(50.0F);
.targetPercentage(50.0F); final RolloutGroupCreate group2 = entityFactory.rolloutGroup().create().conditions(conditions).name("group2").targetPercentage(50.0F);
final RolloutGroupCreate group2 = entityFactory.rolloutGroup().create().conditions(conditions).name("group2")
.targetPercentage(50.0F);
// group1 exceeds the quota // group1 exceeds the quota
assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> rolloutManagement.create( assertThatExceptionOfType(AssignmentQuotaExceededException.class)
entityFactory.rollout().create().name(rolloutName).description(rolloutName) .isThrownBy(() -> rolloutManagement.create(
.targetFilterQuery("controllerId==" + rolloutName + "-*").distributionSetId(distributionSet), entityFactory.rollout().create()
Arrays.asList(group1, group2), conditions)); .name(rolloutName)
.description(rolloutName)
.targetFilterQuery("controllerId==" + rolloutName + "-*")
.distributionSetId(distributionSet),
Arrays.asList(group1, group2), conditions));
// create group definitions // create group definitions
final RolloutGroupCreate group3 = entityFactory.rolloutGroup().create().conditions(conditions).name("group3") final RolloutGroupCreate group3 = entityFactory.rolloutGroup().create().conditions(conditions).name("group3").targetPercentage(1.0F);
.targetPercentage(1.0F); final RolloutGroupCreate group4 = entityFactory.rolloutGroup().create().conditions(conditions).name("group4").targetPercentage(100.0F);
final RolloutGroupCreate group4 = entityFactory.rolloutGroup().create().conditions(conditions).name("group4")
.targetPercentage(100.0F);
// group4 exceeds the quota // group4 exceeds the quota
assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> rolloutManagement.create( assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> rolloutManagement.create(
entityFactory.rollout().create().name(rolloutName).description(rolloutName) entityFactory.rollout().create()
.targetFilterQuery("controllerId==" + rolloutName + "-*").distributionSetId(distributionSet), .name(rolloutName)
.description(rolloutName)
.targetFilterQuery("controllerId==" + rolloutName + "-*")
.distributionSetId(distributionSet),
Arrays.asList(group3, group4), conditions)); Arrays.asList(group3, group4), conditions));
// create group definitions // create group definitions
final RolloutGroupCreate group5 = entityFactory.rolloutGroup().create().conditions(conditions).name("group5") final RolloutGroupCreate group5 = entityFactory.rolloutGroup().create().conditions(conditions).name("group5").targetPercentage(33.3F);
.targetPercentage(33.3F); final RolloutGroupCreate group6 = entityFactory.rolloutGroup().create().conditions(conditions).name("group6").targetPercentage(33.3F);
final RolloutGroupCreate group6 = entityFactory.rolloutGroup().create().conditions(conditions).name("group6") final RolloutGroupCreate group7 = entityFactory.rolloutGroup().create().conditions(conditions).name("group7").targetPercentage(33.3F);
.targetPercentage(33.3F);
final RolloutGroupCreate group7 = entityFactory.rolloutGroup().create().conditions(conditions).name("group7")
.targetPercentage(33.3F);
// should work fine // should work fine
assertThat(rolloutManagement.create( assertThat(rolloutManagement.create(
entityFactory.rollout().create().name(rolloutName).description(rolloutName) entityFactory.rollout().create()
.targetFilterQuery("controllerId==" + rolloutName + "-*").distributionSetId(distributionSet), .name(rolloutName)
.description(rolloutName)
.targetFilterQuery("controllerId==" + rolloutName + "-*")
.distributionSetId(distributionSet),
Arrays.asList(group5, group6, group7), conditions)).isNotNull(); Arrays.asList(group5, group6, group7), conditions)).isNotNull();
} }
@Test @Test
@@ -1770,7 +1771,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@ExpectEvents({ @ExpectEvents({
@Expect(type = RolloutDeletedEvent.class, count = 1), @Expect(type = RolloutDeletedEvent.class, count = 1),
@Expect(type = TargetCreatedEvent.class, count = 25), @Expect(type = TargetCreatedEvent.class, count = 25),
@Expect(type = RolloutUpdatedEvent.class, count = 2), @Expect(type = RolloutUpdatedEvent.class, count = 2),
@Expect(type = RolloutGroupCreatedEvent.class, count = 5), @Expect(type = RolloutGroupCreatedEvent.class, count = 5),
@Expect(type = RolloutGroupDeletedEvent.class, count = 5), @Expect(type = RolloutGroupDeletedEvent.class, count = 5),
@@ -1809,11 +1810,11 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
@Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
@Expect(type = TargetCreatedEvent.class, count = 25), @Expect(type = TargetCreatedEvent.class, count = 25),
@Expect(type = TargetUpdatedEvent.class, count = 2), @Expect(type = TargetUpdatedEvent.class, count = 2),
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = RolloutGroupCreatedEvent.class, count = 5), @Expect(type = RolloutGroupCreatedEvent.class, count = 5),
@Expect(type = ActionCreatedEvent.class, count = 10), @Expect(type = ActionCreatedEvent.class, count = 10),
@Expect(type = ActionUpdatedEvent.class, count = 2), @Expect(type = ActionUpdatedEvent.class, count = 2),
@Expect(type = RolloutDeletedEvent.class, count = 1), @Expect(type = RolloutDeletedEvent.class, count = 1),
@Expect(type = RolloutCreatedEvent.class, count = 1) }) @Expect(type = RolloutCreatedEvent.class, count = 1) })

View File

@@ -1051,8 +1051,13 @@ public class TestdataFactory {
.errorAction(RolloutGroupErrorAction.PAUSE, null).build(); .errorAction(RolloutGroupErrorAction.PAUSE, null).build();
final Rollout rollout = rolloutManagement.create( final Rollout rollout = rolloutManagement.create(
entityFactory.rollout().create().name(rolloutName).description(rolloutDescription) entityFactory.rollout().create()
.targetFilterQuery(filterQuery).distributionSetId(distributionSet).actionType(actionType).weight(weight) .name(rolloutName)
.description(rolloutDescription)
.targetFilterQuery(filterQuery)
.distributionSetId(distributionSet)
.actionType(actionType)
.weight(weight)
.dynamic(dynamic), .dynamic(dynamic),
groupSize, confirmationRequired, conditions, dynamicRolloutGroupTemplate); groupSize, confirmationRequired, conditions, dynamicRolloutGroupTemplate);