Как мне дождаться завершения списка CompletionStage, а затем начать еще один CompletionStage для каждого ответа? - PullRequest
0 голосов
/ 25 апреля 2019

Я запутался в том, как составить следующую последовательность событий, используя 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, ... так они возобновятся в этот момент?

...