ArgumentCaptor.forClass(ApolloInterceptor.InterceptorResponse.class); verify(interceptorCallBack).onResponse(interceptorResponseArgumentCaptor.capture()); assertThat(interceptorResponseArgumentCaptor.getValue().parsedResponse.get().data()).isNotNull(); assertThat(interceptorResponseArgumentCaptor.getValue().parsedResponse.get().hasErrors()).isFalse();
@NotNull @Override public <D extends Operation.Data, T, V extends Operation.Variables> ApolloStoreOperation<Response<T>> read( @NotNull Operation<D, T, V> operation, @NotNull ResponseFieldMapper<D> responseFieldMapper, @NotNull ResponseNormalizer<Record> responseNormalizer, @NotNull CacheHeaders cacheHeaders) { return ApolloStoreOperation.emptyOperation(Response.<T>builder(operation).build()); }
public Response<T> build() { return new Response<>(this); } }
@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(); } });
@SuppressWarnings("unchecked") InterceptorResponse parse(Operation operation, okhttp3.Response httpResponse) throws ApolloHttpException, ApolloParseException { String cacheKey = httpResponse.request().header(HttpCache.CACHE_KEY_HEADER); if (httpResponse.isSuccessful()) { try { OperationResponseParser parser = new OperationResponseParser(operation, responseFieldMapper, scalarTypeAdapters, normalizer); Response parsedResponse = parser.parse(httpResponse.body().source()) .toBuilder() .fromCache(httpResponse.cacheResponse() != null) .build(); if (parsedResponse.hasErrors() && httpCache != null) { httpCache.removeQuietly(cacheKey); } return new InterceptorResponse(httpResponse, parsedResponse, normalizer.records()); } catch (Exception rethrown) { logger.e(rethrown, "Failed to parse network response for operation: %s", operation); closeQuietly(httpResponse); if (httpCache != null) { httpCache.removeQuietly(cacheKey); } throw new ApolloParseException("Failed to parse http response", rethrown); } } else { logger.e("Failed to parse network response: %s", httpResponse); throw new ApolloHttpException(httpResponse); } }
InterceptorResponse resolveFromCache(InterceptorRequest request) throws ApolloException { ResponseNormalizer<Record> responseNormalizer = apolloStore.cacheResponseNormalizer(); //noinspection unchecked ApolloStoreOperation<Response> apolloStoreOperation = apolloStore.read(request.operation, responseFieldMapper, responseNormalizer, request.cacheHeaders); Response cachedResponse = apolloStoreOperation.execute(); if (cachedResponse.data() != null) { logger.d("Cache HIT for operation %s", request.operation); return new InterceptorResponse(null, cachedResponse, responseNormalizer.records()); } logger.d("Cache MISS for operation %s", request.operation); throw new ApolloException(String.format("Cache miss for operation %s", request.operation)); }
@Test public void testUpdateWithInvalidID() { AWSAppSyncClient awsAppSyncClient = AppSyncTestSetupHelper.createAppSyncClientWithIAM(); assertNotNull(awsAppSyncClient); //Try to update a Post with a Fake ID final String updatedContent = "New content coming up @" + System.currentTimeMillis(); final String randomID = UUID.randomUUID().toString(); updatePost(awsAppSyncClient, randomID, updatedContent); assertNotNull(updatePostMutationResponse); assertNull(updatePostMutationResponse.data().updatePost()); assertNotNull(updatePostMutationResponse.errors()); Error error = updatePostMutationResponse.errors().get(0); assertNotNull(error); assertNotNull(error.message()); assertTrue(error.message().contains("Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ConditionalCheckFailedException;")); }
@Test public void onNonPersistedQueryErrorOriginalCallbackCalled() { ApolloInterceptorChain chain = mock(ApolloInterceptorChain.class); doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { ((ApolloInterceptor.CallBack) invocation.getArguments()[2]).onResponse( new ApolloInterceptor.InterceptorResponse( mockHttpResponse(), com.apollographql.apollo.api.Response.<MockOperation.Data>builder(new MockOperation()) .errors(Collections.singletonList(new Error("SomeOtherError", null, null))) .build(), Collections.<Record>emptyList() ) ); return null; } }).when(chain).proceedAsync( any(ApolloInterceptor.InterceptorRequest.class), any(Executor.class), any(ApolloInterceptor.CallBack.class) ); ApolloInterceptor.CallBack interceptorCallBack = mock(ApolloInterceptor.CallBack.class); interceptor.interceptAsync(request, chain, new TrampolineExecutor(), interceptorCallBack); verify(chain).proceedAsync(any(ApolloInterceptor.InterceptorRequest.class), any(Executor.class), any(ApolloInterceptor.CallBack.class)); ArgumentCaptor<ApolloInterceptor.InterceptorResponse> interceptorResponseArgumentCaptor = ArgumentCaptor.forClass(ApolloInterceptor.InterceptorResponse.class); verify(interceptorCallBack).onResponse(interceptorResponseArgumentCaptor.capture()); assertThat(interceptorResponseArgumentCaptor.getValue().parsedResponse.get().hasErrors()).isTrue(); }
@Override public void onResponse(@Nonnull ApolloInterceptor.InterceptorResponse response) { Log.v(TAG, "Thread:[" + Thread.currentThread().getId() +"]: onResponse()"); if(shouldRetry && ConflictResolutionHandler.conflictPresent(response.parsedResponse)) { //Set shouldRetry to false. Conflicts will only be attempted once. shouldRetry = false; //Found Conflict String conflictString = new JSONObject((Map)((Error) response.parsedResponse.get().errors().get(0)).customAttributes().get("data")).toString(); //Send a message to the Queue handler to retry Message message = new Message(); MutationInterceptorMessage msg = new MutationInterceptorMessage(originalMutation, currentMutation); msg.serverState = conflictString; msg.clientState = clientState; msg.requestIdentifier = recordIdentifier; msg.requestClassName = currentMutation.getClass().getSimpleName(); message.obj = msg; message.what = MessageNumberUtil.RETRY_EXEC; queueHandler.sendMessage(message); return; } //Call the customer's callback customerCallBack.onResponse(response); //Set the mutation as completed. appSyncOfflineMutationManager.setInProgressMutationAsCompleted(recordIdentifier); //Send a message to the QueueHandler to process the next mutation in queue Message message = new Message(); message.obj = new MutationInterceptorMessage(); message.what = MessageNumberUtil.SUCCESSFUL_EXEC; queueHandler.sendMessage(message); }
private InterceptorResponse resolveFromCache(InterceptorRequest request) throws ApolloException { ResponseNormalizer<Record> responseNormalizer = mApolloStore.cacheResponseNormalizer(); //noinspection unchecked GraphQLStoreOperation<Response> graphQLStoreOperation = mApolloStore.read(request.operation, responseFieldMapper, responseNormalizer, request.cacheHeaders); Response cachedResponse = graphQLStoreOperation.execute(); if (cachedResponse.data() != null) { logger.d("Cache HIT for operation %s", request.operation); return new InterceptorResponse(null, cachedResponse, responseNormalizer.records()); } logger.d("Cache MISS for operation %s", request.operation); throw new ApolloException(String.format("Cache miss for operation %s", request.operation)); }
static boolean conflictPresent(Optional<Response> parsedResponse) { //Check if the parsed response contains a conflict. //The contract for conflicts is that the response will contain an error with the //string "The conditional request failed" and will contain a data element. if (parsedResponse == null || parsedResponse.get() == null || parsedResponse.get().hasErrors() == false) { return false; } Log.d(TAG, "Thread:[" + Thread.currentThread().getId() +"]: onResponse -- found error"); if ( ! parsedResponse.get().errors().get(0).toString().contains("The conditional request failed") ) { return false; } Map customAttributes = ((Error) parsedResponse.get().errors().get(0)).customAttributes(); if (customAttributes == null || customAttributes.get("data") == null ) { return false; } return true; }
public void onMessage(final String msg) { try { //TODO: Check why is this being converted to a Response Body ResponseBody messageBody = ResponseBody.create(MediaType.parse("text/plain"), msg); OperationResponseParser<D, T> parser = new OperationResponseParser(subscription, subscription.responseFieldMapper(), scalarTypeAdapters, normalizer); Response<T> parsedResponse = parser.parse(messageBody.source()); if (parsedResponse.hasErrors()) { Log.w(TAG, "Errors detected in parsed subscription message"); } //TODO: Check why the message is this is not done in an else clause propagateMessageToAllListeners(parsedResponse); } catch (Exception rethrown) { Log.e(TAG, "Failed to parse: " + msg, rethrown); notifyErrorToAllListeners(new ApolloParseException("Failed to parse http response", rethrown)); } }
InterceptorResponse cacheMissResponse(Operation operation) { return new InterceptorResponse(null, Response.builder(operation).fromCache(true).build(), null); } }
ArgumentCaptor.forClass(ApolloInterceptor.InterceptorResponse.class); verify(interceptorCallBack).onResponse(interceptorResponseArgumentCaptor.capture()); assertThat(interceptorResponseArgumentCaptor.getValue().parsedResponse.get().hasErrors()).isFalse(); assertThat(interceptorResponseArgumentCaptor.getValue().parsedResponse.get().data()).isNotNull();
private InterceptorResponse resolveFromCache(InterceptorRequest request) throws ApolloException { ResponseNormalizer<Record> responseNormalizer = mApolloStore.cacheResponseNormalizer(); //noinspection unchecked GraphQLStoreOperation<Response> graphQLStoreOperation = mApolloStore.read(request.operation, responseFieldMapper, responseNormalizer, request.cacheHeaders); Response cachedResponse = graphQLStoreOperation.execute(); if (cachedResponse.data() != null) { logger.d("Cache HIT for operation %s", request.operation); return new InterceptorResponse(null, cachedResponse, responseNormalizer.records()); } logger.d("Cache MISS for operation %s", request.operation); throw new ApolloException(String.format("Cache miss for operation %s", request.operation)); }
public Response<T> build() { return new Response<>(this); } }
@SuppressWarnings("unchecked") public Response<W> parse(@NotNull Map<String, Object> payload) { checkNotNull(payload, "payload == null"); D data = null; if (payload.containsKey("data")) { Map<String, Object> buffer = (Map<String, Object>) payload.get("data"); RealResponseReader<Map<String, Object>> realResponseReader = new RealResponseReader<>(operation.variables(), buffer, new MapFieldValueResolver(), scalarTypeAdapters, responseNormalizer); data = (D) responseFieldMapper.map(realResponseReader); } List<Error> errors = null; if (payload.containsKey("errors")) { List<Map<String, Object>> errorPayloads = (List<Map<String, Object>>) payload.get("errors"); if (errorPayloads != null) { errors = new ArrayList<>(); for (Map<String, Object> errorPayload : errorPayloads) { errors.add(readError(errorPayload)); } } } return Response.<W>builder(operation) .data(operation.wrapData(data)) .errors(errors) .dependentKeys(responseNormalizer.dependentKeys()) .build(); }
ArgumentCaptor.forClass(ApolloInterceptor.InterceptorResponse.class); verify(interceptorCallBack).onResponse(interceptorResponseArgumentCaptor.capture()); assertThat(interceptorResponseArgumentCaptor.getValue().parsedResponse.get().hasErrors()).isFalse(); assertThat(interceptorResponseArgumentCaptor.getValue().parsedResponse.get().data()).isNotNull();