I think I might be noticing deadlock kind of situation while trying to persist objects concurrently using @Async annotation.
I used a component like
@Component
public class AsyncInserter{
@Autowired
private PersonRepository repository;
@Async
@Transactional
public CompletableFuture<Boolean> insert(List<Person> persons){
repository.saveAll(persons);
repository.flush();
return CompletableFuture.completedFuture(Boolean.TRUE);
}
I'm calling this from a service layer which is defined as @Component public class PersonServiceImpl{
@Autowired
private AsyncInserter asyncInserter;
@Transactional
public void performDBOperation(List<Person> persons){
deletePersons(/** some criteria */);
List<List<Person>> subPersonList = Lists.partition(persons, 100);
subPersonList.forEach(list->{ statuses.add(asyncInserter.insert(list));});
}
As you noticed, I have a delete and Insert (in concurrent ), which I wanted to be atomic completely.
But what I noticed is a delete and a bunch of inserts are submitted but never committed.
I think, there is some lock that is preventing and I can isolate this when running in concurrent threads. Per https://dzone.com/articles/spring-and-threads-transactions, it seems when a new thread is created, the outer transaction is not propagated to the newly created thread, and it creates a new Transaction.
This design seems to have a flaw. Do I need to commit delete first before submitting for Inserts? But how do I achieve atomic operation, if one of the inserts fails
I modified the code to run both delete and insert in a single thread, and it works, which is expected anyway. But what I noticed is after inserting records, it takes a longer time to commit. Usually, 12 secs more to commit 10K records. Which is a huge overhead? Is there any way to improve this?
By the way, I'm using Hikari Connection pool.
Thanks