Skip to content

Commit

Permalink
Avoid optimistic locking exceptions in clusters (#58)
Browse files Browse the repository at this point in the history
  • Loading branch information
stephanpelikan committed Sep 9, 2024
1 parent 56ba0ac commit 2ef1bed
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 14 deletions.
5 changes: 5 additions & 0 deletions spring-boot/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
<artifactId>spring-tx</artifactId>
<version>6.1.3</version>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>2.0.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.data.repository.CrudRepository;
import org.springframework.retry.annotation.EnableRetry;

@AutoConfigurationPackage(basePackageClasses = Camunda8AdapterConfiguration.class)
@AutoConfigureBefore(CamundaAutoConfiguration.class)
@EnableConfigurationProperties(Camunda8VanillaBpProperties.class)
@EnableRetry
public class Camunda8AdapterConfiguration extends AdapterConfigurationBase<Camunda8ProcessService<?>> {

private static final Logger logger = LoggerFactory.getLogger(Camunda8AdapterConfiguration.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,6 @@
import io.vanillabp.camunda8.wiring.Camunda8TaskWiring;
import io.vanillabp.springboot.adapter.ModuleAwareBpmnDeployment;
import io.vanillabp.springboot.adapter.VanillaBpProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.core.io.Resource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StreamUtils;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Arrays;
Expand All @@ -36,8 +29,12 @@
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.core.io.Resource;
import org.springframework.util.StreamUtils;

@Transactional
public class Camunda8DeploymentAdapter extends ModuleAwareBpmnDeployment {

private static final Logger logger = LoggerFactory.getLogger(Camunda8DeploymentAdapter.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
import io.camunda.zeebe.client.api.response.Process;
import io.camunda.zeebe.model.bpmn.Bpmn;
import io.camunda.zeebe.model.bpmn.BpmnModelInstance;

import java.io.ByteArrayOutputStream;
import java.time.OffsetDateTime;
import java.util.List;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

public class DeploymentService {

Expand All @@ -22,12 +27,17 @@ public DeploymentService(
this.deploymentResourceRepository = deploymentResourceRepository;

}


@Transactional(propagation = Propagation.REQUIRES_NEW)
@Retryable(
retryFor = OptimisticLockingFailureException.class,
maxAttempts = 100,
backoff = @Backoff(delay = 100, maxDelay = 500))
public DeployedBpmn addBpmn(
final BpmnModelInstance model,
final int fileId,
final String resourceName) {

final var previous = deploymentResourceRepository.findById(fileId);
if (previous.isPresent()) {
return (DeployedBpmn) previous.get();
Expand All @@ -44,12 +54,31 @@ public DeployedBpmn addBpmn(
return deploymentResourceRepository.save(bpmn);

}


@Recover
public DeployedBpmn recoverAddBpmn(
final OptimisticLockingFailureException exception,
final BpmnModelInstance model,
final int fileId,
final String resourceName) {

throw new RuntimeException(
"Could not save BPMN '"
+ resourceName
+ "' in local DB due to stale OptimisticLockingFailureException", exception);

}

@Transactional(propagation = Propagation.REQUIRES_NEW)
@Retryable(
retryFor = OptimisticLockingFailureException.class,
maxAttempts = 100,
backoff = @Backoff(delay = 100, maxDelay = 500))
public DeployedProcess addProcess(
final int packageId,
final Process camunda8DeployedProcess,
final DeployedBpmn bpmn) {

final var versionedId = camunda8DeployedProcess.getProcessDefinitionKey();

final var previous = deploymentRepository.findByDefinitionKey(versionedId);
Expand All @@ -71,6 +100,20 @@ public DeployedProcess addProcess(

}

@Recover
public DeployedProcess recoverAddProcess(
final OptimisticLockingFailureException exception,
final int packageId,
final Process camunda8DeployedProcess,
final DeployedBpmn bpmn) {

throw new RuntimeException(
"Could not save Process '"
+ camunda8DeployedProcess.getBpmnProcessId()
+ "' in local DB due to stale OptimisticLockingFailureException", exception);

}

public List<DeployedBpmn> getBpmnNotOfPackage(final int packageId) {

return deploymentResourceRepository
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ private DE runInTransaction(
Camunda8AdapterConfiguration.ADAPTER_ID,
camunda8Properties.getTenantId(parent.getWorkflowModuleId()),
parent.getWorkflowModuleId(),
aggregateId == null ? null : aggregateId.toString(),
aggregateId.toString(),
bpmnProcessId,
taskIdToTestForAlreadyCompletedOrCancelled,
null,
Expand Down

0 comments on commit 2ef1bed

Please sign in to comment.