diff --git a/aws-api/src/main/java/com/amplifyframework/api/aws/MutiAuthSubscriptionOperation.java b/aws-api/src/main/java/com/amplifyframework/api/aws/MutiAuthSubscriptionOperation.java index e9c9acee01..7ab97a3145 100644 --- a/aws-api/src/main/java/com/amplifyframework/api/aws/MutiAuthSubscriptionOperation.java +++ b/aws-api/src/main/java/com/amplifyframework/api/aws/MutiAuthSubscriptionOperation.java @@ -120,7 +120,7 @@ private void dispatchRequest() { }, response -> { if (response.hasErrors() && hasAuthRelatedErrors(response) && authTypes.hasNext()) { - // If there are auth-related errors, dispatch an ApiAuthException + // If there are auth-related errors queue up a retry with the next authType executorService.submit(this::dispatchRequest); } else { // Otherwise, we just want to dispatch it as a next item and @@ -139,8 +139,10 @@ private void dispatchRequest() { onSubscriptionComplete ); } else { - emitErrorAndCancelSubscription(new ApiException("Unable to establish subscription connection.", - AmplifyException.TODO_RECOVERY_SUGGESTION)); + emitErrorAndCancelSubscription(new ApiAuthException( + "Unable to establish subscription connection with any of the compatible auth types.", + "Check your application logs for detail." + )); } } diff --git a/aws-datastore/src/main/java/com/amplifyframework/datastore/syncengine/SubscriptionProcessor.java b/aws-datastore/src/main/java/com/amplifyframework/datastore/syncengine/SubscriptionProcessor.java index 62c8725aba..bf01e456d7 100644 --- a/aws-datastore/src/main/java/com/amplifyframework/datastore/syncengine/SubscriptionProcessor.java +++ b/aws-datastore/src/main/java/com/amplifyframework/datastore/syncengine/SubscriptionProcessor.java @@ -19,6 +19,7 @@ import androidx.annotation.VisibleForTesting; import com.amplifyframework.AmplifyException; +import com.amplifyframework.api.ApiException; import com.amplifyframework.api.graphql.GraphQLResponse; import com.amplifyframework.api.graphql.SubscriptionType; import com.amplifyframework.core.Action; @@ -40,6 +41,7 @@ import com.amplifyframework.datastore.appsync.AppSyncExtensions; import com.amplifyframework.datastore.appsync.AppSyncExtensions.AppSyncErrorType; import com.amplifyframework.datastore.appsync.ModelWithMetadata; +import com.amplifyframework.datastore.utils.ErrorInspector; import com.amplifyframework.hub.HubChannel; import com.amplifyframework.hub.HubEvent; import com.amplifyframework.logging.Logger; @@ -195,7 +197,9 @@ private boolean isExceptionType(DataStoreException exception, AppSyncErrorType e }, emitter::onNext, dataStoreException -> { - if (isExceptionType(dataStoreException, AppSyncErrorType.UNAUTHORIZED)) { + if (ErrorInspector.contains(dataStoreException, ApiException.ApiAuthException.class) || + isExceptionType(dataStoreException, AppSyncErrorType.UNAUTHORIZED)) + { // Ignore Unauthorized errors, so that DataStore can still be used even if the user is only // authorized to read a subset of the models. latch.countDown(); diff --git a/aws-datastore/src/main/java/com/amplifyframework/datastore/syncengine/SyncProcessor.java b/aws-datastore/src/main/java/com/amplifyframework/datastore/syncengine/SyncProcessor.java index 9b81528c04..181a97172f 100644 --- a/aws-datastore/src/main/java/com/amplifyframework/datastore/syncengine/SyncProcessor.java +++ b/aws-datastore/src/main/java/com/amplifyframework/datastore/syncengine/SyncProcessor.java @@ -18,6 +18,7 @@ import androidx.annotation.NonNull; import com.amplifyframework.api.ApiException; +import com.amplifyframework.api.ApiException.ApiAuthException; import com.amplifyframework.api.graphql.GraphQLRequest; import com.amplifyframework.api.graphql.GraphQLResponse; import com.amplifyframework.api.graphql.PaginatedResult; @@ -41,6 +42,7 @@ import com.amplifyframework.datastore.appsync.ModelWithMetadata; import com.amplifyframework.datastore.events.NonApplicableDataReceivedEvent; import com.amplifyframework.datastore.events.SyncQueriesStartedEvent; +import com.amplifyframework.datastore.utils.ErrorInspector; import com.amplifyframework.hub.HubChannel; import com.amplifyframework.hub.HubEvent; import com.amplifyframework.logging.Logger; @@ -160,6 +162,13 @@ private Completable createHydrationTask(ModelSchema schema) { return syncModel(schema, lastSyncTime) // Switch to a new thread so that subsequent API fetches will happen in parallel with DB writes. .observeOn(Schedulers.io()) + // Ignore ApiAuthExceptions so that we can continue to sync down other models + .materialize() + .filter(notification -> + !notification.isOnError() || + !(ErrorInspector.contains(notification.getError(), ApiAuthException.class)) + ) + .dematerialize(notification -> notification) // Flatten to a stream of ModelWithMetadata objects .concatMap(Flowable::fromIterable) .concatMapCompletable(item -> merger.merge(item, metricsAccumulator::increment))