I'm writing some kind of middleware HTTP proxy with cache. The workflow is:
- Client requests this proxy for resource
- If resurce exists in cache, proxy returns it
- If resource wasn't found, proxy fetching remote resource and returns to the user. Proxy saves this resource to the cache on data loading.
My interfaces have Publisher<ByteBuffer>
stream for remote resource, cache which accepts Publisher<ByteBuffer>
to save, and clients' connection which accepts Publisher<ByteBuffer>
as a response:
// remote resource
interface Resource {
Publisher<ByteBuffer> fetch();
}
// cache
interface Cache {
Completable save(Publisher<ByteBuffer> data);
}
// clien response connection
interface Connection {
Completable send(Publisher<ByteBuffer> data);
}
My problem is that I need to lazy save this stream of byte buffers to cache when sending the response to the client, so the client should be responsible for requesting ByteByffer
chunks from remote resource, not cache.
I tried to use Publisher::cache
method, but it's not a good choice for me, because it keeps all received data in memory, it's not acceptable, since cached data may be few GB of size.
As a workaround, I created Subject
filled by next items received from Resource
:
private final Cache cache;
private final Connection out;
Completable proxy(Resource res) {
Subject<ByteBuffer> mirror = PublishSUbject.create();
return Completable.mergeArray(
out.send(res.fetch().doOnNext(mirror::onNext),
cache.save(mirror.toFlowable(BackpressureStrategy.BUFFER))
);
}
Is it possible to reuse same Publisher
without caching items in memory, and where only one subscriber will be responsible for requesting items from publisher?