Skip to content
This repository has been archived by the owner on Dec 7, 2019. It is now read-only.

"The MaybeSource is empty" error occurs with persister #305

Open
jeonginc opened this issue Jan 15, 2018 · 6 comments
Open

"The MaybeSource is empty" error occurs with persister #305

jeonginc opened this issue Jan 15, 2018 · 6 comments

Comments

@jeonginc
Copy link

jeonginc commented Jan 15, 2018

In README.md, there's a sample code contains:

           .persister(new Persister<BufferedSource>() {
             @Override
             public Maybe<BufferedSource> read(Integer key) {
               if (dataIsCached) {
                 return Observable.fromCallable(() -> userImplementedCache.get(key));
               } else {
                 return Observable.**empty**();
               }
             }

With this reference code, I wrote my own persister like:

StoreBuilder.
    .key<ApiKey<API, Any>, Any>()
    .persister(object : Persister<Any, ApiKey<API, Any>> {
        override fun read(key: ApiKey<API, Any>): Maybe<Any> {
            if (key.haveLocal()) {
                return key.local()
            }
            // Nothing is saved for the key, returns empty
            return Maybe.empty()
        }
        ....
    })
    .fetcher({ it.request(api).computation() })
    .open()

and then i made a request like
store.fetch(key)

But it occurs java.util.NoSuchElementException: The MaybeSource is empty

I followed inside RealInternalStore.java,
there's weird code in RealInternalStore.response()

    @Nonnull
    Single<Parsed> response(@Nonnull final Key key) {
        return fetcher()
                ...
                        .flatMap(aBoolean -> readDisk(key).toSingle()))
                ...

readDisk() doesn't have code for handling empty state,
readDisk(key).toSingle() can occurs NoSuchElementException

How can I return "empty, there's no saved response" state in Persister.read()?

@Xiadalei
Copy link

Xiadalei commented Jan 16, 2018

That's what confuses me most, why return Maybe when you should convert it to Single?

@digitalbuddha
Copy link
Contributor

I'm confused how it can be empty when you do store.fetch. Fetch should get a new element from your fetcher save it to disk and then return. Could you post a failing test or sample please.

@Xiadalei
Copy link

Xiadalei commented Mar 30, 2018

@digitalbuddha What if what the fetch result is empty from very beginning?

What we normally would do is get and the get would fetch when it gets nothing (that's Maybe.empty()) from persister. That what the API designed for.

Now, if we could fetch nothing from network etc. (of course there's a response but nothing we could write into persister and use case like this is not rare), the fetch would let persister write (which would write nothing) and read( also read nothing just like when it get) and error is coming?

One may say hey, why don't you return a empty object (not null) from persister for the situation like this. If we do that, when we get, we get a empty object and that's all, we have to do the "get then fetch" ourselves which should be done by store itself.

So the problem is why should we assume that fetch could always get new stuff and not empty?

@jeonginc
Copy link
Author

jeonginc commented Apr 4, 2018

Using Maybe.just(Unit) for empty state inside Persister will remove Fetcher's result.
So, i have no choice but to implement my own persister on Fetcher like

StoreBuilder.
    .key<ApiKey<API, Any>, Any>()
    .fetcher({ key ->
        key.load(context)
                .switchIfEmpty(key.fetch(api))
                .switchIfEmpty(Maybe.error<Any>(Exception("No response")))
                .doOnSuccess { key.save(context, it).subscribe() }
                .toSingle()
    })
    .open()

@LukasVykuka
Copy link

LukasVykuka commented Apr 28, 2018

I have same problem - how to distinguish between "not found in cache" and "not found on API" (both should return list of items) in persister's read method without throwing this excepion?

@digitalbuddha
Copy link
Contributor

Thanks for explaining! We are working on store4 and will make an elegant solution. I'll post possible solutions here. Open to suggestions as well

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants