Как откатить транзакцию, если не удалось доставить ответ POST
Используя Spring MVC, предположим, что я реализовал контроллер, который обрабатывает запрос POST, выполняет операцию базы данных внутри транзакции и возвращает результат в теле ответа.
Вот контроллер и уровень обслуживания:
@RestController
@RequiredArgsConstructor
public class SomeController {
private final SomeService someService;
@PostMapping("/something")
public SomeResult postSomething(Something something) {
return someService.handle(something);
}
}
@Service
@RequiredArgsConstructor
public class SomeService {
private final SomeRepository someRepository;
@Transactional
public SomeResult handle(Something something){
// changes to the database
}
}
Вопросы:
Предполагая, что кто-то тянет сетевой кабель сразу после вызова службы, транзакция завершается.
1) Будет ли Spring генерировать исключение, если ответ не может быть доставлен?
2) Можно ли откатить транзакцию, если ответ не может быть доставлен?
3) Как я могу убедиться, что база данных остается согласованной при повторных попытках клиента? (ПОЧТА не идемпотентна).
Спасибо!
1 ответ
Я постараюсь ответить на ваши вопросы:
1) Возможно. Это зависит от размера ответа и точного момента, когда соединение потеряно.
Исключение будет выдано, если при попытке весны написать ответ на сокет ОС обнаружит, что TCP/IP-соединение закрыто. Протокол TCP не содержит внутренней процедуры обнаружения такой ситуации, поэтому ОС использует эвристику, например тайм-ауты.
Поэтому я вижу только один вариант здесь. Spring пытается записать ответ в сокет, но ответ слишком большой, чтобы поместиться в буфер. В этой ситуации операция записи будет заблокирована. Затем через некоторое время оно будет прервано из-за тайм-аута и возникнет исключение.
Я не уверен на 100%, что мой ответ точен, поэтому вам лучше проверить его самостоятельно. Я предлагаю вам не полагаться на эту механику, поскольку она зависит от множества различных факторов, таких как размер буфера, время ожидания и реализация Spring.
2) С весны ответ будет НЕТ.
3) Это зависит от вас. Универсального ответа нет. Например Hibernate
можно настроить на использование версий на ваших объектах.