I have the following use case where I want to retrieve multiple error status information for a device from multiple data sources. I want to terminate all tasks immediately and return the error status to the main task if any of the statuses is true. How can I achieve this? Here is my query logic:
try (var scope = new StructuredTaskScope<>()) {
scope.fork(()->posRepo.findInspectionByUnitId(unitId));
scope.fork(()->posRepo.findEventOfFireByUnitId(unitId));
scope.fork(()->faultRepo.findGeneralErrorByUnitId(unitId));
scope.fork(()->ardInfRepo.findArdModeByUnitId(unitId));
scope.fork(()->ardInfRepo.findArdPowerStatusByUnitId(unitId));
scope.fork(()->ardInfRepo.findArdModeByUnitId(unitId));
// Once a task return true, close all remaining tasks,and return the signal:"true" to main task;
scope.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
public interface ElePosRepo extends CrudRepository<PositionInformation,Integer> {
Optional<Boolean> findInspectionByUnitId(Integer unitId);
Optional<Boolean> findEventOfFireByUnitId(Integer unitId);
}
I expect that when a subtask returns true, all other subtasks within the task group should be immediately terminated. If all subtasks return false or are empty, the main task should return false after completing all subtasks.
and
isSucceededshould be accessed afterjoincompletesbut instead of relying on the haphazard solution to equally haphazard (for example, you didn't specify a behavior on exceptions, thrown by subtasks) requirements, expressed in the question, I'd suggest to learn
handleCompleteoverriding technique, it is recommended for definition of custom behavior, was introduced right inStructuredTaskScope.ShutdownOnFailureandStructuredTaskScope.ShutdownOnSuccessand @Holger gave another excellent example in his answer.Some technical details:
forks afterjoin. To achieve it, either have a (re)setter forsucceededfield or override bothjoins like @Holger did, the second way is more elegant, but it is a bit more prone to errors as it might silently fail if next version will add thirdjoin; (but would like to havejoinImplprotected in next version or have some kind ofjoinCompletedplaceholder in the base class).shutdownis not guarded against concurrent invocations, as I believe thatimplShutdownalready does this, so I found a guarding inShutdownOnSuccess.handleCompleteexcessive.StructuredTaskScope.Subtaskin overriddenhandleCompletemethod isSubtask.State.FAILEDand act accordingly. The good example of such handling is stockShutdownOnFailure.handleComplete,ShutdownOnFailureis a final class, though, and cannot be reused for your purpose. Once again, due to the lack of clearly pronounced system requirements theShutdownOnFirstTrueabove is only a hint, not a fully working tool.