Is there any way to cancel transaction if remote client is gone?
@RestController
class Controller {
...
@PostMapping("/do/thing")
public Response doThing() {
...
return businessLogicService.performAction();
}
}
@Service
class BusinessLogicService {
...
public Response doThing() {
...
var pieceOfData = restClient.callExternalService();
...
transactionTemplate.execute(status -> {
dao.save(pieceOfData);
})
...
return response;
}
...
}
The problem is that sometimes performAction() works longer than usual (REST calls to external service are retried, transactionTemplate waits for free connection in Hikari pool, etc.)
Remote client (consumer of our REST API) get a read timeout and “forget” about us, but our service doesn’t have any clue about it – the method completes successfully, a state in database has been changed (entity is persisted), and when Spring MVC machinery serializes DTO and tries to write it to socket, we have an exception “connection has been closed by the remote peer”.
As a result, we have inconsistency between us and our consumer – we have a succesfull booking in our DB, but they are not.
Maybe there is some pattern to handle such a thing?