-
Notifications
You must be signed in to change notification settings - Fork 656
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
Change CacheControl to Interceptor based Fetcher #556
Conversation
cc @kompfner @martijnwalraven for thoughts from iOS perspective |
@sav007 @digitalbuddha Let me know what you think about going in this direction, if things seem good from a conceptual perspective, I'll move forward with writing all the tests, documentation, and code cleanup |
I love this idea, clean and flexible |
|
||
public interface Fetcher { | ||
|
||
ApolloInterceptor create(ApolloLogger logger); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should it be renamed for clarity to smth provideInterceptor
?
import com.apollographql.apollo.interceptor.ApolloInterceptor; | ||
import com.apollographql.apollo.internal.util.ApolloLogger; | ||
|
||
public interface Fetcher { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it be called ResponseFetcher
?
I like the concept but am not crazy with the builder method name .fetcher(ApolloFetchers.CACHE_FIRST) feels weird. It's not a fetcher but a cache policy or a fetch policy. When I see a builder method called fetcher I expect to pass in something that has an implementation for fetch. |
Ok next time I'll look at code and not just description of pr. It does fetch! I'm with Ivan love it. |
|
||
private synchronized void handleNetworkError(ApolloException exception) { | ||
networkException = Optional.of(exception); | ||
dispatch(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we consider to not dispatch if result if it was canceled (disposed)
We need to make sure that |
8062820
to
69fc87e
Compare
f7513a5
to
ef5bd57
Compare
ef5bd57
to
5193bd0
Compare
5193bd0
to
da88541
Compare
Divided this into runtime changes, rx changes, and test changes.
I don't think the WeakReference approach is a good idea. It as causing issues in tests, and probably could surface other issues. Let's fix 560 in a separate PR to avoid doing too much here. There is a slight change in behavior of cancellation:
The change is in point (3) which would previously trigger onError. This felt weird to me, as if I call I also more aggressively check if dispose has been called on interceptors to avoid doing unnecessary work. |
ba6a547
to
0660a7c
Compare
f2547db
to
5595cb0
Compare
ae780cf
to
c7af7cc
Compare
import com.apollographql.apollo.internal.fetcher.NetworkFirstFetcher; | ||
import com.apollographql.apollo.internal.fetcher.NetworkOnlyFetcher; | ||
|
||
public final class ApolloResponseFetcher { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: should it be named ApolloResponseFetchers
, like in java Executors
, in Rx Schedulers
?
public final boolean fetchFromCache; | ||
public final CacheHeaders cacheHeaders; | ||
|
||
public static final FetchOptions NETWORK = new FetchOptions(false, CacheHeaders.NONE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: NETWORK_ONLY
?
Just curios if |
some code review changes fix runtime checkstyle runtime fix remove weak reference changes runtime changes
fixes to rx
remove unused test test fixes test changes mend
c7af7cc
to
f47f63c
Compare
While, I believe it would be possible to write a custom Fetcher (ApolloInterceptor) that could resolve from network / cache, ideally user's can just proceed with the combo of CacheInterceptor/ParseInterceptor/ServerIntercept that we already assemble. It seemed to me the easiest way to pass a configuration to |
We should update java doc for Callback: |
And we need to mention that |
* | ||
* @param cacheControl the CacheControl strategy to set | ||
* @param fetcher the {@link ResponseFetcher} to use. | ||
* @return The ApolloCall object with the provided CacheControl strategy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@return The ApolloCall object with the provided CacheControl strategy
->
@return The ApolloCall object with the provided fetch strategy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just couple comments on JavaDocs. Other than that lgtm
return this; | ||
} | ||
|
||
/** | ||
* Set the default {@link CacheHeaders} strategy that will be passed | ||
* Set the default {@link ResponseFetcher} that will create a {@link ResponseFetcher} to be passed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
smth wrong here ResponseFetcher
will create a ResponseFetcher
@@ -66,30 +63,39 @@ private Rx2Apollo() { | |||
} | |||
|
|||
/** | |||
* Converts an {@link ApolloCall} to a synchronous Single. | |||
* Converts an {@link ApolloCall} to an {@link Observable}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we should provide more info why it's Observable
on cache and network fetch strategy example
@@ -81,30 +79,50 @@ private RxApollo() { | |||
} | |||
|
|||
/** | |||
* Converts an {@link ApolloCall} to a Single. | |||
* Converts an {@link ApolloCall} to a Observable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the same as above
@sav007 I guess I should bump the version number again since this is a breaking change? Not sure we have enough new stuff since that last release to publish an official release |
but we have't released 0.4.0 yet, why do we need to bump it to 0.5.0? |
Ok, I wasn't sure if we were trying to keep snapshot builds being semver capatabilble. But if not, let's wait to bump! |
This reverts commit f59e15b.
Motivation
The interceptor architecture we use for executing a request is loosely similar to the future direction Apollo JS is going: https://github.com/apollographql/apollo-fetch. If I understand correctly, the vision is that Apollo Fetch will make it easy to write fetch policies like
CACHE_FIRST
or more complicated policies likeCACHE_FIRST_IF_NOT_STALE_BUT_IF_NO_NETWORK_ALLOW_STALE
.However, shipping with every possible fetch strategy is impossible -- thus our current
CacheControl
approach based on a set of enums, could be made more flexible. This PR proposes makingCacheControl
anApolloInterceptor
that contains logic of how to fetch the request. (And changes the name toFetcher
to better align with JS).Fetcher
ApolloInterceptor
FetchOptions
to configure fetching preferencesCacheHeaders
and a booleanfetchFromCache
to control how the data will be fetchedfetchFromCache = true
and catching an exception. If exception it will try to proceed withfetchFromCache = false
Benefits
ApolloCacheInterceptor
has less logic - all fetching logic is contained in theFetcher
Mutli-response
Notably this PR enables a fetcher to respond multiple times. The rationale behind this is that when you use Apollo with a persistent sql cache, currently the only fetch policy that works is
NETWORK_FIRST
which negates the value of the sql / in memory cache. This is because if you useCACHE_FIRST
, after the first cache population, the data will never be automatically refreshed. This could be handled with some sort of "staleness" system, but again, this would result in the cache data always being held until it is stale. Rather, it would be useful to allow a request to fulfill from cache first, and then also, fetch updated data from the network.This does complicate the callback API, particularly with ApolloRx, as we need to know when a request will return no more data (
onCompleted
).This PR ships with one double response fetch policy
CACHE_AND_NETWORK
.Additional work
Previous discussions: https://airbnb.quip.com/BVbnAztIGoLm
closes #432