Я столкнулся с проблемой, когда в некоторых очень редких случаях (<1%) существующий объект не обновляется правильно.Во всех остальных случаях он работает как положено. </p>
Стек: JPA и Hibernate, Wildfly10 (кластер), Ubuntu, PostgreSQL (настройка Master / Slave)
Что происходит?
- Пользователь ожидает в своем браузере, что для ContractEntity установлено значение
PAID
.Браузер выполняет запрос каждые 3 секунды, запрашивая статус ContractEntity - Наш поставщик платежей вызывает на нашем сервере веб-крючок, который вызывает функцию
setContractToPaidAndNotifyUsers()
.Это должно изменить статус ContractEntity на PAID
, но он останется в статусе STARTED
.Нет зарегистрированных ошибок, и другие вызовы функций, которые происходят впоследствии, работают правильно (отправка электронных писем).
Поэтому я предполагаю, что ошибка происходит, когда транзакция базы данных совершается.
Это функция, которую вызывает webhook:
@Stateless
public class ContractBoundary {
@Inject
private ContractControl contractControl;
private void setContractToPaidAndNotifyUsers(PaymentEntity paymentEntity, ContractEntity contractEntity, final String paidResourceId) {
// This is not working (no error, but the contract remains on status STARTED
contractEntity.setStatus(ContractStatusEnum.PAID);
contractEntity.setPaidResourceId(paidResourceId);
ContractEntity updatedContractEntity = contractControl.update(contractEntity);
// These are working
mailControl.sendMoneyArrivedMailToPayee(
contractBoundary.getContractLink(updatedContractEntity.getContractCode()),
updatedContractEntity.getTitle(), updatedContractEntity.getPayer(), updatedContractEntity.getPayee(),
eventMoneyArrivedForPayee);
mailControl.sendMoneyArrivedMailToPayer(
contractBoundary.getContractLink(updatedContractEntity.getContractCode()), contractEntity.getTitle(),
updatedContractEntity.getPayer(), updatedContractEntity.getPayee(), eventMoneyArrivedForPayer);
}
}
Это функция обновления в contractControl
public class ContractControl extends BasicCrudControl {
// ... more CRUD functions
public ContractEntity update(final ContractEntity contract) {
ContractEntity update = super.update(contract);
return update;
}
}
Это функция обновления нашего BasicCRUDControl:
protected <T> T update(final T entityToUpdate) {
T t = this.em.merge(entityToUpdate);
return t;
}
Нужно ли мне запускать em.flush();
или em.refresh();
в моей функции update
?Поскольку это происходит только в некоторых случаях, я думаю, что может возникнуть проблема, когда запрос из браузера пользователя выполняется одновременно с вызовом webhook, что может привести к некоторым проблемам.
ТакжеЯ только что узнал, что ContractControl
не имеет @Stateless
Аннотация, может ли это привести к проблемам, так как ContractBoundary
помечен как не имеющий состояния и вводит ContractControl
?
Любая помощь приветствуется!