Fix circular rollout dependencies (#1337)
* Do some refactoring to fix dependencies between rollout management, executor and evaluator beans. * Move rollout retrieving in same transaction as execution. * Do some refactoring. Extend logging and exception handling. * Remove unnecessary transactional and validation annotations. * remove catching never thrown bean * Fix new rollout handling API
This commit is contained in:
@@ -34,8 +34,8 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.RolloutTargetGroup;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupActionEvaluator;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupConditionEvaluator;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.EvaluatorNotConfiguredException;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupEvaluationManager;
|
||||
import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper;
|
||||
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
@@ -53,8 +53,6 @@ import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.domain.Sort;
|
||||
@@ -105,8 +103,9 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
||||
private final EventPublisherHolder eventPublisherHolder;
|
||||
private final PlatformTransactionManager txManager;
|
||||
private final RolloutApprovalStrategy rolloutApprovalStrategy;
|
||||
private final ApplicationContext context;
|
||||
|
||||
private final RolloutGroupEvaluationManager evaluationManager;
|
||||
private final RolloutManagement rolloutManagement;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
@@ -117,7 +116,8 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
||||
final RolloutGroupManagement rolloutGroupManagement, final QuotaManagement quotaManagement,
|
||||
final DeploymentManagement deploymentManagement, final TargetManagement targetManagement,
|
||||
final EventPublisherHolder eventPublisherHolder, final PlatformTransactionManager txManager,
|
||||
final RolloutApprovalStrategy rolloutApprovalStrategy, final ApplicationContext context) {
|
||||
final RolloutApprovalStrategy rolloutApprovalStrategy,
|
||||
final RolloutGroupEvaluationManager evaluationManager, final RolloutManagement rolloutManagement) {
|
||||
this.rolloutTargetGroupRepository = rolloutTargetGroupRepository;
|
||||
this.entityManager = entityManager;
|
||||
this.rolloutRepository = rolloutRepository;
|
||||
@@ -132,7 +132,8 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
||||
this.eventPublisherHolder = eventPublisherHolder;
|
||||
this.txManager = txManager;
|
||||
this.rolloutApprovalStrategy = rolloutApprovalStrategy;
|
||||
this.context = context;
|
||||
this.evaluationManager = evaluationManager;
|
||||
this.rolloutManagement = rolloutManagement;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -285,7 +286,7 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
||||
LOGGER.debug(
|
||||
"handleReadyRollout called for rollout {} with autostart beyond define time. Switch to STARTING",
|
||||
rollout.getId());
|
||||
context.getBean(RolloutManagement.class).start(rollout.getId());
|
||||
rolloutManagement.start(rollout.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,11 +418,10 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
||||
|
||||
private void callErrorAction(final Rollout rollout, final RolloutGroup rolloutGroup) {
|
||||
try {
|
||||
context.getBean(rolloutGroup.getErrorAction().getBeanName(), RolloutGroupActionEvaluator.class)
|
||||
.eval(rollout, rolloutGroup, rolloutGroup.getErrorActionExp());
|
||||
} catch (final BeansException e) {
|
||||
LOGGER.error("Something bad happend when accessing the error action bean {}",
|
||||
rolloutGroup.getErrorAction().getBeanName(), e);
|
||||
evaluationManager.getErrorActionEvaluator(rolloutGroup.getErrorAction()).exec(rollout, rolloutGroup);
|
||||
} catch (final EvaluatorNotConfiguredException e) {
|
||||
LOGGER.error("Something bad happened when accessing the error action bean {}",
|
||||
rolloutGroup.getErrorAction().name(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,11 +443,10 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return context.getBean(errorCondition.getBeanName(), RolloutGroupConditionEvaluator.class).eval(rollout,
|
||||
rolloutGroup, rolloutGroup.getErrorConditionExp());
|
||||
} catch (final BeansException e) {
|
||||
LOGGER.error("Something bad happend when accessing the error condition bean {}",
|
||||
errorCondition.getBeanName(), e);
|
||||
return evaluationManager.getErrorConditionEvaluator(errorCondition).eval(rollout, rolloutGroup,
|
||||
rolloutGroup.getErrorConditionExp());
|
||||
} catch (final EvaluatorNotConfiguredException e) {
|
||||
LOGGER.error("Something bad happened when accessing the error condition bean {}", errorCondition.name(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -456,9 +455,8 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
||||
final RolloutGroupSuccessCondition finishCondition) {
|
||||
LOGGER.trace("Checking finish condition {} on rolloutgroup {}", finishCondition, rolloutGroup);
|
||||
try {
|
||||
final boolean isFinished = context
|
||||
.getBean(finishCondition.getBeanName(), RolloutGroupConditionEvaluator.class)
|
||||
.eval(rollout, rolloutGroup, rolloutGroup.getSuccessConditionExp());
|
||||
final boolean isFinished = evaluationManager.getSuccessConditionEvaluator(finishCondition).eval(rollout,
|
||||
rolloutGroup, rolloutGroup.getSuccessConditionExp());
|
||||
if (isFinished) {
|
||||
LOGGER.debug("Rolloutgroup {} is finished, starting next group", rolloutGroup);
|
||||
executeRolloutGroupSuccessAction(rollout, rolloutGroup);
|
||||
@@ -466,16 +464,15 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
||||
LOGGER.debug("Rolloutgroup {} is still running", rolloutGroup);
|
||||
}
|
||||
return isFinished;
|
||||
} catch (final BeansException e) {
|
||||
LOGGER.error("Something bad happend when accessing the finish condition bean {}",
|
||||
finishCondition.getBeanName(), e);
|
||||
} catch (final EvaluatorNotConfiguredException e) {
|
||||
LOGGER.error("Something bad happened when accessing the finish condition or success action bean {}",
|
||||
finishCondition.name(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void executeRolloutGroupSuccessAction(final Rollout rollout, final RolloutGroup rolloutGroup) {
|
||||
context.getBean(rolloutGroup.getSuccessAction().getBeanName(), RolloutGroupActionEvaluator.class).eval(rollout,
|
||||
rolloutGroup, rolloutGroup.getSuccessActionExp());
|
||||
evaluationManager.getSuccessActionEvaluator(rolloutGroup.getSuccessAction()).exec(rollout, rolloutGroup);
|
||||
}
|
||||
|
||||
private void startFirstRolloutGroup(final Rollout rollout) {
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* Copyright (c) 2023 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import org.eclipse.hawkbit.repository.RolloutExecutor;
|
||||
import org.eclipse.hawkbit.repository.RolloutHandler;
|
||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper;
|
||||
import org.eclipse.hawkbit.repository.model.BaseEntity;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.integration.support.locks.LockRegistry;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
/**
|
||||
* JPA implementation of {@link RolloutHandler}.
|
||||
*/
|
||||
public class JpaRolloutHandler implements RolloutHandler {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(JpaRolloutHandler.class);
|
||||
|
||||
private final TenantAware tenantAware;
|
||||
private final RolloutManagement rolloutManagement;
|
||||
private final RolloutExecutor rolloutExecutor;
|
||||
private final LockRegistry lockRegistry;
|
||||
private final PlatformTransactionManager txManager;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param tenantAware
|
||||
* the {@link TenantAware} bean holding the tenant information
|
||||
* @param rolloutManagement
|
||||
* to fetch rollout related information from the datasource
|
||||
* @param rolloutExecutor
|
||||
* to trigger executions for a specific rollout
|
||||
* @param lockRegistry
|
||||
* to lock processes
|
||||
* @param txManager
|
||||
* transaction manager interface
|
||||
*/
|
||||
public JpaRolloutHandler(final TenantAware tenantAware, final RolloutManagement rolloutManagement,
|
||||
final RolloutExecutor rolloutExecutor, final LockRegistry lockRegistry,
|
||||
final PlatformTransactionManager txManager) {
|
||||
this.tenantAware = tenantAware;
|
||||
this.rolloutManagement = rolloutManagement;
|
||||
this.rolloutExecutor = rolloutExecutor;
|
||||
this.lockRegistry = lockRegistry;
|
||||
this.txManager = txManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleAll() {
|
||||
final List<Long> rollouts = rolloutManagement.findActiveRollouts();
|
||||
|
||||
if (rollouts.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String handlerId = createRolloutLockKey(tenantAware.getCurrentTenant());
|
||||
final Lock lock = lockRegistry.obtain(handlerId);
|
||||
if (!lock.tryLock()) {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("Could not perform lock {}", lock);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
LOGGER.trace("Trigger handling {} rollouts.", rollouts.size());
|
||||
rollouts.forEach(rolloutId -> handleRolloutInNewTransaction(rolloutId, handlerId));
|
||||
} finally {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("Unlock lock {}", lock);
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private static String createRolloutLockKey(final String tenant) {
|
||||
return tenant + "-rollout";
|
||||
}
|
||||
|
||||
private void handleRolloutInNewTransaction(final long rolloutId, final String handlerId) {
|
||||
DeploymentHelper.runInNewTransaction(txManager, handlerId + "-" + rolloutId, status -> {
|
||||
rolloutManagement.get(rolloutId).ifPresentOrElse(
|
||||
rollout -> runInUserContext(rollout, () -> rolloutExecutor.execute(rollout)),
|
||||
() -> LOGGER.error("Could not retrieve rollout with id {}. Will not continue with execution.",
|
||||
rolloutId));
|
||||
return 0L;
|
||||
});
|
||||
}
|
||||
|
||||
private void runInUserContext(final BaseEntity rollout, final Runnable handler) {
|
||||
DeploymentHelper.runInNonSystemContext(handler, () -> Objects.requireNonNull(rollout.getCreatedBy()),
|
||||
tenantAware);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,9 +16,7 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -28,7 +26,6 @@ import javax.validation.ValidationException;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||
import org.eclipse.hawkbit.repository.RolloutApprovalStrategy;
|
||||
import org.eclipse.hawkbit.repository.RolloutExecutor;
|
||||
import org.eclipse.hawkbit.repository.RolloutFields;
|
||||
import org.eclipse.hawkbit.repository.RolloutHelper;
|
||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
@@ -52,10 +49,8 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaRollout_;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.StartNextGroupRolloutGroupSuccessAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
|
||||
import org.eclipse.hawkbit.repository.jpa.specifications.RolloutSpecification;
|
||||
import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper;
|
||||
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
|
||||
import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper;
|
||||
import org.eclipse.hawkbit.repository.model.BaseEntity;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
@@ -70,8 +65,6 @@ import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.eclipse.hawkbit.utils.TenantConfigHelper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -82,14 +75,11 @@ import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.integration.support.locks.LockRegistry;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.AsyncResult;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.concurrent.ListenableFuture;
|
||||
@@ -137,35 +127,26 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
private final TargetManagement targetManagement;
|
||||
private final DistributionSetManagement distributionSetManagement;
|
||||
private final VirtualPropertyReplacer virtualPropertyReplacer;
|
||||
private final PlatformTransactionManager txManager;
|
||||
private final TenantAware tenantAware;
|
||||
private final LockRegistry lockRegistry;
|
||||
private final RolloutApprovalStrategy rolloutApprovalStrategy;
|
||||
private final TenantConfigurationManagement tenantConfigurationManagement;
|
||||
private final SystemSecurityContext systemSecurityContext;
|
||||
private final RolloutExecutor rolloutExecutor;
|
||||
private final EventPublisherHolder eventPublisherHolder;
|
||||
private final Database database;
|
||||
|
||||
public JpaRolloutManagement(final TargetManagement targetManagement,
|
||||
final DistributionSetManagement distributionSetManagement, final EventPublisherHolder eventPublisherHolder,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final PlatformTransactionManager txManager,
|
||||
final TenantAware tenantAware, final LockRegistry lockRegistry, final Database database,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final Database database,
|
||||
final RolloutApprovalStrategy rolloutApprovalStrategy,
|
||||
final TenantConfigurationManagement tenantConfigurationManagement,
|
||||
final SystemSecurityContext systemSecurityContext, final RolloutExecutor rolloutExecutor) {
|
||||
final SystemSecurityContext systemSecurityContext) {
|
||||
this.targetManagement = targetManagement;
|
||||
this.distributionSetManagement = distributionSetManagement;
|
||||
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
||||
this.txManager = txManager;
|
||||
this.tenantAware = tenantAware;
|
||||
this.lockRegistry = lockRegistry;
|
||||
this.rolloutApprovalStrategy = rolloutApprovalStrategy;
|
||||
this.tenantConfigurationManagement = tenantConfigurationManagement;
|
||||
this.systemSecurityContext = systemSecurityContext;
|
||||
this.eventPublisherHolder = eventPublisherHolder;
|
||||
this.database = database;
|
||||
this.rolloutExecutor = rolloutExecutor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -435,43 +416,10 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
rolloutRepository.save(rollout);
|
||||
}
|
||||
|
||||
@Override
|
||||
// No transaction, will be created per handled rollout
|
||||
@Transactional(propagation = Propagation.NEVER)
|
||||
public void handleRollouts() {
|
||||
final List<Long> rollouts = rolloutRepository.findByStatusIn(ACTIVE_ROLLOUTS);
|
||||
|
||||
if (rollouts.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String tenant = tenantAware.getCurrentTenant();
|
||||
|
||||
final String handlerId = createRolloutLockKey(tenant);
|
||||
final Lock lock = lockRegistry.obtain(handlerId);
|
||||
if (!lock.tryLock()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
rollouts.forEach(rolloutId -> DeploymentHelper.runInNewTransaction(txManager, handlerId + "-" + rolloutId,
|
||||
status -> handleRollout(rolloutId)));
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public static String createRolloutLockKey(final String tenant) {
|
||||
return tenant + "-rollout";
|
||||
}
|
||||
|
||||
private long handleRollout(final long rolloutId) {
|
||||
final JpaRollout rollout = rolloutRepository.findById(rolloutId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Rollout.class, rolloutId));
|
||||
runInUserContext(rollout, () -> rolloutExecutor.execute(rollout));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(include = {
|
||||
@@ -517,6 +465,11 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
return findAll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> findActiveRollouts() {
|
||||
return rolloutRepository.findByStatusIn(ACTIVE_ROLLOUTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Rollout> getByName(final String rolloutName) {
|
||||
return rolloutRepository.findByName(rolloutName);
|
||||
@@ -649,11 +602,6 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
QuotaHelper.assertAssignmentQuota(requested, quota, Target.class, RolloutGroup.class);
|
||||
}
|
||||
|
||||
private void runInUserContext(final BaseEntity rollout, final Runnable handler) {
|
||||
DeploymentHelper.runInNonSystemContext(handler, () -> Objects.requireNonNull(rollout.getCreatedBy()),
|
||||
tenantAware);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void cancelRolloutsForDistributionSet(final DistributionSet set) {
|
||||
@@ -778,7 +726,7 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
.filter(g -> RolloutGroupStatus.RUNNING.equals(g.getStatus())).findFirst()
|
||||
.orElseThrow(() -> new RolloutIllegalStateException("No group is running"));
|
||||
|
||||
startNextRolloutGroupAction.eval(rollout, latestRunning, latestRunning.getSuccessActionExp());
|
||||
startNextRolloutGroupAction.exec(rollout, latestRunning);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.eclipse.hawkbit.repository.RepositoryProperties;
|
||||
import org.eclipse.hawkbit.repository.RolloutApprovalStrategy;
|
||||
import org.eclipse.hawkbit.repository.RolloutExecutor;
|
||||
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
||||
import org.eclipse.hawkbit.repository.RolloutHandler;
|
||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
import org.eclipse.hawkbit.repository.RolloutStatusCache;
|
||||
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
|
||||
@@ -84,6 +85,9 @@ import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHol
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantAwareHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.RolloutScheduler;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.PauseRolloutGroupAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupActionEvaluator;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupConditionEvaluator;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupEvaluationManager;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.StartNextGroupRolloutGroupSuccessAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupErrorCondition;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupSuccessCondition;
|
||||
@@ -92,6 +96,7 @@ import org.eclipse.hawkbit.repository.jpa.rsql.RsqlParserValidationOracle;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
@@ -119,7 +124,6 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
|
||||
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
@@ -195,6 +199,16 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
return new ThresholdRolloutGroupSuccessCondition(actionRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
RolloutGroupEvaluationManager evaluationManager(
|
||||
final List<RolloutGroupConditionEvaluator<RolloutGroup.RolloutGroupErrorCondition>> errorConditionEvaluators,
|
||||
final List<RolloutGroupConditionEvaluator<RolloutGroup.RolloutGroupSuccessCondition>> successConditionEvaluators,
|
||||
final List<RolloutGroupActionEvaluator<RolloutGroup.RolloutGroupErrorAction>> errorActionEvaluators,
|
||||
final List<RolloutGroupActionEvaluator<RolloutGroup.RolloutGroupSuccessAction>> successActionEvaluators) {
|
||||
return new RolloutGroupEvaluationManager(errorConditionEvaluators, successConditionEvaluators,
|
||||
errorActionEvaluators, successActionEvaluators);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
SystemManagementCacheKeyGenerator systemManagementCacheKeyGenerator() {
|
||||
@@ -660,6 +674,14 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
return new JpaSoftwareModuleTypeManagement(distributionSetTypeRepository, softwareModuleTypeRepository,
|
||||
virtualPropertyReplacer, softwareModuleRepository, properties.getDatabase());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
RolloutHandler rolloutHandler(final TenantAware tenantAware, final RolloutManagement rolloutManagement,
|
||||
final RolloutExecutor rolloutExecutor, final LockRegistry lockRegistry,
|
||||
final PlatformTransactionManager txManager) {
|
||||
return new JpaRolloutHandler(tenantAware, rolloutManagement, rolloutExecutor, lockRegistry, txManager);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@@ -670,25 +692,25 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
final RolloutGroupManagement rolloutGroupManagement, final QuotaManagement quotaManagement,
|
||||
final DeploymentManagement deploymentManagement, final TargetManagement targetManagement,
|
||||
final EventPublisherHolder eventPublisherHolder, final PlatformTransactionManager txManager,
|
||||
final RolloutApprovalStrategy rolloutApprovalStrategy, final ApplicationContext context) {
|
||||
final RolloutApprovalStrategy rolloutApprovalStrategy,
|
||||
final RolloutGroupEvaluationManager evaluationManager, final RolloutManagement rolloutManagement) {
|
||||
return new JpaRolloutExecutor(rolloutTargetGroupRepository, entityManager, rolloutRepository, actionRepository,
|
||||
rolloutGroupRepository, afterCommit, tenantAware, rolloutGroupManagement, quotaManagement,
|
||||
deploymentManagement, targetManagement, eventPublisherHolder, txManager, rolloutApprovalStrategy,
|
||||
context);
|
||||
evaluationManager, rolloutManagement);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
RolloutManagement rolloutManagement(final TargetManagement targetManagement,
|
||||
final DistributionSetManagement distributionSetManagement, final EventPublisherHolder eventPublisherHolder,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final PlatformTransactionManager txManager,
|
||||
final TenantAware tenantAware, final LockRegistry lockRegistry, final JpaProperties properties,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final JpaProperties properties,
|
||||
final RolloutApprovalStrategy rolloutApprovalStrategy,
|
||||
final TenantConfigurationManagement tenantConfigurationManagement,
|
||||
final SystemSecurityContext systemSecurityContext, final RolloutExecutor rolloutExecutor) {
|
||||
final SystemSecurityContext systemSecurityContext) {
|
||||
return new JpaRolloutManagement(targetManagement, distributionSetManagement, eventPublisherHolder,
|
||||
virtualPropertyReplacer, txManager, tenantAware, lockRegistry, properties.getDatabase(),
|
||||
rolloutApprovalStrategy, tenantConfigurationManagement, systemSecurityContext, rolloutExecutor);
|
||||
virtualPropertyReplacer, properties.getDatabase(), rolloutApprovalStrategy,
|
||||
tenantConfigurationManagement, systemSecurityContext);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -913,7 +935,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
*
|
||||
* @param systemManagement
|
||||
* to find all tenants
|
||||
* @param rolloutManagement
|
||||
* @param rolloutHandler
|
||||
* to run the rollout handler
|
||||
* @param systemSecurityContext
|
||||
* to run as system
|
||||
@@ -924,8 +946,8 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
@Profile("!test")
|
||||
@ConditionalOnProperty(prefix = "hawkbit.rollout.scheduler", name = "enabled", matchIfMissing = true)
|
||||
RolloutScheduler rolloutScheduler(final TenantAware tenantAware, final SystemManagement systemManagement,
|
||||
final RolloutManagement rolloutManagement, final SystemSecurityContext systemSecurityContext) {
|
||||
return new RolloutScheduler(systemManagement, rolloutManagement, systemSecurityContext);
|
||||
final RolloutHandler rolloutHandler, final SystemSecurityContext systemSecurityContext) {
|
||||
return new RolloutScheduler(systemManagement, rolloutHandler, systemSecurityContext);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rollout;
|
||||
|
||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
import org.eclipse.hawkbit.repository.RolloutHandler;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.slf4j.Logger;
|
||||
@@ -16,8 +16,8 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
/**
|
||||
* Scheduler to schedule the {@link RolloutManagement#handleRollouts()}. The
|
||||
* delay between the checks be be configured using the property from
|
||||
* Scheduler to schedule the {@link RolloutHandler#handleAll()}. The
|
||||
* delay between the checks be configured using the property from
|
||||
* {#PROP_SCHEDULER_DELAY_PLACEHOLDER}.
|
||||
*/
|
||||
public class RolloutScheduler {
|
||||
@@ -28,7 +28,7 @@ public class RolloutScheduler {
|
||||
|
||||
private final SystemManagement systemManagement;
|
||||
|
||||
private final RolloutManagement rolloutManagement;
|
||||
private final RolloutHandler rolloutHandler;
|
||||
|
||||
private final SystemSecurityContext systemSecurityContext;
|
||||
|
||||
@@ -37,22 +37,22 @@ public class RolloutScheduler {
|
||||
*
|
||||
* @param systemManagement
|
||||
* to find all tenants
|
||||
* @param rolloutManagement
|
||||
* @param rolloutHandler
|
||||
* to run the rollout handler
|
||||
* @param systemSecurityContext
|
||||
* to run as system
|
||||
*/
|
||||
public RolloutScheduler(final SystemManagement systemManagement, final RolloutManagement rolloutManagement,
|
||||
public RolloutScheduler(final SystemManagement systemManagement, final RolloutHandler rolloutHandler,
|
||||
final SystemSecurityContext systemSecurityContext) {
|
||||
this.systemManagement = systemManagement;
|
||||
this.rolloutManagement = rolloutManagement;
|
||||
this.rolloutHandler = rolloutHandler;
|
||||
this.systemSecurityContext = systemSecurityContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scheduler method called by the spring-async mechanism. Retrieves all
|
||||
* tenants from the {@link SystemManagement#findTenants()} and runs for each
|
||||
* tenant the {@link RolloutManagement#handleRollouts()} in the
|
||||
* tenants from the {@link SystemManagement#findTenants} and runs for each
|
||||
* tenant the {@link RolloutHandler#handleAll()} in the
|
||||
* {@link SystemSecurityContext}.
|
||||
*/
|
||||
@Scheduled(initialDelayString = PROP_SCHEDULER_DELAY_PLACEHOLDER, fixedDelayString = PROP_SCHEDULER_DELAY_PLACEHOLDER)
|
||||
@@ -63,13 +63,13 @@ public class RolloutScheduler {
|
||||
// permission to query and create entities.
|
||||
systemSecurityContext.runAsSystem(() -> {
|
||||
// workaround eclipselink that is currently not possible to
|
||||
// execute a query without multitenancy if MultiTenant
|
||||
// execute a query without multi-tenancy if MultiTenant
|
||||
// annotation is used.
|
||||
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=355458. So
|
||||
// iterate through all tenants and execute the rollout check for
|
||||
// each tenant seperately.
|
||||
|
||||
systemManagement.forEachTenant(tenant -> rolloutManagement.handleRollouts());
|
||||
systemManagement.forEachTenant(tenant -> rolloutHandler.handleAll());
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2023 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rollout.condition;
|
||||
|
||||
/**
|
||||
* Exception indicating that a specific evaluator is missing in the application
|
||||
* context.
|
||||
*/
|
||||
public class EvaluatorNotConfiguredException extends RuntimeException {
|
||||
|
||||
private static final String MESSAGE_FORMAT = "Cannot find any configured evaluator for action/condition '%s'. Please ensure to configure one in the application context to make use of it.";
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param s
|
||||
* the action/condition to evaluate
|
||||
*/
|
||||
public EvaluatorNotConfiguredException(final String s) {
|
||||
super(String.format(MESSAGE_FORMAT, s));
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
* Error action evaluator which pauses the whole {@link Rollout} and sets the
|
||||
* current {@link RolloutGroup} to error.
|
||||
*/
|
||||
public class PauseRolloutGroupAction implements RolloutGroupActionEvaluator {
|
||||
public class PauseRolloutGroupAction implements RolloutGroupActionEvaluator<RolloutGroup.RolloutGroupErrorAction> {
|
||||
|
||||
private final RolloutManagement rolloutManagement;
|
||||
|
||||
@@ -36,12 +36,12 @@ public class PauseRolloutGroupAction implements RolloutGroupActionEvaluator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verifyExpression(final String expression) {
|
||||
return true;
|
||||
public RolloutGroup.RolloutGroupErrorAction getAction() {
|
||||
return RolloutGroup.RolloutGroupErrorAction.PAUSE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eval(final Rollout rollout, final RolloutGroup rolloutG, final String expression) {
|
||||
public void exec(final Rollout rollout, final RolloutGroup rolloutG) {
|
||||
final JpaRolloutGroup rolloutGroup = (JpaRolloutGroup) rolloutG;
|
||||
|
||||
systemSecurityContext.runAsSystem(() -> {
|
||||
|
||||
@@ -12,11 +12,11 @@ import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
|
||||
/**
|
||||
*
|
||||
* Interface to define a specific execution for an action
|
||||
*/
|
||||
public interface RolloutGroupActionEvaluator {
|
||||
public interface RolloutGroupActionEvaluator<T> {
|
||||
|
||||
boolean verifyExpression(final String expression);
|
||||
T getAction();
|
||||
|
||||
void eval(Rollout rollout, RolloutGroup rolloutGroup, final String expression);
|
||||
void exec(Rollout rollout, RolloutGroup rolloutGroup);
|
||||
}
|
||||
|
||||
@@ -12,20 +12,11 @@ import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
|
||||
/**
|
||||
* Verifies {@link RolloutGroup#getErrorConditionExp()}.
|
||||
* Interface for evaluate conditions define for a {@link RolloutGroup} based on a given expression
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface RolloutGroupConditionEvaluator {
|
||||
public interface RolloutGroupConditionEvaluator<T> {
|
||||
|
||||
default boolean verifyExpression(final String expression) {
|
||||
// percentage value between 0 and 100
|
||||
try {
|
||||
final Integer value = Integer.valueOf(expression);
|
||||
return value >= 0 && value <= 100;
|
||||
} catch (final NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
T getCondition();
|
||||
|
||||
boolean eval(Rollout rollout, RolloutGroup rolloutGroup, final String expression);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Copyright (c) 2023 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rollout.condition;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Manager class to collect all instances of
|
||||
* {@link RolloutGroupConditionEvaluator} and
|
||||
* {@link RolloutGroupActionEvaluator} for specific conditions and actions. The
|
||||
* corresponding instance can be fetched by providing the action/condition.
|
||||
*/
|
||||
public class RolloutGroupEvaluationManager {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RolloutGroupEvaluationManager.class);
|
||||
|
||||
private final List<RolloutGroupConditionEvaluator<RolloutGroup.RolloutGroupErrorCondition>> errorConditionEvaluators;
|
||||
private final List<RolloutGroupConditionEvaluator<RolloutGroup.RolloutGroupSuccessCondition>> successConditionEvaluators;
|
||||
private final List<RolloutGroupActionEvaluator<RolloutGroup.RolloutGroupErrorAction>> errorActionEvaluators;
|
||||
private final List<RolloutGroupActionEvaluator<RolloutGroup.RolloutGroupSuccessAction>> successActionEvaluators;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param errorConditionEvaluators
|
||||
* evaluators for instances of {@link RolloutGroupConditionEvaluator}
|
||||
* handling the {@link RolloutGroup.RolloutGroupErrorCondition}
|
||||
* @param successConditionEvaluators
|
||||
* evaluators for instances of {@link RolloutGroupConditionEvaluator}
|
||||
* handling the {@link RolloutGroup.RolloutGroupSuccessCondition}
|
||||
* @param errorActionEvaluators
|
||||
* evaluators for instances of {@link RolloutGroupActionEvaluator}
|
||||
* handling the {@link RolloutGroup.RolloutGroupErrorAction}
|
||||
* @param successActionEvaluators
|
||||
* evaluators for instances of {@link RolloutGroupActionEvaluator}
|
||||
* handling the {@link RolloutGroup.RolloutGroupSuccessAction}
|
||||
*/
|
||||
public RolloutGroupEvaluationManager(
|
||||
final List<RolloutGroupConditionEvaluator<RolloutGroup.RolloutGroupErrorCondition>> errorConditionEvaluators,
|
||||
final List<RolloutGroupConditionEvaluator<RolloutGroup.RolloutGroupSuccessCondition>> successConditionEvaluators,
|
||||
final List<RolloutGroupActionEvaluator<RolloutGroup.RolloutGroupErrorAction>> errorActionEvaluators,
|
||||
final List<RolloutGroupActionEvaluator<RolloutGroup.RolloutGroupSuccessAction>> successActionEvaluators) {
|
||||
this.errorConditionEvaluators = errorConditionEvaluators;
|
||||
this.successConditionEvaluators = successConditionEvaluators;
|
||||
this.errorActionEvaluators = errorActionEvaluators;
|
||||
this.successActionEvaluators = successActionEvaluators;
|
||||
}
|
||||
|
||||
public RolloutGroupActionEvaluator<RolloutGroup.RolloutGroupErrorAction> getErrorActionEvaluator(
|
||||
final RolloutGroup.RolloutGroupErrorAction errorAction) {
|
||||
return findFirstActionEvaluator(errorActionEvaluators, errorAction);
|
||||
|
||||
}
|
||||
|
||||
public RolloutGroupActionEvaluator<RolloutGroup.RolloutGroupSuccessAction> getSuccessActionEvaluator(
|
||||
final RolloutGroup.RolloutGroupSuccessAction successAction) {
|
||||
return findFirstActionEvaluator(successActionEvaluators, successAction);
|
||||
}
|
||||
|
||||
public RolloutGroupConditionEvaluator<RolloutGroup.RolloutGroupErrorCondition> getErrorConditionEvaluator(
|
||||
final RolloutGroup.RolloutGroupErrorCondition errorCondition) {
|
||||
return findFirstConditionEvaluator(errorConditionEvaluators, errorCondition);
|
||||
|
||||
}
|
||||
|
||||
public RolloutGroupConditionEvaluator<RolloutGroup.RolloutGroupSuccessCondition> getSuccessConditionEvaluator(
|
||||
final RolloutGroup.RolloutGroupSuccessCondition successCondition) {
|
||||
return findFirstConditionEvaluator(successConditionEvaluators, successCondition);
|
||||
}
|
||||
|
||||
private static <T extends Enum<T>> RolloutGroupActionEvaluator<T> findFirstActionEvaluator(
|
||||
final List<RolloutGroupActionEvaluator<T>> evaluators, final T action) {
|
||||
return evaluators.stream().filter(evaluator -> evaluator.getAction() == action).findFirst().orElseThrow(() -> {
|
||||
LOGGER.warn("Could not find suitable evaluator for the '{}' action.", action.name());
|
||||
throw new EvaluatorNotConfiguredException(action.name());
|
||||
});
|
||||
}
|
||||
|
||||
private static <T extends Enum<T>> RolloutGroupConditionEvaluator<T> findFirstConditionEvaluator(
|
||||
final List<RolloutGroupConditionEvaluator<T>> evaluators, final T condition) {
|
||||
return evaluators.stream().filter(evaluator -> evaluator.getCondition() == condition).findFirst()
|
||||
.orElseThrow(() -> {
|
||||
LOGGER.warn("Could not find suitable evaluator for the '{}' condition.", condition.name());
|
||||
throw new EvaluatorNotConfiguredException(condition.name());
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import org.slf4j.LoggerFactory;
|
||||
/**
|
||||
* Success action which starts the next following {@link RolloutGroup}.
|
||||
*/
|
||||
public class StartNextGroupRolloutGroupSuccessAction implements RolloutGroupActionEvaluator {
|
||||
public class StartNextGroupRolloutGroupSuccessAction implements RolloutGroupActionEvaluator<RolloutGroup.RolloutGroupSuccessAction> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(StartNextGroupRolloutGroupSuccessAction.class);
|
||||
|
||||
@@ -41,12 +41,12 @@ public class StartNextGroupRolloutGroupSuccessAction implements RolloutGroupActi
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verifyExpression(final String expression) {
|
||||
return true;
|
||||
public RolloutGroup.RolloutGroupSuccessAction getAction() {
|
||||
return RolloutGroup.RolloutGroupSuccessAction.NEXTGROUP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eval(final Rollout rollout, final RolloutGroup rolloutGroup, final String expression) {
|
||||
public void exec(final Rollout rollout, final RolloutGroup rolloutGroup) {
|
||||
systemSecurityContext.runAsSystem(() -> {
|
||||
startNextGroup(rollout, rolloutGroup);
|
||||
return null;
|
||||
|
||||
@@ -18,9 +18,10 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* Evaluates if the {@link RolloutGroup#getErrorConditionExp()} is reached.
|
||||
*/
|
||||
public class ThresholdRolloutGroupErrorCondition implements RolloutGroupConditionEvaluator {
|
||||
public class ThresholdRolloutGroupErrorCondition
|
||||
implements RolloutGroupConditionEvaluator<RolloutGroup.RolloutGroupErrorCondition> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ThresholdRolloutGroupErrorCondition.class);
|
||||
|
||||
@@ -30,6 +31,11 @@ public class ThresholdRolloutGroupErrorCondition implements RolloutGroupConditio
|
||||
this.actionRepository = actionRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RolloutGroup.RolloutGroupErrorCondition getCondition() {
|
||||
return RolloutGroup.RolloutGroupErrorCondition.THRESHOLD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eval(final Rollout rollout, final RolloutGroup rolloutGroup, final String expression) {
|
||||
final Long totalGroup = actionRepository.countByRolloutAndRolloutGroup((JpaRollout) rollout,
|
||||
|
||||
@@ -16,10 +16,11 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Threshold to calculate if rollout group success condition is reached and the
|
||||
* Threshold to calculate if the {@link RolloutGroup#getSuccessConditionExp()} is reached and the
|
||||
* next rollout group can get started.
|
||||
*/
|
||||
public class ThresholdRolloutGroupSuccessCondition implements RolloutGroupConditionEvaluator {
|
||||
public class ThresholdRolloutGroupSuccessCondition
|
||||
implements RolloutGroupConditionEvaluator<RolloutGroup.RolloutGroupSuccessCondition> {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ThresholdRolloutGroupSuccessCondition.class);
|
||||
|
||||
private final ActionRepository actionRepository;
|
||||
@@ -28,6 +29,11 @@ public class ThresholdRolloutGroupSuccessCondition implements RolloutGroupCondit
|
||||
this.actionRepository = actionRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RolloutGroup.RolloutGroupSuccessCondition getCondition() {
|
||||
return RolloutGroup.RolloutGroupSuccessCondition.THRESHOLD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eval(final Rollout rollout, final RolloutGroup rolloutGroup, final String expression) {
|
||||
|
||||
@@ -44,7 +50,7 @@ public class ThresholdRolloutGroupSuccessCondition implements RolloutGroupCondit
|
||||
final long finished = this.actionRepository.countByRolloutIdAndRolloutGroupIdAndStatus(rollout.getId(),
|
||||
rolloutGroup.getId(), completeActionStatus);
|
||||
try {
|
||||
final Integer threshold = Integer.valueOf(expression);
|
||||
final int threshold = Integer.parseInt(expression);
|
||||
// calculate threshold
|
||||
return ((float) finished / (float) totalGroup) >= ((float) threshold / 100F);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user