如果在 API 调用期间部分失败,以下 java 代码的输出是什么?
What will be the output of the below java code in case of partial failure during API calls?
我有一个总共 115 个输入的列表,使用下面的代码将其分成 20 个输入的数据包大小,这意味着 xoneIndexListOfList
有 6 个元素,大小分别为 [ [20], [20], [20], [20], [20], [15] ]
。
final AtomicInteger counter = new AtomicInteger();
final Collection<List<XoneIndexRequest>> xoneIndexListOfList = xoneIndexRequestList.stream()
.collect(Collectors.groupingBy(it -> counter.getAndIncrement() / xoneIndicesPacketSize))
.values();
在第二步中,我将遍历此列表并将每个数据包作为输入传递给某个 REST 端点,使用以下代码。
return xoneIndexListOfList.stream()
.map(e -> {
return getResponseBody(creditIndicesApiClient.creditIndicesSearch7(e));
}).collect(Collectors.toList());
从上面的代码中,我们可以看到 6 个调用将转到上面的 API(每个数据包 i.e.one),所以这里我的问题是如果有一些部分会发生什么失败?
场景:
假设数据包 1 和 2 通过,数据包 3 失败(即 API 无法 return 第三个数据包的数据)
**问题:**
- 在上面的场景中会进行到4和5包吗?如果是,那么假设数据包 4 和 5 也通过了,所以总共数据包 1,2,4,5 通过但 3 失败,那么上面代码的 return 输出是什么?
- 如果否,他们将只return编辑数据包 1 和 2 的输出,因为它已经通过并且数据包 3 的请求失败?
- 或者如果任何一个数据包在任何时候失败,它是否将每个数据包标记为失败,处理这个数据包列表?
编辑 - 添加完整方法
@Override
public List<XoneIndexResponse> creditIndicesSearch7(List<XoneIndexRequest> xoneIndexRequestList) {
try {
final AtomicInteger counter = new AtomicInteger();
final Collection<List<XoneIndexRequest>> xoneIndexListOfList = xoneIndexRequestList.stream()
.collect(Collectors.groupingBy(it -> counter.getAndIncrement() / xoneIndicesPacketSize))
.values();
return xoneIndexListOfList.stream()
.map(e -> {
return getResponseBody(creditIndicesApiClient.creditIndicesSearch7(e));
}).collect(Collectors.toList());
} catch (Exception e) {
log.error("error while retrieving data from x-one! for Index", e);
return emptyList();
}
}
当发生未处理的异常时,流的处理立即停止。
所以除非你处理异常,否则你不会得到一个列表。
我们可以用下面的代码进行测试:
Stream.of(6, 0, 7)
.map(integer -> 5/integer + integer)
.forEach(System.out::println);
输出:
6
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.example.demo.DemoApplication.lambda$main(DemoApplication.java:244)
at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:193)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
at com.example.demo.DemoApplication.main(DemoApplication.java:245)
这取决于我们要做什么,但我们可以通过以下方式解决它:
Stream.of(6, 0, 7)
.map(integer -> {
try{
return Optional.of(5/integer + integer);
}catch (ArithmeticException e){
return Optional.empty();
}
})
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(System.out::println);
输出:
6
7
编辑:
当整个事情都包含在 try
范围内时,从流中抛出的异常将传播并在 catch
范围内被捕获。
所以在你的情况下,一个错误将被打印到日志中并且 emptyList()
将被调用。
我有一个总共 115 个输入的列表,使用下面的代码将其分成 20 个输入的数据包大小,这意味着 xoneIndexListOfList
有 6 个元素,大小分别为 [ [20], [20], [20], [20], [20], [15] ]
。
final AtomicInteger counter = new AtomicInteger();
final Collection<List<XoneIndexRequest>> xoneIndexListOfList = xoneIndexRequestList.stream()
.collect(Collectors.groupingBy(it -> counter.getAndIncrement() / xoneIndicesPacketSize))
.values();
在第二步中,我将遍历此列表并将每个数据包作为输入传递给某个 REST 端点,使用以下代码。
return xoneIndexListOfList.stream()
.map(e -> {
return getResponseBody(creditIndicesApiClient.creditIndicesSearch7(e));
}).collect(Collectors.toList());
从上面的代码中,我们可以看到 6 个调用将转到上面的 API(每个数据包 i.e.one),所以这里我的问题是如果有一些部分会发生什么失败?
场景: 假设数据包 1 和 2 通过,数据包 3 失败(即 API 无法 return 第三个数据包的数据)
**问题:**
- 在上面的场景中会进行到4和5包吗?如果是,那么假设数据包 4 和 5 也通过了,所以总共数据包 1,2,4,5 通过但 3 失败,那么上面代码的 return 输出是什么?
- 如果否,他们将只return编辑数据包 1 和 2 的输出,因为它已经通过并且数据包 3 的请求失败?
- 或者如果任何一个数据包在任何时候失败,它是否将每个数据包标记为失败,处理这个数据包列表?
编辑 - 添加完整方法
@Override
public List<XoneIndexResponse> creditIndicesSearch7(List<XoneIndexRequest> xoneIndexRequestList) {
try {
final AtomicInteger counter = new AtomicInteger();
final Collection<List<XoneIndexRequest>> xoneIndexListOfList = xoneIndexRequestList.stream()
.collect(Collectors.groupingBy(it -> counter.getAndIncrement() / xoneIndicesPacketSize))
.values();
return xoneIndexListOfList.stream()
.map(e -> {
return getResponseBody(creditIndicesApiClient.creditIndicesSearch7(e));
}).collect(Collectors.toList());
} catch (Exception e) {
log.error("error while retrieving data from x-one! for Index", e);
return emptyList();
}
}
当发生未处理的异常时,流的处理立即停止。
所以除非你处理异常,否则你不会得到一个列表。
我们可以用下面的代码进行测试:
Stream.of(6, 0, 7)
.map(integer -> 5/integer + integer)
.forEach(System.out::println);
输出:
6
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.example.demo.DemoApplication.lambda$main(DemoApplication.java:244)
at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:193)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
at com.example.demo.DemoApplication.main(DemoApplication.java:245)
这取决于我们要做什么,但我们可以通过以下方式解决它:
Stream.of(6, 0, 7)
.map(integer -> {
try{
return Optional.of(5/integer + integer);
}catch (ArithmeticException e){
return Optional.empty();
}
})
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(System.out::println);
输出:
6
7
编辑:
当整个事情都包含在 try
范围内时,从流中抛出的异常将传播并在 catch
范围内被捕获。
所以在你的情况下,一个错误将被打印到日志中并且 emptyList()
将被调用。