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

Introduce explicit re-fetch query for mutation operation. #504

Merged
merged 15 commits into from
May 27, 2017
Prev Previous commit
Next Next commit
Update
  • Loading branch information
sav007 committed May 16, 2017
commit cace53ae18498153bda69c18cbdf79a52b5bfa4b
Original file line number Diff line number Diff line change
Expand Up @@ -156,21 +156,35 @@ Response cachedHttpResponse(String cacheKey) throws IOException {
private <D extends Operation.Data, T, V extends Operation.Variables> RealApolloCall<T> newCall(
@Nonnull Operation<D, T, V> operation) {
ResponseFieldMapper responseFieldMapper = responseFieldMapper(operation);
return new RealApolloCall<T>(operation, serverUrl, httpCallFactory, httpCache, defaultHttpCachePolicy, moshi,
responseFieldMapper, customTypeAdapters, apolloStore, defaultCacheControl, defaultCacheHeaders,
dispatcher, logger, applicationInterceptors, Collections.<OperationName>emptyList());
return RealApolloCall.<T>builder()
.operation(operation)
.serverUrl(serverUrl)
.httpCallFactory(httpCallFactory)
.httpCache(httpCache)
.httpCachePolicy(defaultHttpCachePolicy)
.moshi(moshi)
.responseFieldMapper(responseFieldMapper)
.customTypeAdapters(customTypeAdapters)
.apolloStore(apolloStore)
.cacheControl(defaultCacheControl)
.cacheHeaders(defaultCacheHeaders)
.dispatcher(dispatcher)
.logger(logger)
.applicationInterceptors(applicationInterceptors)
.refetchQueryNames(Collections.<OperationName>emptyList())
.build();
}

private ResponseFieldMapper responseFieldMapper(Operation operation) {
ResponseFieldMapper responseFieldMapper;
Optional<ResponseFieldMapper> responseFieldMapper;
synchronized (responseFieldMapperPool) {
responseFieldMapper = responseFieldMapperPool.get(operation.getClass());
if (responseFieldMapper == null) {
responseFieldMapper = operation.responseFieldMapper();
responseFieldMapperPool.put(operation.getClass(), responseFieldMapper);
responseFieldMapper = Optional.fromNullable(responseFieldMapperPool.get(operation.getClass()));
if (!responseFieldMapper.isPresent()) {
responseFieldMapper = Optional.of(operation.responseFieldMapper());
responseFieldMapperPool.put(operation.getClass(), responseFieldMapper.get());
}
}
return responseFieldMapper;
return responseFieldMapper.get();
}

@SuppressWarnings("WeakerAccess") public static class Builder {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.apollographql.apollo.api.Mutation;
import com.apollographql.apollo.api.OperationName;
import com.apollographql.apollo.cache.CacheHeaders;
import com.apollographql.apollo.cache.normalized.CacheControl;

import javax.annotation.Nonnull;

Expand All @@ -22,8 +21,6 @@ public interface ApolloMutationCall<T> extends ApolloCall<T> {
*/
@Nonnull ApolloMutationCall<T> refetchQueries(@Nonnull OperationName... operationNames);

@Nonnull @Override ApolloMutationCall<T> cacheControl(@Nonnull CacheControl cacheControl);

@Nonnull @Override ApolloMutationCall<T> cacheHeaders(@Nonnull CacheHeaders cacheHeaders);

@Nonnull @Override ApolloMutationCall<T> clone();
Expand All @@ -35,8 +32,8 @@ interface Factory {
/**
* Creates and prepares a new {@link ApolloMutationCall} call.
*
* @param query the operation which needs to be performed
* @return prepared {@link ApolloQueryCall} call to be executed at some point in the future
* @param mutation the mutation which needs to be performed
* @return prepared {@link ApolloMutationCall} call to be executed at some point in the future
*/
<D extends Mutation.Data, T, V extends Mutation.Variables> ApolloMutationCall<T> mutate(
@Nonnull Mutation<D, T, V> mutation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,26 +64,26 @@ public final class RealApolloCall<T> implements ApolloQueryCall<T>, ApolloMutati
final AtomicBoolean executed = new AtomicBoolean();
volatile boolean canceled;

public RealApolloCall(Operation operation, HttpUrl serverUrl, Call.Factory httpCallFactory, HttpCache httpCache,
HttpCachePolicy.Policy httpCachePolicy, Moshi moshi, ResponseFieldMapper responseFieldMapper,
Map<ScalarType, CustomTypeAdapter> customTypeAdapters, ApolloStore apolloStore, CacheControl cacheControl,
CacheHeaders cacheHeaders, ExecutorService dispatcher, ApolloLogger logger,
List<ApolloInterceptor> applicationInterceptors, List<OperationName> refetchQueryNames) {
this.operation = operation;
this.serverUrl = serverUrl;
this.httpCallFactory = httpCallFactory;
this.httpCache = httpCache;
this.httpCachePolicy = httpCachePolicy;
this.moshi = moshi;
this.responseFieldMapper = responseFieldMapper;
this.customTypeAdapters = customTypeAdapters;
this.apolloStore = apolloStore;
this.cacheControl = cacheControl;
this.cacheHeaders = cacheHeaders;
this.dispatcher = dispatcher;
this.logger = logger;
this.applicationInterceptors = applicationInterceptors;
this.refetchQueryNames = refetchQueryNames;
public static <T> Builder<T> builder() {
return new Builder<>();
}

private RealApolloCall(Builder<T> builder) {
this.operation = builder.operation;
this.serverUrl = builder.serverUrl;
this.httpCallFactory = builder.httpCallFactory;
this.httpCache = builder.httpCache;
this.httpCachePolicy = builder.httpCachePolicy;
this.moshi = builder.moshi;
this.responseFieldMapper = builder.responseFieldMapper;
this.customTypeAdapters = builder.customTypeAdapters;
this.apolloStore = builder.apolloStore;
this.cacheControl = builder.cacheControl;
this.cacheHeaders = builder.cacheHeaders;
this.dispatcher = builder.dispatcher;
this.logger = builder.logger;
this.applicationInterceptors = builder.applicationInterceptors;
this.refetchQueryNames = builder.refetchQueryNames;
interceptorChain = prepareInterceptorChain(operation);
}

Expand Down Expand Up @@ -159,24 +159,23 @@ public RealApolloCall(Operation operation, HttpUrl serverUrl, Call.Factory httpC

@Nonnull @Override public RealApolloCall<T> httpCachePolicy(@Nonnull HttpCachePolicy.Policy httpCachePolicy) {
if (executed.get()) throw new IllegalStateException("Already Executed");
return new RealApolloCall<>(operation, serverUrl, httpCallFactory, httpCache,
checkNotNull(httpCachePolicy, "httpCachePolicy == null"), moshi, responseFieldMapper, customTypeAdapters,
apolloStore, cacheControl, cacheHeaders, dispatcher, logger, applicationInterceptors, refetchQueryNames);
return toBuilder()
.httpCachePolicy(checkNotNull(httpCachePolicy, "httpCachePolicy == null"))
.build();
}

@Nonnull @Override public RealApolloCall<T> cacheControl(@Nonnull CacheControl cacheControl) {
if (executed.get()) throw new IllegalStateException("Already Executed");
return new RealApolloCall<>(operation, serverUrl, httpCallFactory, httpCache, httpCachePolicy, moshi,
responseFieldMapper, customTypeAdapters, apolloStore, checkNotNull(cacheControl, "cacheControl == null"),
cacheHeaders, dispatcher, logger, applicationInterceptors, refetchQueryNames);
return toBuilder()
.cacheControl(checkNotNull(cacheControl, "cacheControl == null"))
.build();
}

@Nonnull @Override public RealApolloCall<T> cacheHeaders(@Nonnull CacheHeaders cacheHeaders) {
if (executed.get()) throw new IllegalStateException("Already Executed");
return new RealApolloCall<>(operation, serverUrl, httpCallFactory, httpCache, httpCachePolicy, moshi,
responseFieldMapper, customTypeAdapters, apolloStore, cacheControl,
checkNotNull(cacheHeaders, "cacheHeaders == null"), dispatcher, logger, applicationInterceptors,
refetchQueryNames);
return toBuilder()
.cacheHeaders(checkNotNull(cacheHeaders, "cacheHeaders == null"))
.build();
}

@Override public void cancel() {
Expand All @@ -189,16 +188,33 @@ responseFieldMapper, customTypeAdapters, apolloStore, checkNotNull(cacheControl,
}

@Override @Nonnull public RealApolloCall<T> clone() {
return new RealApolloCall<>(operation, serverUrl, httpCallFactory, httpCache, httpCachePolicy, moshi,
responseFieldMapper, customTypeAdapters, apolloStore, cacheControl, cacheHeaders, dispatcher, logger,
applicationInterceptors, refetchQueryNames);
return toBuilder().build();
}

@Nonnull @Override public ApolloMutationCall<T> refetchQueries(@Nonnull OperationName... operationNames) {
if (executed.get()) throw new IllegalStateException("Already Executed");
return new RealApolloCall<>(operation, serverUrl, httpCallFactory, httpCache, httpCachePolicy, moshi,
responseFieldMapper, customTypeAdapters, apolloStore, cacheControl, cacheHeaders, dispatcher, logger,
applicationInterceptors, Arrays.asList(checkNotNull(operationNames, "operationNames == null")));
return toBuilder()
.refetchQueryNames(Arrays.asList(checkNotNull(operationNames, "operationNames == null")))
.build();
}

public Builder<T> toBuilder() {
return RealApolloCall.<T>builder()
.operation(operation)
.serverUrl(serverUrl)
.httpCallFactory(httpCallFactory)
.httpCache(httpCache)
.httpCachePolicy(httpCachePolicy)
.moshi(moshi)
.responseFieldMapper(responseFieldMapper)
.customTypeAdapters(customTypeAdapters)
.apolloStore(apolloStore)
.cacheControl(cacheControl)
.cacheHeaders(cacheHeaders)
.dispatcher(dispatcher)
.logger(logger)
.applicationInterceptors(applicationInterceptors)
.refetchQueryNames(refetchQueryNames);
}

private ApolloInterceptorChain prepareInterceptorChain(Operation operation) {
Expand All @@ -214,4 +230,110 @@ private ApolloInterceptorChain prepareInterceptorChain(Operation operation) {

return new RealApolloInterceptorChain(operation, interceptors);
}

public static final class Builder<T> {
Operation operation;
HttpUrl serverUrl;
Call.Factory httpCallFactory;
HttpCache httpCache;
HttpCachePolicy.Policy httpCachePolicy;
Moshi moshi;
ResponseFieldMapper responseFieldMapper;
Map<ScalarType, CustomTypeAdapter> customTypeAdapters;
ApolloStore apolloStore;
CacheControl cacheControl;
CacheHeaders cacheHeaders;
ApolloInterceptorChain interceptorChain;
ExecutorService dispatcher;
ApolloLogger logger;
List<ApolloInterceptor> applicationInterceptors;
List<OperationName> refetchQueryNames;

public Builder<T> operation(Operation operation) {
this.operation = operation;
return this;
}

public Builder<T> serverUrl(HttpUrl serverUrl) {
this.serverUrl = serverUrl;
return this;
}

public Builder<T> httpCallFactory(Call.Factory httpCallFactory) {
this.httpCallFactory = httpCallFactory;
return this;
}

public Builder<T> httpCache(HttpCache httpCache) {
this.httpCache = httpCache;
return this;
}

public Builder<T> httpCachePolicy(HttpCachePolicy.Policy httpCachePolicy) {
this.httpCachePolicy = httpCachePolicy;
return this;
}

public Builder<T> moshi(Moshi moshi) {
this.moshi = moshi;
return this;
}

public Builder<T> responseFieldMapper(ResponseFieldMapper responseFieldMapper) {
this.responseFieldMapper = responseFieldMapper;
return this;
}

public Builder<T> customTypeAdapters(Map<ScalarType, CustomTypeAdapter> customTypeAdapters) {
this.customTypeAdapters = customTypeAdapters;
return this;
}

public Builder<T> apolloStore(ApolloStore apolloStore) {
this.apolloStore = apolloStore;
return this;
}

public Builder<T> cacheControl(CacheControl cacheControl) {
this.cacheControl = cacheControl;
return this;
}

public Builder<T> cacheHeaders(CacheHeaders cacheHeaders) {
this.cacheHeaders = cacheHeaders;
return this;
}

public Builder<T> interceptorChain(ApolloInterceptorChain interceptorChain) {
this.interceptorChain = interceptorChain;
return this;
}

public Builder<T> dispatcher(ExecutorService dispatcher) {
this.dispatcher = dispatcher;
return this;
}

public Builder<T> logger(ApolloLogger logger) {
this.logger = logger;
return this;
}

public Builder<T> applicationInterceptors(List<ApolloInterceptor> applicationInterceptors) {
this.applicationInterceptors = applicationInterceptors;
return this;
}

public Builder<T> refetchQueryNames(List<OperationName> refetchQueryNames) {
this.refetchQueryNames = refetchQueryNames;
return this;
}

Builder() {
}

public RealApolloCall<T> build() {
return new RealApolloCall<>(this);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ private Rx2Apollo() {
/**
* Converts an {@link ApolloQueryWatcher} to an asynchronous Observable.
*
* @param watcher the ApolloWatcher to convert.
* @param watcher the ApolloQueryWatcher to convert.
* @param <T> the value type
* @return the converted Observable
* @throws NullPointerException if watcher == null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ private RxApollo() {
* Converts an {@link ApolloQueryWatcher} into an Observable. Honors the back pressure from downstream with the back
* pressure strategy {@link rx.Emitter.BackpressureMode#LATEST}.
*
* @param watcher the ApolloWatcher to convert
* @param watcher the ApolloQueryWatcher to convert
* @param <T> the value type
* @return the converted Observable
*/
Expand All @@ -50,7 +50,7 @@ public static <T> Observable<Response<T>> from(@Nonnull final ApolloQueryWatcher
/**
* Converts an {@link ApolloQueryWatcher} into an Observable.
*
* @param watcher the ApolloWatcher to convert
* @param watcher the ApolloQueryWatcher to convert
* @param backpressureMode the back pressure strategy to apply to the observable source.
* @param <T> the value type
* @return the converted Observable
Expand Down