Description
What is the problem
Blocking call into Task constructor
Some of our tasks do blocking calls into their constructors.
Example:
public ClearMailRepositoryTask(List<MailRepository> mailRepositories, MailRepositoryPath path) { this.mailRepositories = mailRepositories; this.mailRepositoryPath = path; this.initialCount = getRemainingSize(); // blocking }
Logic into constructor:
- Is clearly an anti-pattern
- This stuff get's deserialized so we should be really careful with what get's into the constructor
- We don't expect blocking calls when deserializing
We should get rid of all those blocking calls into constructors.
Blocking calls when generating task details
We might need to do backend calls when generating task details, eg querying the DB to know how much records remains.
The issue here is that those blocking calls are 'hidden'. We should enable tasks to expose a publisher for getting their details, allowing to wrap "on demand" their details.
interface Task { default Optional<TaskExecutionDetails.AdditionalInformation> details() { return Optional.empty(); } default Publisher<TaskExecutionDetails.AdditionalInformation> detailsReactive() { return Mono.fromCallable(() -> details) .handle(ReactorUtils::publishIfPresent); } }
This would enable:
- To preserve the non blocking chain
- To wrap blocking calls only where needed.
Why is this needed?
The Cassandra driver 4 work highlighted the limitation of our task system. We got away with quick fixes but a little redesign will get this sorted.