Я запутался в том, как составить следующую последовательность событий, используя Java 8 CompletionStage
.
У меня есть иерархия объектов, которая выглядит следующим образом:
parent
|
+-- link1 --- link2 --- link3 --- ...
| | |
| | |
child1 child2 child3
Ипоследовательность событий, которая мне нужна, такова:
CompletionStage<Response> fp = approve(parent);
CompletionStage<Response> fc1 = approve(child1);
CompletionStage<Response> fc2 = approve(child2);
CompletionStage<Response> fc3 = approve(child3);
...
Когда каждый из этих фьючерсов завершен, если какой-либо из них завершился неудачей, возможна повторная попытка:
fp.thenCompose(parentResponse -> {
if (parentResponse.hasErrors()) {
return forceApprove(parent);
}
return parentResponse;
}
fc1.thenCompose(child1Response -> {
if (child1Response.hasErrors()) {
return forceApprove(child1);
}
return child1Response;
}
...
и так далее.Все вышеперечисленное может происходить параллельно.
Это следующий шаг, который меня смущает.Для каждого будущего ребенка, которое завершается, я хочу сделать еще одну вещь:
child1Response -> {
if (someLogic(child1Response, parentResponse)) {
return approve(link1);
}
return otherLogic();
}
child2Response -> {
if (someLogic(child2Response, parentResponse)) {
return approve(link2);
}
return otherLogic();
}
...
Обратите внимание, что каждый из них зависит от завершения родительского будущего.Я в основном хотел бы подождать на всех fp
, fc1
, fc2
, fc3
, ... прежде чем делать любой из fl1
, fl2
, fl3
, ... этапы, но как мне соединить fc1+fl1
, fc2+fl2
, fc3+fl3
, ... и все же попросить все последние этапы дождаться завершения всех начальных этапов?
Возвращаясь, ядумаю, что повторная часть проста.Я могу просто обернуть обе ступени в будущее каждая:
CompletionStage<Response> fp =
approve(parent).thenCompose(parentResponse -> {
if (parentResponse.hasErrors()) {
return forceApprove(parent);
}
return parentResponse;
});
CompletionStage<Response> fc1 =
approve(child1).thenCompose(child1Response -> {
if (child1Response.hasErrors()) {
return forceApprove(child1);
}
return child1Response;
});
CompletionStage<Response> fc2 =
approve(child2).thenCompose(child1Response -> {
if (child2Response.hasErrors()) {
return forceApprove(child2);
}
return child2Response;
});
CompletionStage<Response> fc3 =
approve(child3).thenCompose(child1Response -> {
if (child3Response.hasErrors()) {
return forceApprove(child3);
}
return child3Response;
});
...
Тогда я подумал, может быть
List<CompletionStage<Response>> fcList; // fc1, fc2, fc3, ...
fp.thenCombine(CompletableFutures.allOf(fcList)).thenApply(
// ?
);
Но как мне "приковать" последний кусочек логики к каждой ступени?fc1
, fc2
, fc3
, ... так они возобновятся в этот момент?