Caching 来自流的网络调用ID的RxJava缓存结果(Redis或类似缓存解决方案)
我需要一些关于RxJava的帮助。我有一个昂贵的网络呼叫,它返回一个可观察的(elasticsearch的广告流)。我希望将每个发出的项目(广告)的ID属性缓存10分钟(在Redis中),以便接下来10分钟内的后续调用使用缓存中的ID从Elasticsearch获取广告 我有一些代码-这在某种程度上有助于实现预期的结果(归功于下面的博客.)。。 ) 它可以缓存流中每个发出的项,我需要的是将流中这些项的所有ID缓存为一个缓存条目 到目前为止,所有感兴趣的人都可以看到下面的代码片段Caching 来自流的网络调用ID的RxJava缓存结果(Redis或类似缓存解决方案),caching,rx-java,observable,Caching,Rx Java,Observable,我需要一些关于RxJava的帮助。我有一个昂贵的网络呼叫,它返回一个可观察的(elasticsearch的广告流)。我希望将每个发出的项目(广告)的ID属性缓存10分钟(在Redis中),以便接下来10分钟内的后续调用使用缓存中的ID从Elasticsearch获取广告 我有一些代码-这在某种程度上有助于实现预期的结果(归功于下面的博客.)。。 ) 它可以缓存流中每个发出的项,我需要的是将流中这些项的所有ID缓存为一个缓存条目 到目前为止,所有感兴趣的人都可以看到下面的代码片段 @Compone
@Component
public class CachingObservable {
private final Logger logger = LoggerFactory.getLogger(CachingObservable.class);
@Autowired
private AdvertService advertService;
// Each "network" response is different
private Long requestNumber = 0L;
public Observable<Advert> getAdverts(final String location) {
Observable<Advert> memory = memory(location);
Observable<Advert> network = network(location);
Observable<Advert> networkWithSave = network.doOnNext(new Action1<Advert>() {
@Override
public void call(Advert advert) {
List<Long> ids = new ArrayList<Long>();
ids.add(advert.getId());
advertService.cache(location, ids);
}
});
// Retrieve the first source with data - concat checks in order
Observable<Advert> source = Observable.concat(memory,
networkWithSave)
.first();
return source;
}
@组件
公共类CachingObservable{
私有最终记录器Logger=LoggerFactory.getLogger(CachingObservable.class);
@自动连线
私人广告服务;
//每个“网络”响应都是不同的
专用长请求编号=0L;
公共可观察的getAdverts(最终字符串位置){
可观察记忆=记忆(位置);
可观测网络=网络(位置);
Observable networkWithSave=network.doOnNext(新操作1(){
@凌驾
公共无效呼叫(广告){
列表ID=新的ArrayList();
add(advert.getId());
advertService.cache(位置、ID);
}
});
//使用数据检索第一个源-按顺序进行concat检查
可观测源=可观测的concat(内存,
网络(带存储)
.first();
返回源;
}
从我的理解来看,concat方法对我的用例并没有真正的用处。我需要知道网络可观察性是否/何时完成,我需要获取返回的广告id列表,并将它们存储在缓存中。我可以订阅网络可观察性-但我希望它是惰性的-只有在缓存中找不到数据时才调用。所以以下更新的代码不起作用..有什么想法吗
public Observable<Advert> getAdverts(final String location) {
Observable<Advert> memory = memory(location);
Observable<Advert> network = network(location);
Observable<Advert> networkWithSave = network.doOnNext(new Action1<Advert>() {
@Override
public void call(Advert advert) {
List<Long> ids = new ArrayList<Long>();
ids.add(advert.getId());
advertService.cache(location, ids);
}
});
// Retrieve the first source with data - concat checks in order
Observable<Advert> source = Observable.concat(memory,
networkWithSave)
.first();
Observable<List<Advert>> listObservable = networkWithSave.toList();
final Func1<List<Advert>, List<Long>> transformer = new Func1<List<Advert>, List<Long>>() {
@Override
public List<Long> call(List<Advert> adverts) {
List<Long> ids = new ArrayList<Long>();
for (Advert advert : adverts) {
ids.add(advert.getId());
}
return ids;
}
};
listObservable.map(transformer).subscribe(new Action1<List<Long>>() {
@Override
public void call(List<Long> ids) {
logger.info("ids {}", ids);
}
});
return source;
}
公共可观察的getAdverts(最终字符串位置){
可观察记忆=记忆(位置);
可观测网络=网络(位置);
Observable networkWithSave=network.doOnNext(新操作1(){
@凌驾
公共无效呼叫(广告){
列表ID=新的ArrayList();
add(advert.getId());
advertService.cache(位置、ID);
}
});
//使用数据检索第一个源-按顺序进行concat检查
可观测源=可观测的concat(内存,
网络(带存储)
.first();
Observable listObservable=networkWithSave.toList();
最终Func1转换器=新Func1(){
@凌驾
公共列表电话(列表广告){
列表ID=新的ArrayList();
用于(广告:广告){
add(advert.getId());
}
返回ID;
}
};
listObservable.map(transformer.subscribe)(新操作1(){
@凌驾
公共作废调用(列表ID){
logger.info(“ids{}”,ids);
}
});
返回源;
}
我要做的是使用filter来确保缓存的旧内容不会被释放,以便concat跳转到网络调用:
Subject<Pair<Long, List<Advert>>, Pair<Long, List<Advert>>> cache =
BehaviorSubject.create().toSerialized();
static final long RETENTION_TIME = 10L * 60 * 1000;
Observable<Advert> memory = cache.filter(v ->
v.first + RETENTION_TIME > System.currentTimeMillis()).flatMapIterable(v -> v);
Observable<Advert> network = ...
Observable<Advert> networkWithSave = network.toList().doOnNext(v ->
cache.onNext(Pair.of(System.currentTimeMillis(), v)).flatMapIterable(v -> v)
);
return memory.switchIfEmpty(network);
主题缓存=
BehaviorSubject.create().toSerialized();
静态最终长保留时间=10L*60*1000;
可观察内存=缓存.过滤器(v->
v、 first+RETENTION\u TIME>System.currentTimeMillis()).flatMapIterable(v->v);
可观测网络=。。。
Observable networkWithSave=network.toList().doOnNext(v->
cache.onNext(一对(System.currentTimeMillis(),v)).flatMapIterable(v->v)
);
返回内存。开关为空(网络);
好的,我想我有一个适合我的解决方案。我可能忽略了一些东西,但应该很简单吧
public Observable<Advert> getAdverts(final String location) {
Observable<Advert> memory = memory(location);
final Observable<Advert> network = network(location);
final Func1<List<Advert>, List<Long>> advertToIdTransformer = convertAdvertsToIds();
memory.isEmpty().subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean aBoolean) {
if (aBoolean.equals(Boolean.TRUE)) {
Observable<List<Long>> listObservable = network.toList().map(advertToIdTransformer);
listObservable.subscribe(new Action1<List<Long>>() {
@Override
public void call(List<Long> ids) {
logger.info("Caching ids {}", ids);
advertService.cache(location, ids);
}
});
}
}
});
// Retrieve the first source with data - concat checks in order
Observable<Advert> source = Observable.concat(memory,
network)
.first();
return source;
}
公共可观察的getAdverts(最终字符串位置){
可观察记忆=记忆(位置);
最终可观测网络=网络(位置);
final Func1 advertoidTransformer=convertAdvertoids();
memory.isEmpty().subscribe(新操作1()){
@凌驾
公共无效调用(布尔aBoolean){
if(aBoolean.equals(Boolean.TRUE)){
Observable listObservable=network.toList().map(AdvertoidTransformer);
listObservable.subscribe(新操作1(){
@凌驾
公共作废调用(列表ID){
info(“缓存id{}”,ids);
advertService.cache(位置、ID);
}
});
}
}
});
//使用数据检索第一个源-按顺序进行concat检查
可观测源=可观测的concat(内存,
(网络)
.first();
返回源;
}