Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature to not emit cache misses? #5791

Closed
edenman opened this issue Apr 9, 2024 · 6 comments
Closed

Feature to not emit cache misses? #5791

edenman opened this issue Apr 9, 2024 · 6 comments

Comments

@edenman
Copy link
Contributor

edenman commented Apr 9, 2024

Question

I see that there used to be a emitCacheMisses(Boolean) but it was removed and I don't see why.

Usecase: I'm doing a query with the default CacheFirst fetch policy + watch() so I can get updates if there are any. I'd like to have the flow emit when there's a valid value, or a network/server error. I don't care about cache misses. I can obviously filter the cache miss out myself with a mapNotNull or filter but I'm hoping there's a cleaner way to do that.

@BoD
Copy link
Contributor

BoD commented Apr 10, 2024

Hi!

Thanks for the feedback. The origin for this change was to stop throwing exceptions, as a means to simplify error handling overall.

In v3, cache misses would throw by default, with the possibility to emit empty data instead with emitCacheMisses(true). In v4, that is now the default.

With this change in place, we figured filtering the Flow is a simple and familiar way to ignore certain elements. For extra legibility it can be an extension:

fun <T : Operation.Data> Flow<ApolloResponse<T>>.ignoreCacheMisses(): Flow<ApolloResponse<T>> = filterNot {
  it.exception is CacheMissException
}


// ...

apolloClient.query(...)
  .watch()
  .ignoreCacheMisses()

@edenman
Copy link
Contributor Author

edenman commented Apr 10, 2024

yeah, I guess I mean that I would like some way to do this globally (at the ApolloClient.Builder step?).

Although I'm not sure how that would work if you did a query with fetchPolicy(FetchPolicy.CacheOnly)

@BoD
Copy link
Contributor

BoD commented Apr 11, 2024

That's good points! An API to do it globally might be something we want to add, but it would need to play nice with CacheOnly. Maybe it comes down to find a good descriptive name for it. In the meantime a good compromise for you may be something like an ApolloCall.watchData() extension that calls watch().ignoreCacheMisses()?

@martinbonnin
Copy link
Contributor

@edenman you can restore the global "ignore cache misses" using the below extension functions on ApolloClient.Builder:

fun ApolloClient.Builder.ignoreCacheMisses() = apply {
  addInterceptor(object : ApolloInterceptor {
    override fun <D : Operation.Data> intercept(request: ApolloRequest<D>, chain: ApolloInterceptorChain): Flow<ApolloResponse<D>> {
      return chain.proceed(request).filter { it.exception !is CacheMissException }
    }
  })
}

It's not 100% clear given the CacheOnly case above if we want to provide that option by default. Maybe we need different cases for single-shot queries vs multiple-responses Flow or something like that.

As it's always easier to add than remove, I'd prefer not adding a new API at this point. If you end up using the extension function and it works well for you, feel free to leave a comment and we'll revisit.

@martinbonnin
Copy link
Contributor

For the record, we just bumped into a use case for always emitting cache misses. Having the initial cache result allows to skip displaying a loading indicator while fetching the cache result.

I'm going to close this one for now. Anyone wanting a global ignoreCacheMisses(true) can use the extension function above:

fun ApolloClient.Builder.ignoreCacheMisses() = apply {
  addInterceptor(object : ApolloInterceptor {
    override fun <D : Operation.Data> intercept(request: ApolloRequest<D>, chain: ApolloInterceptorChain): Flow<ApolloResponse<D>> {
      return chain.proceed(request).filter { it.exception !is CacheMissException }
    }
  })
}

If this is proven to work well, we could add it as a first party extension but I'd rather wait for a bit more feedback before doing so.

Copy link
Contributor

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo Kotlin usage and allow us to serve you better.

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

No branches or pull requests

3 participants