Reduce probability of ConcurrentModification errors (#505)
* Fix unassign handling for tags. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Batch writes. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Activate retry on DB concurrency exceptions. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Code format, constants. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
@@ -71,9 +71,9 @@ public interface DistributionSetTagRepository
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
||||||
* reasons (this is a "delete everything" query after all) we add the tenant manually to
|
* reasons (this is a "delete everything" query after all) we add the tenant
|
||||||
* query even if this will by done by {@link EntityManager} anyhow. The DB
|
* manually to query even if this will by done by {@link EntityManager}
|
||||||
* should take care of optimizing this away.
|
* anyhow. The DB should take care of optimizing this away.
|
||||||
*
|
*
|
||||||
* @param tenant
|
* @param tenant
|
||||||
* to delete data from
|
* to delete data from
|
||||||
|
|||||||
@@ -64,9 +64,9 @@ public interface DistributionSetTypeRepository
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
||||||
* reasons (this is a "delete everything" query after all) we add the tenant manually to
|
* reasons (this is a "delete everything" query after all) we add the tenant
|
||||||
* query even if this will by done by {@link EntityManager} anyhow. The DB
|
* manually to query even if this will by done by {@link EntityManager}
|
||||||
* should take care of optimizing this away.
|
* anyhow. The DB should take care of optimizing this away.
|
||||||
*
|
*
|
||||||
* @param tenant
|
* @param tenant
|
||||||
* to delete data from
|
* to delete data from
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
|||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
import org.eclipse.hawkbit.repository.exception.InvalidMD5HashException;
|
import org.eclipse.hawkbit.repository.exception.InvalidMD5HashException;
|
||||||
import org.eclipse.hawkbit.repository.exception.InvalidSHA1HashException;
|
import org.eclipse.hawkbit.repository.exception.InvalidSHA1HashException;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
|
||||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||||
@@ -30,8 +31,11 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.retry.annotation.Backoff;
|
||||||
|
import org.springframework.retry.annotation.Retryable;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
@@ -71,6 +75,8 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Artifact createArtifact(final InputStream stream, final Long moduleId, final String filename,
|
public Artifact createArtifact(final InputStream stream, final Long moduleId, final String filename,
|
||||||
final String providedMd5Sum, final String providedSha1Sum, final boolean overrideExisting,
|
final String providedMd5Sum, final String providedSha1Sum, final boolean overrideExisting,
|
||||||
final String contentType) {
|
final String contentType) {
|
||||||
@@ -101,6 +107,8 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public boolean clearArtifactBinary(final String sha1Hash, final Long moduleId) {
|
public boolean clearArtifactBinary(final String sha1Hash, final Long moduleId) {
|
||||||
|
|
||||||
if (localArtifactRepository.existsWithSha1HashAndSoftwareModuleIdIsNot(sha1Hash, moduleId)) {
|
if (localArtifactRepository.existsWithSha1HashAndSoftwareModuleIdIsNot(sha1Hash, moduleId)) {
|
||||||
@@ -119,6 +127,8 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteArtifact(final Long id) {
|
public void deleteArtifact(final Long id) {
|
||||||
final JpaArtifact existing = (JpaArtifact) findArtifact(id)
|
final JpaArtifact existing = (JpaArtifact) findArtifact(id)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Artifact.class, id));
|
.orElseThrow(() -> new EntityNotFoundException(Artifact.class, id));
|
||||||
@@ -186,6 +196,8 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Artifact createArtifact(final InputStream inputStream, final Long moduleId, final String filename,
|
public Artifact createArtifact(final InputStream inputStream, final Long moduleId, final String filename,
|
||||||
final boolean overrideExisting) {
|
final boolean overrideExisting) {
|
||||||
return createArtifact(inputStream, moduleId, filename, null, null, overrideExisting, null);
|
return createArtifact(inputStream, moduleId, filename, null, null, overrideExisting, null);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
|||||||
import org.eclipse.hawkbit.repository.exception.ToManyAttributeEntriesException;
|
import org.eclipse.hawkbit.repository.exception.ToManyAttributeEntriesException;
|
||||||
import org.eclipse.hawkbit.repository.exception.TooManyStatusEntriesException;
|
import org.eclipse.hawkbit.repository.exception.TooManyStatusEntriesException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusCreate;
|
import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusCreate;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
|
||||||
@@ -56,9 +57,12 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationEventPublisher;
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.data.domain.Sort.Direction;
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
import org.springframework.data.jpa.domain.Specification;
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
|
import org.springframework.retry.annotation.Backoff;
|
||||||
|
import org.springframework.retry.annotation.Retryable;
|
||||||
import org.springframework.transaction.annotation.Isolation;
|
import org.springframework.transaction.annotation.Isolation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@@ -126,6 +130,8 @@ public class JpaControllerManagement implements ControllerManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Target updateLastTargetQuery(final String controllerId, final URI address) {
|
public Target updateLastTargetQuery(final String controllerId, final URI address) {
|
||||||
final JpaTarget target = (JpaTarget) targetRepository.findByControllerId(controllerId)
|
final JpaTarget target = (JpaTarget) targetRepository.findByControllerId(controllerId)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
||||||
@@ -195,6 +201,8 @@ public class JpaControllerManagement implements ControllerManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Target findOrRegisterTargetIfItDoesNotexist(final String controllerId, final URI address) {
|
public Target findOrRegisterTargetIfItDoesNotexist(final String controllerId, final URI address) {
|
||||||
final Specification<JpaTarget> spec = (targetRoot, query, cb) -> cb
|
final Specification<JpaTarget> spec = (targetRoot, query, cb) -> cb
|
||||||
.equal(targetRoot.get(JpaTarget_.controllerId), controllerId);
|
.equal(targetRoot.get(JpaTarget_.controllerId), controllerId);
|
||||||
@@ -240,6 +248,8 @@ public class JpaControllerManagement implements ControllerManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Action addCancelActionStatus(final ActionStatusCreate c) {
|
public Action addCancelActionStatus(final ActionStatusCreate c) {
|
||||||
final JpaActionStatusCreate create = (JpaActionStatusCreate) c;
|
final JpaActionStatusCreate create = (JpaActionStatusCreate) c;
|
||||||
|
|
||||||
@@ -283,6 +293,8 @@ public class JpaControllerManagement implements ControllerManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Action addUpdateActionStatus(final ActionStatusCreate c) {
|
public Action addUpdateActionStatus(final ActionStatusCreate c) {
|
||||||
final JpaActionStatusCreate create = (JpaActionStatusCreate) c;
|
final JpaActionStatusCreate create = (JpaActionStatusCreate) c;
|
||||||
final JpaAction action = getActionAndThrowExceptionIfNotFound(create.getActionId());
|
final JpaAction action = getActionAndThrowExceptionIfNotFound(create.getActionId());
|
||||||
@@ -381,6 +393,8 @@ public class JpaControllerManagement implements ControllerManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Target updateControllerAttributes(final String controllerId, final Map<String, String> data) {
|
public Target updateControllerAttributes(final String controllerId, final Map<String, String> data) {
|
||||||
final JpaTarget target = (JpaTarget) targetRepository.findByControllerId(controllerId)
|
final JpaTarget target = (JpaTarget) targetRepository.findByControllerId(controllerId)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
||||||
@@ -401,6 +415,8 @@ public class JpaControllerManagement implements ControllerManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Action registerRetrieved(final Long actionId, final String message) {
|
public Action registerRetrieved(final Long actionId, final String message) {
|
||||||
return handleRegisterRetrieved(actionId, message);
|
return handleRegisterRetrieved(actionId, message);
|
||||||
}
|
}
|
||||||
@@ -460,6 +476,8 @@ public class JpaControllerManagement implements ControllerManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public ActionStatus addInformationalActionStatus(final ActionStatusCreate c) {
|
public ActionStatus addInformationalActionStatus(final ActionStatusCreate c) {
|
||||||
final JpaActionStatusCreate create = (JpaActionStatusCreate) c;
|
final JpaActionStatusCreate create = (JpaActionStatusCreate) c;
|
||||||
final JpaAction action = getActionAndThrowExceptionIfNotFound(create.getActionId());
|
final JpaAction action = getActionAndThrowExceptionIfNotFound(create.getActionId());
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationEventPublisher;
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
import org.springframework.data.domain.AuditorAware;
|
import org.springframework.data.domain.AuditorAware;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageImpl;
|
import org.springframework.data.domain.PageImpl;
|
||||||
@@ -74,6 +75,8 @@ import org.springframework.data.domain.PageRequest;
|
|||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.domain.Slice;
|
import org.springframework.data.domain.Slice;
|
||||||
import org.springframework.data.jpa.domain.Specification;
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
|
import org.springframework.retry.annotation.Backoff;
|
||||||
|
import org.springframework.retry.annotation.Retryable;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.TransactionDefinition;
|
import org.springframework.transaction.TransactionDefinition;
|
||||||
import org.springframework.transaction.annotation.Isolation;
|
import org.springframework.transaction.annotation.Isolation;
|
||||||
@@ -136,6 +139,8 @@ public class JpaDeploymentManagement implements DeploymentManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
// Exception squid:S2095: see
|
// Exception squid:S2095: see
|
||||||
// https://jira.sonarsource.com/browse/SONARJAVA-1478
|
// https://jira.sonarsource.com/browse/SONARJAVA-1478
|
||||||
@SuppressWarnings({ "squid:S2095" })
|
@SuppressWarnings({ "squid:S2095" })
|
||||||
@@ -147,6 +152,8 @@ public class JpaDeploymentManagement implements DeploymentManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public DistributionSetAssignmentResult assignDistributionSet(final Long dsID,
|
public DistributionSetAssignmentResult assignDistributionSet(final Long dsID,
|
||||||
final Collection<TargetWithActionType> targets) {
|
final Collection<TargetWithActionType> targets) {
|
||||||
return assignDistributionSet(dsID, targets, null);
|
return assignDistributionSet(dsID, targets, null);
|
||||||
@@ -154,6 +161,8 @@ public class JpaDeploymentManagement implements DeploymentManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public DistributionSetAssignmentResult assignDistributionSet(final Long dsID,
|
public DistributionSetAssignmentResult assignDistributionSet(final Long dsID,
|
||||||
final Collection<TargetWithActionType> targets, final String actionMessage) {
|
final Collection<TargetWithActionType> targets, final String actionMessage) {
|
||||||
final JpaDistributionSet set = distributionSetRepository.findOne(dsID);
|
final JpaDistributionSet set = distributionSetRepository.findOne(dsID);
|
||||||
@@ -348,6 +357,8 @@ public class JpaDeploymentManagement implements DeploymentManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Action cancelAction(final Long actionId) {
|
public Action cancelAction(final Long actionId) {
|
||||||
LOG.debug("cancelAction({})", actionId);
|
LOG.debug("cancelAction({})", actionId);
|
||||||
|
|
||||||
@@ -390,6 +401,8 @@ public class JpaDeploymentManagement implements DeploymentManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Action forceQuitAction(final Long actionId) {
|
public Action forceQuitAction(final Long actionId) {
|
||||||
final JpaAction action = actionRepository.findById(actionId)
|
final JpaAction action = actionRepository.findById(actionId)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
||||||
@@ -595,6 +608,8 @@ public class JpaDeploymentManagement implements DeploymentManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Action forceTargetAction(final Long actionId) {
|
public Action forceTargetAction(final Long actionId) {
|
||||||
final JpaAction action = actionRepository.findById(actionId)
|
final JpaAction action = actionRepository.findById(actionId)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
package org.eclipse.hawkbit.repository.jpa;
|
package org.eclipse.hawkbit.repository.jpa;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -36,6 +35,7 @@ import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
|||||||
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
|
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaDistributionSetCreate;
|
import org.eclipse.hawkbit.repository.jpa.builder.JpaDistributionSetCreate;
|
||||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaDistributionSetTypeCreate;
|
import org.eclipse.hawkbit.repository.jpa.builder.JpaDistributionSetTypeCreate;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.DsMetadataCompositeKey;
|
import org.eclipse.hawkbit.repository.jpa.model.DsMetadataCompositeKey;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
|
||||||
@@ -64,10 +64,13 @@ import org.eclipse.hawkbit.tenancy.TenantAware;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationEventPublisher;
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageImpl;
|
import org.springframework.data.domain.PageImpl;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.jpa.domain.Specification;
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
|
import org.springframework.retry.annotation.Backoff;
|
||||||
|
import org.springframework.retry.annotation.Retryable;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@@ -140,6 +143,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public DistributionSetTagAssignmentResult toggleTagAssignment(final Collection<Long> dsIds, final String tagName) {
|
public DistributionSetTagAssignmentResult toggleTagAssignment(final Collection<Long> dsIds, final String tagName) {
|
||||||
final List<JpaDistributionSet> sets = findDistributionSetListWithDetails(dsIds);
|
final List<JpaDistributionSet> sets = findDistributionSetListWithDetails(dsIds);
|
||||||
|
|
||||||
@@ -187,6 +192,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public DistributionSet updateDistributionSet(final DistributionSetUpdate u) {
|
public DistributionSet updateDistributionSet(final DistributionSetUpdate u) {
|
||||||
final GenericDistributionSetUpdate update = (GenericDistributionSetUpdate) u;
|
final GenericDistributionSetUpdate update = (GenericDistributionSetUpdate) u;
|
||||||
|
|
||||||
@@ -237,6 +244,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteDistributionSet(final Collection<Long> distributionSetIDs) {
|
public void deleteDistributionSet(final Collection<Long> distributionSetIDs) {
|
||||||
final List<DistributionSet> setsFound = findDistributionSetsById(distributionSetIDs);
|
final List<DistributionSet> setsFound = findDistributionSetsById(distributionSetIDs);
|
||||||
|
|
||||||
@@ -274,6 +283,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public DistributionSet createDistributionSet(final DistributionSetCreate c) {
|
public DistributionSet createDistributionSet(final DistributionSetCreate c) {
|
||||||
final JpaDistributionSetCreate create = (JpaDistributionSetCreate) c;
|
final JpaDistributionSetCreate create = (JpaDistributionSetCreate) c;
|
||||||
if (create.getType() == null) {
|
if (create.getType() == null) {
|
||||||
@@ -285,12 +296,16 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public List<DistributionSet> createDistributionSets(final Collection<DistributionSetCreate> creates) {
|
public List<DistributionSet> createDistributionSets(final Collection<DistributionSetCreate> creates) {
|
||||||
return creates.stream().map(this::createDistributionSet).collect(Collectors.toList());
|
return creates.stream().map(this::createDistributionSet).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public DistributionSet assignSoftwareModules(final Long setId, final Collection<Long> moduleIds) {
|
public DistributionSet assignSoftwareModules(final Long setId, final Collection<Long> moduleIds) {
|
||||||
|
|
||||||
final Collection<JpaSoftwareModule> modules = softwareModuleRepository.findByIdIn(moduleIds);
|
final Collection<JpaSoftwareModule> modules = softwareModuleRepository.findByIdIn(moduleIds);
|
||||||
@@ -310,6 +325,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public DistributionSet unassignSoftwareModule(final Long setId, final Long moduleId) {
|
public DistributionSet unassignSoftwareModule(final Long setId, final Long moduleId) {
|
||||||
final JpaDistributionSet set = findDistributionSetAndThrowExceptionIfNotFound(setId);
|
final JpaDistributionSet set = findDistributionSetAndThrowExceptionIfNotFound(setId);
|
||||||
final JpaSoftwareModule module = findSoftwareModuleAndThrowExceptionIfNotFound(moduleId);
|
final JpaSoftwareModule module = findSoftwareModuleAndThrowExceptionIfNotFound(moduleId);
|
||||||
@@ -323,6 +340,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public DistributionSetType updateDistributionSetType(final DistributionSetTypeUpdate u) {
|
public DistributionSetType updateDistributionSetType(final DistributionSetTypeUpdate u) {
|
||||||
final GenericDistributionSetTypeUpdate update = (GenericDistributionSetTypeUpdate) u;
|
final GenericDistributionSetTypeUpdate update = (GenericDistributionSetTypeUpdate) u;
|
||||||
|
|
||||||
@@ -349,6 +368,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public DistributionSetType assignMandatorySoftwareModuleTypes(final Long dsTypeId,
|
public DistributionSetType assignMandatorySoftwareModuleTypes(final Long dsTypeId,
|
||||||
final Collection<Long> softwareModulesTypeIds) {
|
final Collection<Long> softwareModulesTypeIds) {
|
||||||
final Collection<JpaSoftwareModuleType> modules = softwareModuleTypeRepository
|
final Collection<JpaSoftwareModuleType> modules = softwareModuleTypeRepository
|
||||||
@@ -369,6 +390,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public DistributionSetType assignOptionalSoftwareModuleTypes(final Long dsTypeId,
|
public DistributionSetType assignOptionalSoftwareModuleTypes(final Long dsTypeId,
|
||||||
final Collection<Long> softwareModulesTypeIds) {
|
final Collection<Long> softwareModulesTypeIds) {
|
||||||
|
|
||||||
@@ -397,6 +420,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public DistributionSetType unassignSoftwareModuleType(final Long dsTypeId, final Long softwareModuleTypeId) {
|
public DistributionSetType unassignSoftwareModuleType(final Long dsTypeId, final Long softwareModuleTypeId) {
|
||||||
final JpaDistributionSetType type = findDistributionSetTypeAndThrowExceptionIfNotFound(dsTypeId);
|
final JpaDistributionSetType type = findDistributionSetTypeAndThrowExceptionIfNotFound(dsTypeId);
|
||||||
|
|
||||||
@@ -581,6 +606,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public DistributionSetType createDistributionSetType(final DistributionSetTypeCreate c) {
|
public DistributionSetType createDistributionSetType(final DistributionSetTypeCreate c) {
|
||||||
final JpaDistributionSetTypeCreate create = (JpaDistributionSetTypeCreate) c;
|
final JpaDistributionSetTypeCreate create = (JpaDistributionSetTypeCreate) c;
|
||||||
|
|
||||||
@@ -589,6 +616,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteDistributionSetType(final Long typeId) {
|
public void deleteDistributionSetType(final Long typeId) {
|
||||||
|
|
||||||
final JpaDistributionSetType toDelete = distributionSetTypeRepository.findById(typeId)
|
final JpaDistributionSetType toDelete = distributionSetTypeRepository.findById(typeId)
|
||||||
@@ -604,6 +633,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public List<DistributionSetMetadata> createDistributionSetMetadata(final Long dsId, final Collection<MetaData> md) {
|
public List<DistributionSetMetadata> createDistributionSetMetadata(final Long dsId, final Collection<MetaData> md) {
|
||||||
|
|
||||||
md.forEach(meta -> checkAndThrowAlreadyIfDistributionSetMetadataExists(
|
md.forEach(meta -> checkAndThrowAlreadyIfDistributionSetMetadataExists(
|
||||||
@@ -619,6 +650,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public DistributionSetMetadata updateDistributionSetMetadata(final Long dsId, final MetaData md) {
|
public DistributionSetMetadata updateDistributionSetMetadata(final Long dsId, final MetaData md) {
|
||||||
|
|
||||||
// check if exists otherwise throw entity not found exception
|
// check if exists otherwise throw entity not found exception
|
||||||
@@ -634,6 +667,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteDistributionSetMetadata(final Long distributionSetId, final String key) {
|
public void deleteDistributionSetMetadata(final Long distributionSetId, final String key) {
|
||||||
final JpaDistributionSetMetadata metadata = (JpaDistributionSetMetadata) findDistributionSetMetadata(
|
final JpaDistributionSetMetadata metadata = (JpaDistributionSetMetadata) findDistributionSetMetadata(
|
||||||
distributionSetId, key).orElseThrow(
|
distributionSetId, key).orElseThrow(
|
||||||
@@ -818,6 +853,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public List<DistributionSet> assignTag(final Collection<Long> dsIds, final Long dsTagId) {
|
public List<DistributionSet> assignTag(final Collection<Long> dsIds, final Long dsTagId) {
|
||||||
final List<JpaDistributionSet> allDs = findDistributionSetListWithDetails(dsIds);
|
final List<JpaDistributionSet> allDs = findDistributionSetListWithDetails(dsIds);
|
||||||
|
|
||||||
@@ -831,41 +868,46 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
|
|
||||||
allDs.forEach(ds -> ds.addTag(distributionSetTag));
|
allDs.forEach(ds -> ds.addTag(distributionSetTag));
|
||||||
|
|
||||||
return Collections
|
final List<DistributionSet> result = Collections
|
||||||
.unmodifiableList(allDs.stream().map(distributionSetRepository::save).collect(Collectors.toList()));
|
.unmodifiableList(allDs.stream().map(distributionSetRepository::save).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
// No reason to save the tag
|
||||||
|
entityManager.detach(distributionSetTag);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public DistributionSet unAssignTag(final Long dsId, final Long dsTagId) {
|
public DistributionSet unAssignTag(final Long dsId, final Long dsTagId) {
|
||||||
final List<JpaDistributionSet> allDs = findDistributionSetListWithDetails(Arrays.asList(dsId));
|
final JpaDistributionSet set = (JpaDistributionSet) findDistributionSetByIdWithDetails(dsId)
|
||||||
|
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, dsId));
|
||||||
if (allDs.isEmpty()) {
|
|
||||||
throw new EntityNotFoundException(DistributionSet.class, dsId);
|
|
||||||
}
|
|
||||||
|
|
||||||
final DistributionSetTag distributionSetTag = tagManagement.findDistributionSetTagById(dsTagId)
|
final DistributionSetTag distributionSetTag = tagManagement.findDistributionSetTagById(dsTagId)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, dsTagId));
|
.orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, dsTagId));
|
||||||
final List<JpaDistributionSet> unAssignTag = unAssignTag(allDs, distributionSetTag);
|
|
||||||
return unAssignTag.isEmpty() ? null : unAssignTag.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<JpaDistributionSet> unAssignTag(final Collection<JpaDistributionSet> distributionSets,
|
set.removeTag(distributionSetTag);
|
||||||
final DistributionSetTag tag) {
|
|
||||||
distributionSets.forEach(ds -> ds.removeTag(tag));
|
final JpaDistributionSet result = distributionSetRepository.save(set);
|
||||||
return Collections.unmodifiableList(
|
|
||||||
distributionSets.stream().map(distributionSetRepository::save).collect(Collectors.toList()));
|
// No reason to save the tag
|
||||||
|
entityManager.detach(distributionSetTag);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public List<DistributionSetType> createDistributionSetTypes(final Collection<DistributionSetTypeCreate> types) {
|
public List<DistributionSetType> createDistributionSetTypes(final Collection<DistributionSetTypeCreate> types) {
|
||||||
|
|
||||||
return types.stream().map(this::createDistributionSetType).collect(Collectors.toList());
|
return types.stream().map(this::createDistributionSetType).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteDistributionSet(final Long setId) {
|
public void deleteDistributionSet(final Long setId) {
|
||||||
throwExceptionIfDistributionSetDoesNotExist(setId);
|
throwExceptionIfDistributionSetDoesNotExist(setId);
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import org.eclipse.hawkbit.repository.exception.ConstraintViolationException;
|
|||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
|
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
|
||||||
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
|
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
|
||||||
@@ -74,6 +75,7 @@ import org.springframework.beans.BeansException;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationEventPublisher;
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
@@ -82,6 +84,8 @@ import org.springframework.data.domain.Sort;
|
|||||||
import org.springframework.data.domain.Sort.Direction;
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
import org.springframework.data.jpa.domain.Specification;
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
import org.springframework.integration.support.locks.LockRegistry;
|
import org.springframework.integration.support.locks.LockRegistry;
|
||||||
|
import org.springframework.retry.annotation.Backoff;
|
||||||
|
import org.springframework.retry.annotation.Retryable;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.scheduling.annotation.AsyncResult;
|
import org.springframework.scheduling.annotation.AsyncResult;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
@@ -179,6 +183,8 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Rollout createRollout(final RolloutCreate rollout, final int amountGroup,
|
public Rollout createRollout(final RolloutCreate rollout, final int amountGroup,
|
||||||
final RolloutGroupConditions conditions) {
|
final RolloutGroupConditions conditions) {
|
||||||
RolloutHelper.verifyRolloutGroupParameter(amountGroup, quotaManagement);
|
RolloutHelper.verifyRolloutGroupParameter(amountGroup, quotaManagement);
|
||||||
@@ -188,6 +194,8 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Rollout createRollout(final RolloutCreate rollout, final List<RolloutGroupCreate> groups,
|
public Rollout createRollout(final RolloutCreate rollout, final List<RolloutGroupCreate> groups,
|
||||||
final RolloutGroupConditions conditions) {
|
final RolloutGroupConditions conditions) {
|
||||||
RolloutHelper.verifyRolloutGroupParameter(groups.size(), quotaManagement);
|
RolloutHelper.verifyRolloutGroupParameter(groups.size(), quotaManagement);
|
||||||
@@ -422,6 +430,8 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Rollout startRollout(final Long rolloutId) {
|
public Rollout startRollout(final Long rolloutId) {
|
||||||
LOGGER.debug("startRollout called for rollout {}", rolloutId);
|
LOGGER.debug("startRollout called for rollout {}", rolloutId);
|
||||||
|
|
||||||
@@ -552,6 +562,8 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void pauseRollout(final Long rolloutId) {
|
public void pauseRollout(final Long rolloutId) {
|
||||||
final JpaRollout rollout = getRolloutAndThrowExceptionIfNotFound(rolloutId);
|
final JpaRollout rollout = getRolloutAndThrowExceptionIfNotFound(rolloutId);
|
||||||
if (!RolloutStatus.RUNNING.equals(rollout.getStatus())) {
|
if (!RolloutStatus.RUNNING.equals(rollout.getStatus())) {
|
||||||
@@ -569,6 +581,8 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void resumeRollout(final Long rolloutId) {
|
public void resumeRollout(final Long rolloutId) {
|
||||||
final JpaRollout rollout = getRolloutAndThrowExceptionIfNotFound(rolloutId);
|
final JpaRollout rollout = getRolloutAndThrowExceptionIfNotFound(rolloutId);
|
||||||
if (!(RolloutStatus.PAUSED.equals(rollout.getStatus()))) {
|
if (!(RolloutStatus.PAUSED.equals(rollout.getStatus()))) {
|
||||||
@@ -795,6 +809,8 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteRollout(final long rolloutId) {
|
public void deleteRollout(final long rolloutId) {
|
||||||
final JpaRollout jpaRollout = rolloutRepository.findOne(rolloutId);
|
final JpaRollout jpaRollout = rolloutRepository.findOne(rolloutId);
|
||||||
|
|
||||||
@@ -903,6 +919,8 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Rollout updateRollout(final RolloutUpdate u) {
|
public Rollout updateRollout(final RolloutUpdate u) {
|
||||||
final GenericRolloutUpdate update = (GenericRolloutUpdate) u;
|
final GenericRolloutUpdate update = (GenericRolloutUpdate) u;
|
||||||
final JpaRollout rollout = getRolloutAndThrowExceptionIfNotFound(update.getId());
|
final JpaRollout rollout = getRolloutAndThrowExceptionIfNotFound(update.getId());
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
|||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleCreate;
|
import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleCreate;
|
||||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleTypeCreate;
|
import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleTypeCreate;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
|
||||||
@@ -62,6 +63,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
|
|||||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
import org.springframework.data.domain.AuditorAware;
|
import org.springframework.data.domain.AuditorAware;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageImpl;
|
import org.springframework.data.domain.PageImpl;
|
||||||
@@ -69,6 +71,8 @@ import org.springframework.data.domain.Pageable;
|
|||||||
import org.springframework.data.domain.Slice;
|
import org.springframework.data.domain.Slice;
|
||||||
import org.springframework.data.domain.SliceImpl;
|
import org.springframework.data.domain.SliceImpl;
|
||||||
import org.springframework.data.jpa.domain.Specification;
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
|
import org.springframework.retry.annotation.Backoff;
|
||||||
|
import org.springframework.retry.annotation.Retryable;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@@ -117,6 +121,8 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public SoftwareModule updateSoftwareModule(final SoftwareModuleUpdate u) {
|
public SoftwareModule updateSoftwareModule(final SoftwareModuleUpdate u) {
|
||||||
final GenericSoftwareModuleUpdate update = (GenericSoftwareModuleUpdate) u;
|
final GenericSoftwareModuleUpdate update = (GenericSoftwareModuleUpdate) u;
|
||||||
|
|
||||||
@@ -131,6 +137,8 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public SoftwareModuleType updateSoftwareModuleType(final SoftwareModuleTypeUpdate u) {
|
public SoftwareModuleType updateSoftwareModuleType(final SoftwareModuleTypeUpdate u) {
|
||||||
final GenericSoftwareModuleTypeUpdate update = (GenericSoftwareModuleTypeUpdate) u;
|
final GenericSoftwareModuleTypeUpdate update = (GenericSoftwareModuleTypeUpdate) u;
|
||||||
|
|
||||||
@@ -145,6 +153,8 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public SoftwareModule createSoftwareModule(final SoftwareModuleCreate c) {
|
public SoftwareModule createSoftwareModule(final SoftwareModuleCreate c) {
|
||||||
final JpaSoftwareModuleCreate create = (JpaSoftwareModuleCreate) c;
|
final JpaSoftwareModuleCreate create = (JpaSoftwareModuleCreate) c;
|
||||||
|
|
||||||
@@ -153,6 +163,8 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public List<SoftwareModule> createSoftwareModule(final Collection<SoftwareModuleCreate> swModules) {
|
public List<SoftwareModule> createSoftwareModule(final Collection<SoftwareModuleCreate> swModules) {
|
||||||
return swModules.stream().map(this::createSoftwareModule).collect(Collectors.toList());
|
return swModules.stream().map(this::createSoftwareModule).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
@@ -225,6 +237,8 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteSoftwareModules(final Collection<Long> ids) {
|
public void deleteSoftwareModules(final Collection<Long> ids) {
|
||||||
final List<JpaSoftwareModule> swModulesToDelete = softwareModuleRepository.findByIdIn(ids);
|
final List<JpaSoftwareModule> swModulesToDelete = softwareModuleRepository.findByIdIn(ids);
|
||||||
|
|
||||||
@@ -483,6 +497,8 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public SoftwareModuleType createSoftwareModuleType(final SoftwareModuleTypeCreate c) {
|
public SoftwareModuleType createSoftwareModuleType(final SoftwareModuleTypeCreate c) {
|
||||||
final JpaSoftwareModuleTypeCreate create = (JpaSoftwareModuleTypeCreate) c;
|
final JpaSoftwareModuleTypeCreate create = (JpaSoftwareModuleTypeCreate) c;
|
||||||
|
|
||||||
@@ -491,6 +507,8 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteSoftwareModuleType(final Long typeId) {
|
public void deleteSoftwareModuleType(final Long typeId) {
|
||||||
final JpaSoftwareModuleType toDelete = softwareModuleTypeRepository.findById(typeId)
|
final JpaSoftwareModuleType toDelete = softwareModuleTypeRepository.findById(typeId)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(SoftwareModuleType.class, typeId));
|
.orElseThrow(() -> new EntityNotFoundException(SoftwareModuleType.class, typeId));
|
||||||
@@ -515,6 +533,8 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public SoftwareModuleMetadata createSoftwareModuleMetadata(final Long moduleId, final MetaData md) {
|
public SoftwareModuleMetadata createSoftwareModuleMetadata(final Long moduleId, final MetaData md) {
|
||||||
|
|
||||||
checkAndThrowAlreadyIfSoftwareModuleMetadataExists(moduleId, md);
|
checkAndThrowAlreadyIfSoftwareModuleMetadataExists(moduleId, md);
|
||||||
@@ -531,6 +551,8 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public List<SoftwareModuleMetadata> createSoftwareModuleMetadata(final Long moduleId,
|
public List<SoftwareModuleMetadata> createSoftwareModuleMetadata(final Long moduleId,
|
||||||
final Collection<MetaData> md) {
|
final Collection<MetaData> md) {
|
||||||
md.forEach(meta -> checkAndThrowAlreadyIfSoftwareModuleMetadataExists(moduleId, meta));
|
md.forEach(meta -> checkAndThrowAlreadyIfSoftwareModuleMetadataExists(moduleId, meta));
|
||||||
@@ -545,6 +567,8 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public SoftwareModuleMetadata updateSoftwareModuleMetadata(final Long moduleId, final MetaData md) {
|
public SoftwareModuleMetadata updateSoftwareModuleMetadata(final Long moduleId, final MetaData md) {
|
||||||
|
|
||||||
// check if exists otherwise throw entity not found exception
|
// check if exists otherwise throw entity not found exception
|
||||||
@@ -589,6 +613,8 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteSoftwareModuleMetadata(final Long moduleId, final String key) {
|
public void deleteSoftwareModuleMetadata(final Long moduleId, final String key) {
|
||||||
final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) findSoftwareModuleMetadata(moduleId, key)
|
final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) findSoftwareModuleMetadata(moduleId, key)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(SoftwareModuleMetadata.class, moduleId, key));
|
.orElseThrow(() -> new EntityNotFoundException(SoftwareModuleMetadata.class, moduleId, key));
|
||||||
@@ -653,12 +679,16 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteSoftwareModule(final Long moduleId) {
|
public void deleteSoftwareModule(final Long moduleId) {
|
||||||
deleteSoftwareModules(Sets.newHashSet(moduleId));
|
deleteSoftwareModules(Sets.newHashSet(moduleId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public List<SoftwareModuleType> createSoftwareModuleType(final Collection<SoftwareModuleTypeCreate> creates) {
|
public List<SoftwareModuleType> createSoftwareModuleType(final Collection<SoftwareModuleTypeCreate> creates) {
|
||||||
return creates.stream().map(this::createSoftwareModuleType).collect(Collectors.toList());
|
return creates.stream().map(this::createSoftwareModuleType).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ import java.util.stream.Collectors;
|
|||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.cache.TenancyCacheManager;
|
import org.eclipse.hawkbit.cache.TenancyCacheManager;
|
||||||
import org.eclipse.hawkbit.repository.Constants;
|
|
||||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||||
import org.eclipse.hawkbit.repository.TenantStatsManagement;
|
import org.eclipse.hawkbit.repository.TenantStatsManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||||
import org.eclipse.hawkbit.repository.jpa.configuration.MultiTenantJpaTransactionManager;
|
import org.eclipse.hawkbit.repository.jpa.configuration.MultiTenantJpaTransactionManager;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
|
||||||
@@ -34,10 +34,13 @@ import org.eclipse.persistence.config.PersistenceUnitProperties;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
import org.springframework.cache.interceptor.KeyGenerator;
|
import org.springframework.cache.interceptor.KeyGenerator;
|
||||||
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageImpl;
|
import org.springframework.data.domain.PageImpl;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.retry.annotation.Backoff;
|
||||||
|
import org.springframework.retry.annotation.Retryable;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.TransactionDefinition;
|
import org.springframework.transaction.TransactionDefinition;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
@@ -211,6 +214,8 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteTenant(final String t) {
|
public void deleteTenant(final String t) {
|
||||||
final String tenant = t.toUpperCase();
|
final String tenant = t.toUpperCase();
|
||||||
cacheManager.evictCaches(tenant);
|
cacheManager.evictCaches(tenant);
|
||||||
@@ -254,6 +259,8 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public TenantMetaData updateTenantMetadata(final Long defaultDsType) {
|
public TenantMetaData updateTenantMetadata(final Long defaultDsType) {
|
||||||
final JpaTenantMetaData data = (JpaTenantMetaData) getTenantMetadata();
|
final JpaTenantMetaData data = (JpaTenantMetaData) getTenantMetadata();
|
||||||
|
|
||||||
@@ -264,20 +271,26 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
|||||||
|
|
||||||
private DistributionSetType createStandardSoftwareDataSetup() {
|
private DistributionSetType createStandardSoftwareDataSetup() {
|
||||||
final SoftwareModuleType app = softwareModuleTypeRepository
|
final SoftwareModuleType app = softwareModuleTypeRepository
|
||||||
.save(new JpaSoftwareModuleType(Constants.SMT_DEFAULT_APP_KEY, Constants.SMT_DEFAULT_APP_NAME,
|
.save(new JpaSoftwareModuleType(org.eclipse.hawkbit.repository.Constants.SMT_DEFAULT_APP_KEY,
|
||||||
"Application Addons", Integer.MAX_VALUE));
|
org.eclipse.hawkbit.repository.Constants.SMT_DEFAULT_APP_NAME, "Application Addons",
|
||||||
|
Integer.MAX_VALUE));
|
||||||
final SoftwareModuleType os = softwareModuleTypeRepository.save(new JpaSoftwareModuleType(
|
final SoftwareModuleType os = softwareModuleTypeRepository.save(new JpaSoftwareModuleType(
|
||||||
Constants.SMT_DEFAULT_OS_KEY, Constants.SMT_DEFAULT_OS_NAME, "Core firmware or operationg system", 1));
|
org.eclipse.hawkbit.repository.Constants.SMT_DEFAULT_OS_KEY,
|
||||||
|
org.eclipse.hawkbit.repository.Constants.SMT_DEFAULT_OS_NAME, "Core firmware or operationg system", 1));
|
||||||
|
|
||||||
// make sure the module types get their IDs
|
// make sure the module types get their IDs
|
||||||
entityManager.flush();
|
entityManager.flush();
|
||||||
|
|
||||||
distributionSetTypeRepository.save(new JpaDistributionSetType(Constants.DST_DEFAULT_OS_ONLY_KEY,
|
distributionSetTypeRepository
|
||||||
Constants.DST_DEFAULT_OS_ONLY_NAME, "Default type with Firmware/OS only.").addMandatoryModuleType(os));
|
.save(new JpaDistributionSetType(org.eclipse.hawkbit.repository.Constants.DST_DEFAULT_OS_ONLY_KEY,
|
||||||
|
org.eclipse.hawkbit.repository.Constants.DST_DEFAULT_OS_ONLY_NAME,
|
||||||
|
"Default type with Firmware/OS only.").addMandatoryModuleType(os));
|
||||||
|
|
||||||
return distributionSetTypeRepository.save(new JpaDistributionSetType(Constants.DST_DEFAULT_OS_WITH_APPS_KEY,
|
return distributionSetTypeRepository
|
||||||
Constants.DST_DEFAULT_OS_WITH_APPS_NAME, "Default type with Firmware/OS and optional app(s).")
|
.save(new JpaDistributionSetType(org.eclipse.hawkbit.repository.Constants.DST_DEFAULT_OS_WITH_APPS_KEY,
|
||||||
.addMandatoryModuleType(os).addOptionalModuleType(app));
|
org.eclipse.hawkbit.repository.Constants.DST_DEFAULT_OS_WITH_APPS_NAME,
|
||||||
|
"Default type with Firmware/OS and optional app(s).").addMandatoryModuleType(os)
|
||||||
|
.addOptionalModuleType(app));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import org.eclipse.hawkbit.repository.builder.TagCreate;
|
|||||||
import org.eclipse.hawkbit.repository.builder.TagUpdate;
|
import org.eclipse.hawkbit.repository.builder.TagUpdate;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaTagCreate;
|
import org.eclipse.hawkbit.repository.jpa.builder.JpaTagCreate;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
|
||||||
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
|
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
|
||||||
@@ -31,10 +32,13 @@ import org.eclipse.hawkbit.repository.model.Target;
|
|||||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageImpl;
|
import org.springframework.data.domain.PageImpl;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.jpa.domain.Specification;
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
|
import org.springframework.retry.annotation.Backoff;
|
||||||
|
import org.springframework.retry.annotation.Retryable;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
@@ -68,6 +72,8 @@ public class JpaTagManagement implements TagManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public TargetTag createTargetTag(final TagCreate c) {
|
public TargetTag createTargetTag(final TagCreate c) {
|
||||||
final JpaTagCreate create = (JpaTagCreate) c;
|
final JpaTagCreate create = (JpaTagCreate) c;
|
||||||
|
|
||||||
@@ -76,6 +82,8 @@ public class JpaTagManagement implements TagManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public List<TargetTag> createTargetTags(final Collection<TagCreate> tt) {
|
public List<TargetTag> createTargetTags(final Collection<TagCreate> tt) {
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
final Collection<JpaTagCreate> targetTags = (Collection) tt;
|
final Collection<JpaTagCreate> targetTags = (Collection) tt;
|
||||||
@@ -86,6 +94,8 @@ public class JpaTagManagement implements TagManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteTargetTag(final String targetTagName) {
|
public void deleteTargetTag(final String targetTagName) {
|
||||||
if (!targetTagRepository.existsByName(targetTagName)) {
|
if (!targetTagRepository.existsByName(targetTagName)) {
|
||||||
throw new EntityNotFoundException(TargetTag.class, targetTagName);
|
throw new EntityNotFoundException(TargetTag.class, targetTagName);
|
||||||
@@ -118,6 +128,8 @@ public class JpaTagManagement implements TagManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public TargetTag updateTargetTag(final TagUpdate u) {
|
public TargetTag updateTargetTag(final TagUpdate u) {
|
||||||
final GenericTagUpdate update = (GenericTagUpdate) u;
|
final GenericTagUpdate update = (GenericTagUpdate) u;
|
||||||
|
|
||||||
@@ -132,8 +144,9 @@ public class JpaTagManagement implements TagManagement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public DistributionSetTag updateDistributionSetTag(final TagUpdate u) {
|
public DistributionSetTag updateDistributionSetTag(final TagUpdate u) {
|
||||||
final GenericTagUpdate update = (GenericTagUpdate) u;
|
final GenericTagUpdate update = (GenericTagUpdate) u;
|
||||||
|
|
||||||
@@ -154,6 +167,8 @@ public class JpaTagManagement implements TagManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public DistributionSetTag createDistributionSetTag(final TagCreate c) {
|
public DistributionSetTag createDistributionSetTag(final TagCreate c) {
|
||||||
final JpaTagCreate create = (JpaTagCreate) c;
|
final JpaTagCreate create = (JpaTagCreate) c;
|
||||||
return distributionSetTagRepository.save(create.buildDistributionSetTag());
|
return distributionSetTagRepository.save(create.buildDistributionSetTag());
|
||||||
@@ -161,6 +176,8 @@ public class JpaTagManagement implements TagManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public List<DistributionSetTag> createDistributionSetTags(final Collection<TagCreate> dst) {
|
public List<DistributionSetTag> createDistributionSetTags(final Collection<TagCreate> dst) {
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
@@ -173,6 +190,8 @@ public class JpaTagManagement implements TagManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteDistributionSetTag(final String tagName) {
|
public void deleteDistributionSetTag(final String tagName) {
|
||||||
if (!distributionSetTagRepository.existsByName(tagName)) {
|
if (!distributionSetTagRepository.existsByName(tagName)) {
|
||||||
throw new EntityNotFoundException(DistributionSetTag.class, tagName);
|
throw new EntityNotFoundException(DistributionSetTag.class, tagName);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate;
|
|||||||
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryUpdate;
|
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryUpdate;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetFilterQueryCreate;
|
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetFilterQueryCreate;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery;
|
||||||
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
|
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
|
||||||
@@ -31,11 +32,14 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
|
|||||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageImpl;
|
import org.springframework.data.domain.PageImpl;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.jpa.domain.Specification;
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
import org.springframework.data.jpa.domain.Specifications;
|
import org.springframework.data.jpa.domain.Specifications;
|
||||||
|
import org.springframework.retry.annotation.Backoff;
|
||||||
|
import org.springframework.retry.annotation.Retryable;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
@@ -65,8 +69,10 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
|||||||
this.distributionSetManagement = distributionSetManagement;
|
this.distributionSetManagement = distributionSetManagement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public TargetFilterQuery createTargetFilterQuery(final TargetFilterQueryCreate c) {
|
public TargetFilterQuery createTargetFilterQuery(final TargetFilterQueryCreate c) {
|
||||||
final JpaTargetFilterQueryCreate create = (JpaTargetFilterQueryCreate) c;
|
final JpaTargetFilterQueryCreate create = (JpaTargetFilterQueryCreate) c;
|
||||||
|
|
||||||
@@ -75,6 +81,8 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteTargetFilterQuery(final Long targetFilterQueryId) {
|
public void deleteTargetFilterQuery(final Long targetFilterQueryId) {
|
||||||
findTargetFilterQueryById(targetFilterQueryId)
|
findTargetFilterQueryById(targetFilterQueryId)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId));
|
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId));
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent;
|
|||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetCreate;
|
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetCreate;
|
||||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetUpdate;
|
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetUpdate;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
|
||||||
@@ -55,12 +56,15 @@ import org.eclipse.hawkbit.tenancy.TenantAware;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationEventPublisher;
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageImpl;
|
import org.springframework.data.domain.PageImpl;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.domain.Slice;
|
import org.springframework.data.domain.Slice;
|
||||||
import org.springframework.data.domain.SliceImpl;
|
import org.springframework.data.domain.SliceImpl;
|
||||||
import org.springframework.data.jpa.domain.Specification;
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
|
import org.springframework.retry.annotation.Backoff;
|
||||||
|
import org.springframework.retry.annotation.Retryable;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
@@ -149,6 +153,8 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Target updateTarget(final TargetUpdate u) {
|
public Target updateTarget(final TargetUpdate u) {
|
||||||
final JpaTargetUpdate update = (JpaTargetUpdate) u;
|
final JpaTargetUpdate update = (JpaTargetUpdate) u;
|
||||||
|
|
||||||
@@ -165,6 +171,8 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteTargets(final Collection<Long> targetIDs) {
|
public void deleteTargets(final Collection<Long> targetIDs) {
|
||||||
final List<JpaTarget> targets = targetRepository.findAll(targetIDs);
|
final List<JpaTarget> targets = targetRepository.findAll(targetIDs);
|
||||||
|
|
||||||
@@ -183,6 +191,8 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteTarget(final String controllerID) {
|
public void deleteTarget(final String controllerID) {
|
||||||
final Target target = targetRepository.findByControllerId(controllerID)
|
final Target target = targetRepository.findByControllerId(controllerID)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerID));
|
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerID));
|
||||||
@@ -322,6 +332,8 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public TargetTagAssignmentResult toggleTagAssignment(final Collection<String> controllerIds, final String tagName) {
|
public TargetTagAssignmentResult toggleTagAssignment(final Collection<String> controllerIds, final String tagName) {
|
||||||
final TargetTag tag = targetTagRepository.findByNameEquals(tagName)
|
final TargetTag tag = targetTagRepository.findByNameEquals(tagName)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(TargetTag.class, tagName));
|
.orElseThrow(() -> new EntityNotFoundException(TargetTag.class, tagName));
|
||||||
@@ -359,7 +371,10 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public List<Target> assignTag(final Collection<String> controllerIds, final Long tagId) {
|
public List<Target> assignTag(final Collection<String> controllerIds, final Long tagId) {
|
||||||
|
|
||||||
final List<JpaTarget> allTargets = targetRepository
|
final List<JpaTarget> allTargets = targetRepository
|
||||||
.findAll(TargetSpecifications.byControllerIdWithTagsInJoin(controllerIds));
|
.findAll(TargetSpecifications.byControllerIdWithTagsInJoin(controllerIds));
|
||||||
|
|
||||||
@@ -372,12 +387,19 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
.orElseThrow(() -> new EntityNotFoundException(TargetTag.class, tagId));
|
.orElseThrow(() -> new EntityNotFoundException(TargetTag.class, tagId));
|
||||||
|
|
||||||
allTargets.forEach(target -> target.addTag(tag));
|
allTargets.forEach(target -> target.addTag(tag));
|
||||||
return Collections
|
|
||||||
|
final List<Target> result = Collections
|
||||||
.unmodifiableList(allTargets.stream().map(targetRepository::save).collect(Collectors.toList()));
|
.unmodifiableList(allTargets.stream().map(targetRepository::save).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
// No reason to save the tag
|
||||||
|
entityManager.detach(tag);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Target unAssignTag(final String controllerID, final Long targetTagId) {
|
public Target unAssignTag(final String controllerID, final Long targetTagId) {
|
||||||
final JpaTarget target = (JpaTarget) targetRepository.findByControllerId(controllerID)
|
final JpaTarget target = (JpaTarget) targetRepository.findByControllerId(controllerID)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerID));
|
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerID));
|
||||||
@@ -387,7 +409,11 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
|
|
||||||
target.removeTag(tag);
|
target.removeTag(tag);
|
||||||
|
|
||||||
return targetRepository.save(target);
|
final Target result = targetRepository.save(target);
|
||||||
|
|
||||||
|
// No reason to save the tag
|
||||||
|
entityManager.detach(tag);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -524,6 +550,8 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public Target createTarget(final TargetCreate c) {
|
public Target createTarget(final TargetCreate c) {
|
||||||
final JpaTargetCreate create = (JpaTargetCreate) c;
|
final JpaTargetCreate create = (JpaTargetCreate) c;
|
||||||
return targetRepository.save(create.build());
|
return targetRepository.save(create.build());
|
||||||
@@ -531,6 +559,8 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public List<Target> createTargets(final Collection<TargetCreate> targets) {
|
public List<Target> createTargets(final Collection<TargetCreate> targets) {
|
||||||
return targets.stream().map(this::createTarget).collect(Collectors.toList());
|
return targets.stream().map(this::createTarget).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ package org.eclipse.hawkbit.repository.jpa;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTenantConfiguration;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTenantConfiguration;
|
||||||
import org.eclipse.hawkbit.repository.model.TenantConfiguration;
|
import org.eclipse.hawkbit.repository.model.TenantConfiguration;
|
||||||
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
||||||
@@ -23,6 +24,9 @@ import org.springframework.cache.annotation.Cacheable;
|
|||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||||
import org.springframework.core.convert.support.DefaultConversionService;
|
import org.springframework.core.convert.support.DefaultConversionService;
|
||||||
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
|
import org.springframework.retry.annotation.Backoff;
|
||||||
|
import org.springframework.retry.annotation.Retryable;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
@@ -122,6 +126,8 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
|
|||||||
@Override
|
@Override
|
||||||
@CacheEvict(value = "tenantConfiguration", key = "#configurationKeyName")
|
@CacheEvict(value = "tenantConfiguration", key = "#configurationKeyName")
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public <T extends Serializable> TenantConfigurationValue<T> addOrUpdateConfiguration(
|
public <T extends Serializable> TenantConfigurationValue<T> addOrUpdateConfiguration(
|
||||||
final String configurationKeyName, final T value) {
|
final String configurationKeyName, final T value) {
|
||||||
|
|
||||||
@@ -160,6 +166,8 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
|
|||||||
@Override
|
@Override
|
||||||
@CacheEvict(value = "tenantConfiguration", key = "#configurationKeyName")
|
@CacheEvict(value = "tenantConfiguration", key = "#configurationKeyName")
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Retryable(include = {
|
||||||
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public void deleteConfiguration(final String configurationKeyName) {
|
public void deleteConfiguration(final String configurationKeyName) {
|
||||||
tenantConfigurationRepository.deleteByKey(configurationKeyName);
|
tenantConfigurationRepository.deleteByKey(configurationKeyName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ import org.eclipse.hawkbit.repository.ControllerManagement;
|
|||||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||||
import org.eclipse.hawkbit.repository.EntityFactory;
|
import org.eclipse.hawkbit.repository.EntityFactory;
|
||||||
|
import org.eclipse.hawkbit.repository.PropertiesQuotaManagement;
|
||||||
import org.eclipse.hawkbit.repository.ReportManagement;
|
import org.eclipse.hawkbit.repository.ReportManagement;
|
||||||
import org.eclipse.hawkbit.repository.RepositoryProperties;
|
import org.eclipse.hawkbit.repository.RepositoryProperties;
|
||||||
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
||||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||||
import org.eclipse.hawkbit.repository.SoftwareManagement;
|
import org.eclipse.hawkbit.repository.SoftwareManagement;
|
||||||
import org.eclipse.hawkbit.repository.PropertiesQuotaManagement;
|
|
||||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||||
import org.eclipse.hawkbit.repository.TagManagement;
|
import org.eclipse.hawkbit.repository.TagManagement;
|
||||||
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
|
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
|
||||||
@@ -69,6 +69,7 @@ import org.eclipse.hawkbit.security.SecurityTokenGenerator;
|
|||||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties;
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties;
|
||||||
|
import org.eclipse.persistence.config.PersistenceUnitProperties;
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
@@ -89,6 +90,7 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
|||||||
import org.springframework.integration.support.locks.LockRegistry;
|
import org.springframework.integration.support.locks.LockRegistry;
|
||||||
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
|
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
|
||||||
import org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter;
|
import org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter;
|
||||||
|
import org.springframework.retry.annotation.EnableRetry;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
@@ -110,6 +112,7 @@ import com.google.common.collect.Maps;
|
|||||||
@EnableConfigurationProperties({ RepositoryProperties.class, ControllerPollProperties.class,
|
@EnableConfigurationProperties({ RepositoryProperties.class, ControllerPollProperties.class,
|
||||||
TenantConfigurationProperties.class })
|
TenantConfigurationProperties.class })
|
||||||
@EnableScheduling
|
@EnableScheduling
|
||||||
|
@EnableRetry
|
||||||
@EntityScan("org.eclipse.hawkbit.repository.jpa.model")
|
@EntityScan("org.eclipse.hawkbit.repository.jpa.model")
|
||||||
public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||||
|
|
||||||
@@ -283,17 +286,22 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
|||||||
@Override
|
@Override
|
||||||
protected Map<String, Object> getVendorProperties() {
|
protected Map<String, Object> getVendorProperties() {
|
||||||
|
|
||||||
final Map<String, Object> properties = Maps.newHashMapWithExpectedSize(5);
|
final Map<String, Object> properties = Maps.newHashMapWithExpectedSize(7);
|
||||||
// Turn off dynamic weaving to disable LTW lookup in static weaving mode
|
// Turn off dynamic weaving to disable LTW lookup in static weaving mode
|
||||||
properties.put("eclipselink.weaving", "false");
|
properties.put(PersistenceUnitProperties.WEAVING, "false");
|
||||||
// needed for reports
|
// needed for reports
|
||||||
properties.put("eclipselink.jdbc.allow-native-sql-queries", "true");
|
properties.put(PersistenceUnitProperties.ALLOW_NATIVE_SQL_QUERIES, "true");
|
||||||
// flyway
|
// flyway
|
||||||
properties.put("eclipselink.ddl-generation", "none");
|
properties.put(PersistenceUnitProperties.DDL_GENERATION, "none");
|
||||||
// Embeed into hawkBit logging
|
// Embeed into hawkBit logging
|
||||||
properties.put("eclipselink.logging.logger", "JavaLogger");
|
properties.put(PersistenceUnitProperties.LOGGING_LOGGER, "JavaLogger");
|
||||||
// Ensure that we flush only at the end of the transaction
|
// Ensure that we flush only at the end of the transaction
|
||||||
properties.put("eclipselink.persistence-context.flush-mode", "COMMIT");
|
properties.put(PersistenceUnitProperties.PERSISTENCE_CONTEXT_FLUSH_MODE, "COMMIT");
|
||||||
|
|
||||||
|
// Enable batch writing
|
||||||
|
properties.put(PersistenceUnitProperties.BATCH_WRITING, "JDBC");
|
||||||
|
// Batch size
|
||||||
|
properties.put(PersistenceUnitProperties.BATCH_WRITING_SIZE, "500");
|
||||||
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,9 +53,9 @@ public interface RolloutRepository
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
||||||
* reasons (this is a "delete everything" query after all) we add the tenant manually to
|
* reasons (this is a "delete everything" query after all) we add the tenant
|
||||||
* query even if this will by done by {@link EntityManager} anyhow. The DB
|
* manually to query even if this will by done by {@link EntityManager}
|
||||||
* should take care of optimizing this away.
|
* anyhow. The DB should take care of optimizing this away.
|
||||||
*
|
*
|
||||||
* @param tenant
|
* @param tenant
|
||||||
* to delete data from
|
* to delete data from
|
||||||
|
|||||||
@@ -113,9 +113,9 @@ public interface SoftwareModuleRepository
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
||||||
* reasons (this is a "delete everything" query after all) we add the tenant manually to
|
* reasons (this is a "delete everything" query after all) we add the tenant
|
||||||
* query even if this will by done by {@link EntityManager} anyhow. The DB
|
* manually to query even if this will by done by {@link EntityManager}
|
||||||
* should take care of optimizing this away.
|
* anyhow. The DB should take care of optimizing this away.
|
||||||
*
|
*
|
||||||
* @param tenant
|
* @param tenant
|
||||||
* to delete data from
|
* to delete data from
|
||||||
|
|||||||
@@ -82,9 +82,9 @@ public interface SoftwareModuleTypeRepository
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
||||||
* reasons (this is a "delete everything" query after all) we add the tenant manually to
|
* reasons (this is a "delete everything" query after all) we add the tenant
|
||||||
* query even if this will by done by {@link EntityManager} anyhow. The DB
|
* manually to query even if this will by done by {@link EntityManager}
|
||||||
* should take care of optimizing this away.
|
* anyhow. The DB should take care of optimizing this away.
|
||||||
*
|
*
|
||||||
* @param tenant
|
* @param tenant
|
||||||
* to delete data from
|
* to delete data from
|
||||||
|
|||||||
@@ -57,9 +57,9 @@ public interface TargetFilterQueryRepository
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
||||||
* reasons (this is a "delete everything" query after all) we add the tenant manually to
|
* reasons (this is a "delete everything" query after all) we add the tenant
|
||||||
* query even if this will by done by {@link EntityManager} anyhow. The DB
|
* manually to query even if this will by done by {@link EntityManager}
|
||||||
* should take care of optimizing this away.
|
* anyhow. The DB should take care of optimizing this away.
|
||||||
*
|
*
|
||||||
* @param tenant
|
* @param tenant
|
||||||
* to delete data from
|
* to delete data from
|
||||||
|
|||||||
@@ -217,9 +217,9 @@ public interface TargetRepository extends BaseEntityRepository<JpaTarget, Long>,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
||||||
* reasons (this is a "delete everything" query after all) we add the tenant manually to
|
* reasons (this is a "delete everything" query after all) we add the tenant
|
||||||
* query even if this will by done by {@link EntityManager} anyhow. The DB
|
* manually to query even if this will by done by {@link EntityManager}
|
||||||
* should take care of optimizing this away.
|
* anyhow. The DB should take care of optimizing this away.
|
||||||
*
|
*
|
||||||
* @param tenant
|
* @param tenant
|
||||||
* to delete data from
|
* to delete data from
|
||||||
|
|||||||
@@ -70,9 +70,9 @@ public interface TargetTagRepository
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
||||||
* reasons (this is a "delete everything" query after all) we add the tenant manually to
|
* reasons (this is a "delete everything" query after all) we add the tenant
|
||||||
* query even if this will by done by {@link EntityManager} anyhow. The DB
|
* manually to query even if this will by done by {@link EntityManager}
|
||||||
* should take care of optimizing this away.
|
* anyhow. The DB should take care of optimizing this away.
|
||||||
*
|
*
|
||||||
* @param tenant
|
* @param tenant
|
||||||
* to delete data from
|
* to delete data from
|
||||||
|
|||||||
@@ -46,9 +46,9 @@ public interface TenantConfigurationRepository extends BaseEntityRepository<JpaT
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
||||||
* reasons (this is a "delete everything" query after all) we add the tenant manually to
|
* reasons (this is a "delete everything" query after all) we add the tenant
|
||||||
* query even if this will by done by {@link EntityManager} anyhow. The DB
|
* manually to query even if this will by done by {@link EntityManager}
|
||||||
* should take care of optimizing this away.
|
* anyhow. The DB should take care of optimizing this away.
|
||||||
*
|
*
|
||||||
* @param tenant
|
* @param tenant
|
||||||
* to delete data from
|
* to delete data from
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository.jpa.configuration;
|
package org.eclipse.hawkbit.repository.jpa.configuration;
|
||||||
|
|
||||||
|
import org.springframework.retry.annotation.Backoff;
|
||||||
|
import org.springframework.retry.annotation.Retryable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A constant class which holds only static constants used within the SP server.
|
* A constant class which holds only static constants used within the SP server.
|
||||||
*
|
*
|
||||||
@@ -23,6 +26,16 @@ public final class Constants {
|
|||||||
*/
|
*/
|
||||||
public static final int MAX_ENTRIES_IN_STATEMENT = 999;
|
public static final int MAX_ENTRIES_IN_STATEMENT = 999;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Retryable#maxAttempts()
|
||||||
|
*/
|
||||||
|
public static final int TX_RT_MAX = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Backoff#delay()
|
||||||
|
*/
|
||||||
|
public static final long TX_RT_DELAY = 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constant class only private constructor.
|
* Constant class only private constructor.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user