我为Rx专家提出了一个有趣的问题。我有一个关系表来保存有关事件的信息。事件由id,类型和时间组成。在我的代码中,我需要在某个可能很宽的时间范围内获取所有事件。
SELECT * FROM events WHERE event.time > :before AND event.time < :after ORDER BY time LIMIT :batch_size
为了提高可靠性并处理大型结果集,我分批查询大小的记录:batch_size。现在,我想写一个函数,给定:before和:after,将返回一个代表结果集的Observable。
Observable<Event> getEvents(long before, long after);
在内部,该函数应该批量查询数据库。沿着时间尺度的事件分布是未知的。因此,解决批处理的自然方法是: 获取前N条记录 如果结果不为空,请将最后一条记录的时间用作新的&#39;之前的&#39;参数,并获取下N个记录;否则终止 如果结果不为空,请将最后一条记录的时间用作新的&#39;之前的&#39;参数,并获取下N个记录;否则终止 ......等等(这个想法应该清楚)
我的问题是:
有没有办法用更高级别的Observable基元(filter / map / flatMap / scan / range等)来表达这个函数,而不明确地使用订阅者?
到目前为止,我没有做到这一点,而是提出以下简单的代码:
private void observeGetRecords(long before, long after, Subscriber<? super Event> subscriber) {
long start = before;
while (start < after) {
final List<Event> records;
try {
records = getRecordsByRange(start, after);
} catch (Exception e) {
subscriber.onError(e);
return;
}
if (records.isEmpty()) break;
records.forEach(subscriber::onNext);
start = Iterables.getLast(records).getTime();
}
subscriber.onCompleted();
}
public Observable<Event> getRecords(final long before, final long after) {
return Observable.create(subscriber -> observeGetRecords(before, after, subscriber));
}
这里,getRecordsByRange使用DBI实现SELECT查询并返回List。这段代码工作正常,但缺乏高级Rx结构的优雅。
注意:我知道我可以在DBI中通过SELECT查询返回Iterator。但是,我不想这样做,而是更喜欢运行多个查询。此计算不必是原子的,因此事务隔离问题无关紧要。
答案 0 :(得分:0)
虽然我不完全理解为什么你想要这样的时间重用,但我是这样做的:
BehaviorSubject<Long> start = BehaviorSubject.create(0L);
start
.subscribeOn(Schedulers.trampoline())
.flatMap(tstart ->
getEvents(tstart, tstart + twindow)
.publish(o ->
o.takeLast(1)
.doOnNext(r -> start.onNext(r.time))
.ignoreElements()
.mergeWith(o)
)
)
.subscribe(...)