我正在查询Dynamo DB以获取给定的主键。主键包含两个UUID字段(fieldUUID1,fieldUUID2)。 对于上面带有值列表的主键组合,我有很多查询要执行。为此,我将ExecutorService与Asynchronous CompleteableFuture配合使用,线程池的大小为4。
在所有查询返回结果CompletableFuture<Object>
之后,我使用allOf
可完成未来的方法将其加入,该方法可确保所有查询执行均完成,并且给我CompletableFuture<void>
,使用该流我收到CompletableFuture<List<Object>>
如果某些查询导致结果分页,即返回lastEvaluatedKey
,则我无法知道哪个查询请求返回了此结果。
如果我在收到`CompletableFuture的同时进行.get()调用,这将是一个阻塞操作,无法实现使用异步的目的。我有办法解决这种情况吗?
示例:
我可以尝试thenCompose方法,但是我怎么知道在没有lastEvaluatedKey的情况下需要停在什么地方。
for (final QueryRequest queryRequest : queryRequests) {
final CompletableFuture<QueryResult> futureResult =
CompletableFuture.supplyAsync(() ->
dynamoDBClient.query(queryRequest), executorService));
if (futureResult == null) {
continue;
}
futures.add(futureResult);
}
// Wait for completion of all of the Futures provided
final CompletableFuture<Void> allfuture = CompletableFuture
.allOf(futures.toArray(new CompletableFuture[futures.size()]));
// The return type of the CompletableFuture.allOf() is a
// CompletableFuture<Void>. The limitation of this method is that it does not
// return the combined results of all Futures. Instead we have to manually get
// results from Futures. CompletableFuture.join() method and Java 8 Streams API
// makes it simple:
final CompletableFuture<List<QueryResult>> allFutureList = allfuture.thenApply(val -> {
return futures.stream().map(f -> f.join()).collect(Collectors.toList());
});
final List<QueryOutcome> completableResults = new ArrayList<>();
try {
try {
// at this point all the Futures should be done, because we already executed
// CompletableFuture.allOf method.
final List<QueryResult> returnedResult = allFutureList.get();
for (final QueryResult queryResult : returnedResult) {
if (MapUtils.isNotEmpty(queryResult.getLastEvaluatedKey()) {
// how to get hold of original request and include last evaluated key ?
}
}
} finally {
}
} finally {
}
我可以依赖.get()方法,但这将是一个阻塞调用。
答案 0 :(得分:0)
您需要的快速解决方案是更改public function createRecipe(Request $request )
{
$data = ([
'recipe_name' => 'Fried Chicken',
'ingredient_id' => ['1', '3', '4'],
])
Recipe::create($data);
return redirect()->route('recipe.index')->withStatus(__('Recipe has been added.'));
}
}
列表。除了可以存储futures
之外,您还可以更改为存储CompletableFuture<QueryResult>
,其中CompletableFuture<RequestAndResult>
是包含RequestAndResult
和QueryRequest
的简单数据类。为此,您需要更改第一个循环。
然后,QueryResult
完成后,您可以遍历allfuture
并获得对请求和结果的访问权限。
但是,这里有一个更深层次的问题。一旦可以访问原始版本futures
,您打算做什么?我的猜测是,您想发出一个QueryRequest
设置为响应exclusiveStartKey
所设置的后续请求。这意味着您将等待所有原始查询完成,然后才发出下一个查询。这效率低下:如果查询返回的是lastEvaluatedKey
,则您希望尽快发出其后续查询。
为实现这一目标,我建议您引入一种新方法,该方法采用单个lastEvaluatedKey
对象并返回一个QueryRequest
。其实现大致如下:
CompletableFuture<QueryResult>
为空,则返回该方法的结果是的,用lastEvaluatedKey
(相比于阻塞代码)很难做到这一点,但完全可行。
一旦有了该方法,您的代码就需要针对CompletableFutures
中的每个请求调用一次此方法,将返回的queryRequests
放入列表中,然后对CompletableFuture
进行操作那个清单。一旦allOf future完成,您就可以使用结果-无需发出后续查询。