Оптимистичная блокировка не работает в спячкеJAVA

Программисты JAVA общаются здесь
Anonymous
Оптимистичная блокировка не работает в спячке

Сообщение Anonymous »

У меня есть проблема при работе с оптимистичной блокировкой, он притворяется, что работает, даже повышает версию в базе данных и бросает оптимистичное плавное положение в случае чего -либо, то есть наиболее ожидаемого поведения. Я внедрил систему, где ожидаемые ошибки, и мы стараемся выполнять действия, пока блокировка на месте. Но я вижу дубликаты и отсутствующие файлы, условие гонки очевидно. Кто -нибудь знает, что я должен сделать, чтобы правильно работать?public void updateIdsVariableInProcess(String processId, String processInstanceId, String objectKey, boolean insertFlag) {
log.info("Adding ID variable to process. processId={}, processInstanceId={}, objectKey={}", new Object[]{processId, processInstanceId, objectKey});
boolean lockAndVarsInContextUpdated = false;

while(!lockAndVarsInContextUpdated) {
try {
this.processLockService.updateVariableWithLock2(processId, processInstanceId, objectKey, insertFlag);
lockAndVarsInContextUpdated = true;
} catch (ArcUndeclaredThrowableException | PersistenceException var8) {
RuntimeException expected = var8;
log.warn("Error while setting lock and updating process variable. processId={}, processInstanceId={}, objectKey={}, error={}", new Object[]{processId, processInstanceId, objectKey, expected.getMessage(), expected});
} catch (Exception var9) {
Exception unexpected = var9;
log.error("Unexpected error while updating variable. processId={}, processInstanceId={}, cause={}", new Object[]{processId, processInstanceId, unexpected.getMessage(), unexpected});
throw new RuntimeException("Unexpected error while updating variable", unexpected);
}

if (!lockAndVarsInContextUpdated) {
try {
Thread.sleep(50L);
} catch (InterruptedException var7) {
InterruptedException e = var7;
Thread.currentThread().interrupt();
throw new RuntimeException("Thread interrupted while waiting to retry", e);
}
}
}

log.info("SyncInteractionProcessService.addIdsVariableInProcess - Retrying ProcessId: {}, ProcessInstanceId: {}, ObjectKey: {}", new Object[]{processId, processInstanceId, objectKey});
}
< /code>
И это самый основной метод транзакции, который должен выполнять всю работу или бросить ошибку. < /p>
@Transactional
public Boolean updateVariableWithLock2(String processId, String processInstanceId, String fileId, boolean insertFlag) {
if (!this.processLockRepository.existsByProcessIdAndProcessInstanceId(processId, processInstanceId)) {
this.createNewLock(processId, processInstanceId);
}

int version;
try {
ProcessLockEntity processLockEntity = this.processLockRepository.getByProcessIdAndProcessInstanceId(processId, processInstanceId);
version = processLockEntity.getVersion();
log.info("Existing lock found. Updating processLockEntity. ProcessId: {}, ProcessInstanceId: {}, Version: {}", new Object[]{processId, processInstanceId, version});
Map variables = this.processInteractionService.getVariables(processId, processInstanceId);
S3ObjectIds s3ObjectIds = (S3ObjectIds)variables.get("s3ObjectIds");
if (s3ObjectIds == null) {
s3ObjectIds = new S3ObjectIds();
}

if (s3ObjectIds.getIdS() == null) {
s3ObjectIds.setIdS(new ArrayList());
}

List filesIds = new ArrayList(s3ObjectIds.getIdS());
if (insertFlag) {
filesIds.add(fileId);
} else {
filesIds.remove(fileId);
}

s3ObjectIds.setIdS(filesIds);
// WE ARE UPDATING CONTEXT OF PROCESS HERE, WE DO NOT WRITE TO DB HERE, ONLY CONTEXT HERE
this.patchIdsVariableInProcess(processId, processInstanceId, s3ObjectIds);
this.updateVersionLock(processLockEntity);
} catch (Exception var10) {
Exception e = var10;
log.error("Failed to update variable with lock", e);
throw e;
}

log.info("Finished lock update. ProcessId: {}, ProcessInstanceId: {}, Version: {}", new Object[]{processId, processInstanceId, version});
return true;
}
< /code>
Здесь мы занимаем текущий контекст (место, где мы храним список чего -то) и размещаем блокировку < /p>
public ProcessLockEntity getByProcessIdAndProcessInstanceId(String processId, String processInstanceId) {
CriteriaBuilder cb = this.entityManager.getCriteriaBuilder();
CriteriaQuery query = cb.createQuery(ProcessLockEntity.class);
Root root = query.from(ProcessLockEntity.class);
query.select(root).where(cb.and(cb.equal(root.get("processId"), processId), cb.equal(root.get("processInstanceId"), processInstanceId)));
TypedQuery typedQuery = this.entityManager.createQuery(query).setLockMode(LockModeType.OPTIMISTIC);
ProcessLockEntity processLockEntity = (ProcessLockEntity)typedQuery.getSingleResult();
log.info("Retrieved ProcessLockEntity. ProcessId: {}, ProcessInstanceId: {}, Entity: {}", new Object[]{processId, processInstanceId, processLockEntity});
return processLockEntity;
}
< /code>
И здесь мы скажем, что мы заканчиваем блокировку < /p>
private void updateVersionLock(ProcessLockEntity version) {
this.processLockRepository.updateProcessInstanceVersion(version);
}
public void updateProcessInstanceVersion(ProcessLockEntity version) {
log.info("ProcessLockCriteriaRepository class, updateProcessInstanceVersion: processId={}, processInstanceId={}, version={}", new Object[]{version.getProcessId(), version.getProcessInstanceId(), version.getVersion()});
version.setLastUpdated(Instant.now());
}
< /code>
Наш класс объектов < /p>
@Entity
@Table(name = "process_lock", schema = "public", uniqueConstraints = {
@UniqueConstraint(columnNames = {"process_id", "process_instance_id"})
})
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ProcessLockEntity {

/**
* Unique identifier for the context version.
*/
@Id
@GeneratedValue
private UUID id;

/**
* Identifier of the process. (for example ServiceDeskRequestRegistration)
*/
@Column(name = "process_id")
private String processId;

/**
* Identifier of the process instance.
*/
@Column(name = "process_instance_id")
private String processInstanceId;

/**
* TIMESTAMP of the last update.
*/
@Column(name = "last_updated")
private Instant lastUpdated;

/**
* Version number of the context.
*/
@Version
private Integer version;

}
< /code>
Я пытался отправить 5 запросов на публикацию с идентификаторами одновременно. И это то, что я вижу в DB, ​​а в журналах
Введите описание изображения здесь < /p>
Последний журнал < /p>
{"timestamp":"2025-05-02T00:04:58.107+03:00","sequence":5076,"loggerClassName":"org.slf4j.impl.Slf4jLogger","loggerName":"ru.logic.bpm.service.lock.service.ProcessLockServiceImpl","level":"INFO","message":"S3OBJECT +ru.logic.bpm.service.s3.interactingprocess.model.S3ObjectIds@5183aeee VALUES CLASS + class java.util.ArrayList VALUES + [a5cc34ca-c276-419b-be90-b6e2e484c68c, 11159010-a303-4b59-8df4-81bf3cc0e1e8, 763bca97-d3ea-4786-ad8b-0880015792e6, 11159010-a303-4b59-8df4-81bf3cc0e1e8, 5c21bc3d-d278-47b9-b06c-693cbaede836]","threadName":"executor-thread-0","threadId":264,"mdc":{"spanId":"e6a6e47a224e0724","parentId":"d0de6776d305095d","traceId":"faad8e083cc24ccd952c2908f76b8d82","sampled":"true"},"ndc":"","hostName":"msi","processName":"sd-request-registration-dev.jar","processId":24832}


Подробнее здесь: https://stackoverflow.com/questions/796 ... -hibernate

Вернуться в «JAVA»