@Override @Async public ListenableFuture<RolloutGroupsValidation> validateTargetsInGroups(final List<RolloutGroupCreate> groups, final String targetFilter, final Long createdAt) { final String baseFilter = RolloutHelper.getTargetFilterQuery(targetFilter, createdAt); final long totalTargets = targetManagement.countByRsql(baseFilter); if (totalTargets == 0) { throw new ConstraintDeclarationException("Rollout target filter does not match any targets"); } return new AsyncResult<>(validateTargetsInGroups( groups.stream().map(RolloutGroupCreate::build).collect(Collectors.toList()), baseFilter, totalTargets)); }
if (isTargetFilterInGroups(groupFilter, groups)) { return concatAndTargetFilters(baseFilter, groupFilter); final String previousGroupFilters = getAllGroupsTargetFilter(groups); if (!StringUtils.isEmpty(previousGroupFilters)) { if (!StringUtils.isEmpty(groupFilter)) { return concatAndTargetFilters(baseFilter, groupFilter, previousGroupFilters); } else { return concatAndTargetFilters(baseFilter, previousGroupFilters); return concatAndTargetFilters(baseFilter, groupFilter); } else { return baseFilter;
protected RolloutGroupsValidation validateTargetsInGroups(final List<RolloutGroup> groups, final String baseFilter, final long totalTargets) { final List<Long> groupTargetCounts = new ArrayList<>(groups.size()); final Map<String, Long> targetFilterCounts = groups.stream() .map(group -> RolloutHelper.getGroupTargetFilter(baseFilter, group)).distinct() .collect(Collectors.toMap(Function.identity(), targetManagement::countByRsql)); long unusedTargetsCount = 0; for (int i = 0; i < groups.size(); i++) { final RolloutGroup group = groups.get(i); final String groupTargetFilter = RolloutHelper.getGroupTargetFilter(baseFilter, group); RolloutHelper.verifyRolloutGroupTargetPercentage(group.getTargetPercentage()); final long targetsInGroupFilter = targetFilterCounts.get(groupTargetFilter); final long overlappingTargets = countOverlappingTargetsWithPreviousGroups(baseFilter, groups, group, i, targetFilterCounts); final long realTargetsInGroup; // Assume that targets which were not used in the previous groups // are used in this group if (overlappingTargets > 0 && unusedTargetsCount > 0) { realTargetsInGroup = targetsInGroupFilter - overlappingTargets + unusedTargetsCount; unusedTargetsCount = 0; } else { realTargetsInGroup = targetsInGroupFilter - overlappingTargets; } final long reducedTargetsInGroup = Math .round(group.getTargetPercentage() / 100 * (double) realTargetsInGroup); groupTargetCounts.add(reducedTargetsInGroup); unusedTargetsCount += realTargetsInGroup - reducedTargetsInGroup; } return new RolloutGroupsValidation(totalTargets, groupTargetCounts); }
private RolloutGroup fillRolloutGroupWithTargets(final JpaRollout rollout, final RolloutGroup group1) { RolloutHelper.verifyRolloutInStatus(rollout, RolloutStatus.CREATING); final String baseFilter = RolloutHelper.getTargetFilterQuery(rollout); final String groupTargetFilter; if (StringUtils.isEmpty(group.getTargetFilterQuery())) { final List<Long> readyGroups = RolloutHelper.getGroupsByStatusIncludingGroup(rollout.getRolloutGroups(), RolloutGroupStatus.READY, group);
private Rollout createRolloutGroups(final int amountOfGroups, final RolloutGroupConditions conditions, final JpaRollout rollout) { RolloutHelper.verifyRolloutInStatus(rollout, RolloutStatus.CREATING); RolloutHelper.verifyRolloutGroupConditions(conditions);
private Rollout createRolloutGroups(final List<RolloutGroupCreate> groupList, final RolloutGroupConditions conditions, final Rollout rollout) { RolloutHelper.verifyRolloutInStatus(rollout, RolloutStatus.CREATING); final JpaRollout savedRollout = (JpaRollout) rollout; groups.forEach(RolloutHelper::verifyRolloutGroupHasConditions); RolloutHelper.verifyRemainingTargets( calculateRemainingTargets(groups, savedRollout.getTargetFilterQuery(), savedRollout.getCreatedAt()));
@Override @Transactional @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) public Rollout start(final long rolloutId) { LOGGER.debug("startRollout called for rollout {}", rolloutId); final JpaRollout rollout = getRolloutAndThrowExceptionIfNotFound(rolloutId); RolloutHelper.checkIfRolloutCanStarted(rollout, rollout); rollout.setStatus(RolloutStatus.STARTING); rollout.setLastCheck(0); return rolloutRepository.save(rollout); }
private Long assignTargetsToGroupInNewTransaction(final JpaRollout rollout, final RolloutGroup group, final String targetFilter, final long limit) { return DeploymentHelper.runInNewTransaction(txManager, "assignTargetsToRolloutGroup", status -> { final PageRequest pageRequest = PageRequest.of(0, Math.toIntExact(limit)); final List<Long> readyGroups = RolloutHelper.getGroupsByStatusIncludingGroup(rollout.getRolloutGroups(), RolloutGroupStatus.READY, group); final Page<Target> targets = targetManagement.findByTargetFilterQueryAndNotInRolloutGroups(pageRequest, readyGroups, targetFilter); createAssignmentOfTargetsToGroup(targets, group); return Long.valueOf(targets.getNumberOfElements()); }); }
private long countOverlappingTargetsWithPreviousGroups(final String baseFilter, final List<RolloutGroup> groups, final RolloutGroup group, final int groupIndex, final Map<String, Long> targetFilterCounts) { // there can't be overlapping targets in the first group if (groupIndex == 0) { return 0; } final List<RolloutGroup> previousGroups = groups.subList(0, groupIndex); final String overlappingTargetsFilter = RolloutHelper.getOverlappingWithGroupsTargetFilter(baseFilter, previousGroups, group); if (targetFilterCounts.containsKey(overlappingTargetsFilter)) { return targetFilterCounts.get(overlappingTargetsFilter); } else { final long overlappingTargets = targetManagement.countByRsql(overlappingTargetsFilter); targetFilterCounts.put(overlappingTargetsFilter, overlappingTargets); return overlappingTargets; } }
/** * @param baseFilter * the base filter from the rollout * @param group * group for which the filter string should be created * @return the final target filter query for a rollout group */ static String getGroupTargetFilter(final String baseFilter, final RolloutGroup group) { if (StringUtils.isEmpty(group.getTargetFilterQuery())) { return baseFilter; } else { return concatAndTargetFilters(baseFilter, group.getTargetFilterQuery()); } }
private RolloutGroup fillRolloutGroupWithTargets(final JpaRollout rollout, final RolloutGroup group1) { RolloutHelper.verifyRolloutInStatus(rollout, RolloutStatus.CREATING); final String baseFilter = RolloutHelper.getTargetFilterQuery(rollout); final String groupTargetFilter; if (StringUtils.isEmpty(group.getTargetFilterQuery())) { final List<Long> readyGroups = RolloutHelper.getGroupsByStatusIncludingGroup(rollout.getRolloutGroups(), RolloutGroupStatus.READY, group);
private Rollout createRolloutGroups(final int amountOfGroups, final RolloutGroupConditions conditions, final JpaRollout rollout) { RolloutHelper.verifyRolloutInStatus(rollout, RolloutStatus.CREATING); RolloutHelper.verifyRolloutGroupConditions(conditions);
private Rollout createRolloutGroups(final List<RolloutGroupCreate> groupList, final RolloutGroupConditions conditions, final Rollout rollout) { RolloutHelper.verifyRolloutInStatus(rollout, RolloutStatus.CREATING); final JpaRollout savedRollout = (JpaRollout) rollout; groups.forEach(RolloutHelper::verifyRolloutGroupHasConditions); RolloutHelper.verifyRemainingTargets( calculateRemainingTargets(groups, savedRollout.getTargetFilterQuery(), savedRollout.getCreatedAt()));
@Override @Transactional @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) public Rollout start(final long rolloutId) { LOGGER.debug("startRollout called for rollout {}", rolloutId); final JpaRollout rollout = getRolloutAndThrowExceptionIfNotFound(rolloutId); RolloutHelper.checkIfRolloutCanStarted(rollout, rollout); rollout.setStatus(RolloutStatus.STARTING); rollout.setLastCheck(0); return rolloutRepository.save(rollout); }
private Long assignTargetsToGroupInNewTransaction(final JpaRollout rollout, final RolloutGroup group, final String targetFilter, final long limit) { return runInNewTransaction("assignTargetsToRolloutGroup", status -> { final PageRequest pageRequest = new PageRequest(0, Math.toIntExact(limit)); final List<Long> readyGroups = RolloutHelper.getGroupsByStatusIncludingGroup(rollout.getRolloutGroups(), RolloutGroupStatus.READY, group); final Page<Target> targets = targetManagement.findByTargetFilterQueryAndNotInRolloutGroups(pageRequest, readyGroups, targetFilter); createAssignmentOfTargetsToGroup(targets, group); return Long.valueOf(targets.getNumberOfElements()); }); }
@Override @Async public ListenableFuture<RolloutGroupsValidation> validateTargetsInGroups(final List<RolloutGroupCreate> groups, final String targetFilter, final Long createdAt) { final String baseFilter = RolloutHelper.getTargetFilterQuery(targetFilter, createdAt); final long totalTargets = targetManagement.countByRsql(baseFilter); if (totalTargets == 0) { throw new ConstraintDeclarationException("Rollout target filter does not match any targets"); } return new AsyncResult<>(validateTargetsInGroups( groups.stream().map(RolloutGroupCreate::build).collect(Collectors.toList()), baseFilter, totalTargets)); }
/** * Modifies the target filter query to only match targets that were created * after the Rollout. * * @param rollout * Rollout to derive the filter from * @return resulting target filter query */ public static String getTargetFilterQuery(final Rollout rollout) { return getTargetFilterQuery(rollout.getTargetFilterQuery(), rollout.getCreatedAt()); }
@Override @Async public ListenableFuture<RolloutGroupsValidation> validateTargetsInGroups(final List<RolloutGroupCreate> groups, final String targetFilter, final Long createdAt) { final String baseFilter = RolloutHelper.getTargetFilterQuery(targetFilter, createdAt); final long totalTargets = targetManagement.countByRsql(baseFilter); if (totalTargets == 0) { throw new ConstraintDeclarationException("Rollout target filter does not match any targets"); } return new AsyncResult<>(validateTargetsInGroups( groups.stream().map(RolloutGroupCreate::build).collect(Collectors.toList()), baseFilter, totalTargets)); }
protected long calculateRemainingTargets(final List<RolloutGroup> groups, final String targetFilter, final Long createdAt) { final String baseFilter = RolloutHelper.getTargetFilterQuery(targetFilter, createdAt); final long totalTargets = targetManagement.countByRsql(baseFilter); if (totalTargets == 0) { throw new ConstraintDeclarationException("Rollout target filter does not match any targets"); } final RolloutGroupsValidation validation = validateTargetsInGroups(groups, baseFilter, totalTargets); return totalTargets - validation.getTargetsInGroups(); }