/** * <p>Adds provided {@link ApolloMutationCall} that is currently in progress.</p> * * <p><b>Note</b>: This method needs to be called right before an apolloCall is executed.</p> */ void registerMutationCall(@NotNull ApolloMutationCall apolloMutationCall) { checkNotNull(apolloMutationCall, "apolloMutationCall == null"); OperationName operationName = apolloMutationCall.operation().name(); registerCall(activeMutationCalls, operationName, apolloMutationCall); }
/** * <p>Adds provided {@link ApolloPrefetch} that is currently in progress.</p> * * <p><b>Note</b>: This method needs to be called right before a prefetch call is executed.</p> */ void registerPrefetchCall(@NotNull ApolloPrefetch apolloPrefetch) { checkNotNull(apolloPrefetch, "apolloPrefetch == null"); OperationName operationName = apolloPrefetch.operation().name(); registerCall(activePrefetchCalls, operationName, apolloPrefetch); }
/** * <p>Adds provided {@link ApolloQueryWatcher} that is currently in progress.</p> * * <p><b>Note</b>: This method needs to be called right before * {@link ApolloQueryWatcher#enqueueAndWatch(ApolloCall.Callback)}.</p> */ void registerQueryWatcher(@NotNull ApolloQueryWatcher queryWatcher) { checkNotNull(queryWatcher, "queryWatcher == null"); OperationName operationName = queryWatcher.operation().name(); registerCall(activeQueryWatchers, operationName, queryWatcher); }
/** * <p>Adds provided {@link ApolloQueryCall} that is currently in progress.</p> * * <p><b>Note</b>: This method needs to be called right before an apolloCall is executed.</p> */ void registerQueryCall(@NotNull ApolloQueryCall apolloQueryCall) { checkNotNull(apolloQueryCall, "apolloQueryCall == null"); OperationName operationName = apolloQueryCall.operation().name(); registerCall(activeQueryCalls, operationName, apolloQueryCall); }
/** * <p>Removes provided {@link ApolloMutationCall} that finished his execution, if it is found, else throws an * {@link AssertionError}.</p> * * If the removal operation is successful and no active running calls are found, then the registered * {@link ApolloCallTracker#idleResourceCallback} is invoked. * * <p><b>Note</b>: This method needs to be called right after an apolloCall is completed (whether successful or * failed).</p> */ void unregisterMutationCall(@NotNull ApolloMutationCall apolloMutationCall) { checkNotNull(apolloMutationCall, "apolloMutationCall == null"); OperationName operationName = apolloMutationCall.operation().name(); unregisterCall(activeMutationCalls, operationName, apolloMutationCall); }
/** * <p>Removes provided {@link ApolloQueryWatcher} that finished his execution, if it is found, else throws an * {@link AssertionError}.</p> * * If the removal operation is successful and no active running calls are found, then the registered * {@link ApolloCallTracker#idleResourceCallback} is invoked. * * <p><b>Note</b>: This method needs to be called right after an apolloCall is completed (whether successful or * failed).</p> */ void unregisterQueryWatcher(@NotNull ApolloQueryWatcher queryWatcher) { checkNotNull(queryWatcher, "queryWatcher == null"); OperationName operationName = queryWatcher.operation().name(); unregisterCall(activeQueryWatchers, operationName, queryWatcher); }
/** * <p>Removes provided {@link ApolloPrefetch} that finished his execution, if it is found, else throws an * {@link AssertionError}.</p> * * If the removal operation is successful and no active running calls are found, then the registered * {@link ApolloCallTracker#idleResourceCallback} is invoked. * * <p><b>Note</b>: This method needs to be called right after a prefetch call is completed (whether successful or * failed).</p> */ void unregisterPrefetchCall(@NotNull ApolloPrefetch apolloPrefetch) { checkNotNull(apolloPrefetch, "apolloPrefetch == null"); OperationName operationName = apolloPrefetch.operation().name(); unregisterCall(activePrefetchCalls, operationName, apolloPrefetch); }
/** * <p>Removes provided {@link ApolloQueryCall} that finished his execution, if it is found, else throws an * {@link AssertionError}.</p> * * If the removal operation is successful and no active running calls are found, then the registered * {@link ApolloCallTracker#idleResourceCallback} is invoked. * * <p><b>Note</b>: This method needs to be called right after an apolloCall is completed (whether successful or * failed).</p> */ void unregisterQueryCall(@NotNull ApolloQueryCall apolloQueryCall) { checkNotNull(apolloQueryCall, "apolloQueryCall == null"); OperationName operationName = apolloQueryCall.operation().name(); unregisterCall(activeQueryCalls, operationName, apolloQueryCall); }
Call httpCall(Operation operation, CacheHeaders cacheHeaders, boolean writeQueryDocument) throws IOException { RequestBody requestBody = RequestBody.create(MEDIA_TYPE, httpRequestBody(operation, scalarTypeAdapters, writeQueryDocument)); Request.Builder requestBuilder = new Request.Builder() .url(serverUrl) .post(requestBody) .header(HEADER_ACCEPT_TYPE, ACCEPT_TYPE) .header(HEADER_CONTENT_TYPE, CONTENT_TYPE) .header(HEADER_APOLLO_OPERATION_ID, operation.operationId()) .header(HEADER_APOLLO_OPERATION_NAME, operation.name().name()) .tag(operation.operationId()); if (cachePolicy.isPresent()) { HttpCachePolicy.Policy cachePolicy = this.cachePolicy.get(); boolean skipCacheHttpResponse = "true".equalsIgnoreCase(cacheHeaders.headerValue( ApolloCacheHeaders.DO_NOT_STORE)); String cacheKey = httpRequestBody(operation, scalarTypeAdapters, true).md5().hex(); requestBuilder = requestBuilder .header(HttpCache.CACHE_KEY_HEADER, cacheKey) .header(HttpCache.CACHE_FETCH_STRATEGY_HEADER, cachePolicy.fetchStrategy.name()) .header(HttpCache.CACHE_EXPIRE_TIMEOUT_HEADER, String.valueOf(cachePolicy.expireTimeoutMs())) .header(HttpCache.CACHE_EXPIRE_AFTER_READ_HEADER, Boolean.toString(cachePolicy.expireAfterRead)) .header(HttpCache.CACHE_PREFETCH_HEADER, Boolean.toString(prefetch)) .header(HttpCache.CACHE_DO_NOT_STORE, Boolean.toString(skipCacheHttpResponse)); } return httpCallFactory.newCall(requestBuilder.build()); }
@Override public void onResponse(@NotNull final ApolloInterceptor.InterceptorResponse response) { Optional<Callback<T>> callback = responseCallback(); if (!callback.isPresent()) { logger.d("onResponse for operation: %s. No callback present.", operation().name().name()); return; } //noinspection unchecked callback.get().onResponse(response.parsedResponse.get()); }
@Override public ApolloQueryWatcher<T> enqueueAndWatch(@Nullable final ApolloCall.Callback<T> callback) { try { activate(Optional.fromNullable(callback)); } catch (ApolloCanceledException e) { if (callback != null) { callback.onCanceledError(e); } else { logger.e(e, "Operation: %s was canceled", operation().name().name()); } return this; } activeCall.enqueue(callbackProxy()); return this; }
@Override public void run() { callBack.onFetch(FetchSourceType.NETWORK); try { httpCall = httpCall(request.operation, request.cacheHeaders, request.sendQueryDocument); } catch (IOException e) { logger.e(e, "Failed to prepare http call for operation %s", request.operation.name().name()); callBack.onFailure(new ApolloNetworkException("Failed to prepare http call", e)); return; } httpCall.enqueue(new Callback() { @Override public void onFailure(@NotNull Call call, @NotNull IOException e) { if (disposed) return; logger.e(e, "Failed to execute http call for operation %s", request.operation.name().name()); callBack.onFailure(new ApolloNetworkException("Failed to execute http call", e)); } @Override public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { if (disposed) return; callBack.onResponse(new ApolloInterceptor.InterceptorResponse(response)); callBack.onCompleted(); } }); } });
@Override public void enqueue(@Nullable final Callback responseCallback) { try { activate(Optional.fromNullable(responseCallback)); } catch (ApolloCanceledException e) { if (responseCallback != null) { responseCallback.onFailure(e); } else { logger.e(e, "Operation: %s was canceled", operation().name().name()); } return; } ApolloInterceptor.InterceptorRequest request = ApolloInterceptor.InterceptorRequest.builder(operation).build(); interceptorChain.proceedAsync(request, dispatcher, interceptorCallbackProxy()); }
@Override public void onResponse(@NotNull ApolloInterceptor.InterceptorResponse response) { Response httpResponse = response.httpResponse.get(); try { Optional<Callback> callback = terminate(); if (!callback.isPresent()) { logger.d("onResponse for prefetch operation: %s. No callback present.", operation().name().name()); return; } if (httpResponse.isSuccessful()) { callback.get().onSuccess(); } else { callback.get().onHttpError(new ApolloHttpException(httpResponse)); } } finally { httpResponse.close(); } }
@Override public void onFailure(@NotNull ApolloException e) { Optional<Callback> callback = terminate(); if (!callback.isPresent()) { logger.e(e, "onFailure for prefetch operation: %s. No callback present.", operation().name().name()); return; } if (e instanceof ApolloHttpException) { callback.get().onHttpError((ApolloHttpException) e); } else if (e instanceof ApolloNetworkException) { callback.get().onNetworkError((ApolloNetworkException) e); } else { callback.get().onFailure(e); } }
@Override public void onCompleted() { Optional<Callback<T>> callback = terminate(); if (queryReFetcher.isPresent()) { queryReFetcher.get().refetch(); } if (!callback.isPresent()) { logger.d("onCompleted for operation: %s. No callback present.", operation().name().name()); return; } callback.get().onStatusEvent(StatusEvent.COMPLETED); }
@Override public void onFailure(@NotNull ApolloException e) { Optional<Callback<T>> callback = terminate(); if (!callback.isPresent()) { logger.d(e, "onFailure for operation: %s. No callback present.", operation().name().name()); return; } if (e instanceof ApolloHttpException) { callback.get().onHttpError((ApolloHttpException) e); } else if (e instanceof ApolloParseException) { callback.get().onParseError((ApolloParseException) e); } else if (e instanceof ApolloNetworkException) { callback.get().onNetworkError((ApolloNetworkException) e); } else { callback.get().onFailure(e); } }
@NotNull @Override public Optional<InterceptorRequest> apply(@NotNull Response response) { if (response.hasErrors()) { if (isPersistedQueryNotFound(response.errors())) { logger.w("GraphQL server couldn't find Automatic Persisted Query for operation name: " + request.operation.name().name() + " id: " + request.operation.operationId()); return Optional.of(request.toBuilder().sendQueryDocument(true).build()); } if (isPersistedQueryNotSupported(response.errors())) { // TODO how to disable Automatic Persisted Queries in future and how to notify user about this logger.e("GraphQL server doesn't support Automatic Persisted Queries"); return Optional.of(request.toBuilder().sendQueryDocument(true).build()); } } return Optional.absent(); } });
@Override public void enqueue(@Nullable final Callback<T> responseCallback) { try { activate(Optional.fromNullable(responseCallback)); } catch (ApolloCanceledException e) { if (responseCallback != null) { responseCallback.onCanceledError(e); } else { logger.e(e, "Operation: %s was canceled", operation().name().name()); } return; } ApolloInterceptor.InterceptorRequest request = ApolloInterceptor.InterceptorRequest.builder(operation) .cacheHeaders(cacheHeaders) .fetchFromCache(false) .optimisticUpdates(optimisticUpdates) .build(); interceptorChain.proceedAsync(request, dispatcher, interceptorCallbackProxy()); }
static ByteString httpRequestBody(Operation operation, ScalarTypeAdapters scalarTypeAdapters, boolean writeQueryDocument) throws IOException { Buffer buffer = new Buffer(); JsonWriter jsonWriter = JsonWriter.of(buffer); jsonWriter.setSerializeNulls(true); jsonWriter.beginObject(); jsonWriter.name("operationName").value(operation.name().name()); jsonWriter.name("variables").beginObject(); operation.variables().marshaller().marshal(new InputFieldJsonWriter(jsonWriter, scalarTypeAdapters)); jsonWriter.endObject(); jsonWriter.name("extensions") .beginObject() .name("persistedQuery") .beginObject() .name("version").value(1) .name("sha256Hash").value(operation.operationId()) .endObject() .endObject(); if (writeQueryDocument) { jsonWriter.name("query").value(operation.queryDocument().replaceAll("\\n", "")); } jsonWriter.endObject(); jsonWriter.close(); return buffer.readByteString(); } }