我正在尝试在其下编写带有XML解析器的复杂的实体发射系统,并且无法正确了解背压。目前,我有以下接口(我的解析器实现):
public interface Reader<T> {
void read(T chunk, Recorder recorder) throws FatalException;
default Flowable<Object> toFlowable(Flowable<T> input) {
return input.flatMap(chunk -> {
Recorder recorder = new Accumulator();
read(chunk, recorder);
var combination = Stream.concat(recorder.values.stream(), recorder.errors.stream().map(ErrorEvent::new))
.collect(Collectors.toList());
return Flowable.fromIterable(combination);
}, false, 128, 1); // note the buffer size of one
}
}
其中块是实现中的单个XML标记,因此我的解析器可能在一次调用时记录0..1个项目。我想完全暂停阅读,直到订阅者请求新项目。
我以此方式进行测试:
var reader = new XmlReader(handlers);
// collection of XML tags in form of
// <root><child>content</child><child>content</child>...
var source = Flowable.fromIterable(standardDocument());
var stream = reader.toFlowable(source);
stream.subscribe(new DisposableSubscriber<>() {
@Override
protected void onStart() {
request(1);
}
@Override
public void onNext(Object o) {}
@Override
public void onError(Throwable t) {}
@Override
public void onComplete() {}
});
verify(root, times(1)).getChildHandler("child"); // means only one <child> tag was encountered
但是,测试失败并显示以下断言错误:
entityHandler.getChildHandler("child");
Wanted 1 time:
-> at redacted.reader.xml.XmlReaderTest.respectsBackpressure(XmlReaderTest.java:156)
But was 18 times. Undesired invocation:
-> at redacted.reader.xml.XmlReader.lambda$handleStart$1(XmlReader.java:52)
“ 18次”是最大数目,无论我的伪造文档将重复<child>
标签多少次,因此感觉就像有一个缓冲区。但是,如您在上面的代码中所见,我将缓冲区设置为1的大小。我错过了什么?如何使解析器暂停直到订阅者请求新项目?