@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(); } });
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; }
@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); }
@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;")); }