use of com.amplifyframework.datastore.DataStoreException in project amplify-android by aws-amplify.
the class AppSyncClientTest method validateBaseSyncQueryGen.
/**
* Validates the construction of a base-sync query.
* @throws JSONException On bad request JSON found in API category call
* @throws DataStoreException If no valid response returned from AppSync endpoint during sync
* @throws AmplifyException On failure to arrange model schema
*/
@Test
public void validateBaseSyncQueryGen() throws JSONException, AmplifyException {
ModelSchema schema = ModelSchema.fromModelClass(BlogOwner.class);
Await.result((Consumer<GraphQLResponse<PaginatedResult<ModelWithMetadata<BlogOwner>>>> onResult, Consumer<DataStoreException> onError) -> {
try {
GraphQLRequest<PaginatedResult<ModelWithMetadata<BlogOwner>>> request = endpoint.buildSyncRequest(schema, null, null, QueryPredicates.all());
endpoint.sync(request, onResult, onError);
} catch (DataStoreException datastoreException) {
onError.accept(datastoreException);
}
});
// Now, capture the request argument on API, so we can see what was passed.
// Recall that we pass a raw doc to API.
ArgumentCaptor<GraphQLRequest<ModelWithMetadata<BlogOwner>>> requestCaptor = ArgumentCaptor.forClass(GraphQLRequest.class);
verify(api).query(requestCaptor.capture(), any(Consumer.class), any(Consumer.class));
GraphQLRequest<ModelWithMetadata<BlogOwner>> capturedRequest = requestCaptor.getValue();
Type type = TypeMaker.getParameterizedType(PaginatedResult.class, ModelWithMetadata.class, BlogOwner.class);
assertEquals(type, capturedRequest.getResponseType());
// The request was sent as JSON. It has a null variables field, and a present query field.
JSONAssert.assertEquals(Resources.readAsString("base-sync-request-document-for-blog-owner.txt"), capturedRequest.getContent(), true);
}
use of com.amplifyframework.datastore.DataStoreException in project amplify-android by aws-amplify.
the class SyncProcessor method syncModel.
/**
* Sync models for a given model class.
* This involves three steps:
* 1. Lookup the last time the model class was synced;
* 2. Make a request to the AppSync endpoint. If the last sync time is within a recent window
* of time, then request a *delta* sync. If the last sync time is outside a recent window of time,
* perform a *base* sync. A base sync is preformed by passing null.
* 3. Continue fetching paged results until !hasNextResult() or we have synced the max records.
*
* @param schema The schema of the model to sync
* @param syncTime The time of a last successful sync.
* @param <T> The type of model to sync.
* @return a stream of all ModelWithMetadata<T> objects from all pages for the provided model.
* @throws DataStoreException if dataStoreConfigurationProvider.getConfiguration() fails
*/
private <T extends Model> Flowable<List<ModelWithMetadata<T>>> syncModel(ModelSchema schema, SyncTime syncTime) throws DataStoreException {
final Long lastSyncTimeAsLong = syncTime.exists() ? syncTime.toLong() : null;
final Integer syncPageSize = dataStoreConfigurationProvider.getConfiguration().getSyncPageSize();
final Integer syncMaxRecords = dataStoreConfigurationProvider.getConfiguration().getSyncMaxRecords();
AtomicReference<Integer> recordsFetched = new AtomicReference<>(0);
QueryPredicate predicate = queryPredicateProvider.getPredicate(schema.getName());
// Create a BehaviorProcessor, and set the default value to a GraphQLRequest that fetches the first page.
BehaviorProcessor<GraphQLRequest<PaginatedResult<ModelWithMetadata<T>>>> processor = BehaviorProcessor.createDefault(appSync.buildSyncRequest(schema, lastSyncTimeAsLong, syncPageSize, predicate));
return processor.concatMap(request -> {
if (isSyncRetryEnabled) {
return syncPageWithRetry(request).toFlowable();
} else {
return syncPage(request).toFlowable();
}
}).doOnNext(paginatedResult -> {
if (paginatedResult.hasNextResult()) {
processor.onNext(paginatedResult.getRequestForNextResult());
} else {
processor.onComplete();
}
}).map(paginatedResult -> Flowable.fromIterable(paginatedResult).map(modelWithMetadata -> hydrateSchemaIfNeeded(modelWithMetadata, schema)).toList().blockingGet()).takeUntil(items -> recordsFetched.accumulateAndGet(items.size(), Integer::sum) >= syncMaxRecords);
}
use of com.amplifyframework.datastore.DataStoreException in project amplify-android by aws-amplify.
the class SyncProcessor method syncPage.
/**
* Fetches one page for a sync.
* @param request GraphQLRequest object for the sync, obtained from {@link AppSync#buildSyncRequest}, or from
* response.getData().getRequestForNextResult() for subsequent requests.
* @param <T> The type of model to sync.
*/
private <T extends Model> Single<PaginatedResult<ModelWithMetadata<T>>> syncPage(GraphQLRequest<PaginatedResult<ModelWithMetadata<T>>> request) {
return Single.create(emitter -> {
Cancelable cancelable = appSync.sync(request, result -> {
if (result.hasErrors()) {
emitter.onError(new DataStoreException(String.format("A model sync failed: %s", result.getErrors()), "Check your schema."));
} else if (!result.hasData()) {
emitter.onError(new DataStoreException.IrRecoverableException("Empty response from AppSync.", "Report to AWS team."));
} else {
emitter.onSuccess(result.getData());
}
}, emitter::onError);
emitter.setDisposable(AmplifyDisposables.fromCancelable(cancelable));
});
}
use of com.amplifyframework.datastore.DataStoreException in project amplify-android by aws-amplify.
the class SQLPredicate method parsePredicateOperation.
@SuppressWarnings("fallthrough")
private // Utility method to recursively parse a given predicate operation.
StringBuilder parsePredicateOperation(QueryPredicateOperation<?> operation) throws DataStoreException {
final StringBuilder builder = new StringBuilder();
final String model = Wrap.inBackticks(operation.modelName());
final String field = Wrap.inBackticks(operation.field());
final String column = model == null ? operation.field() : model + "." + field;
final QueryOperator<?> op = operation.operator();
switch(op.type()) {
case BETWEEN:
BetweenQueryOperator<?> betweenOp = (BetweenQueryOperator<?>) op;
addBinding(betweenOp.start());
addBinding(betweenOp.end());
return builder.append(column).append(SqlKeyword.DELIMITER).append(SqlKeyword.BETWEEN).append(SqlKeyword.DELIMITER).append("?").append(SqlKeyword.DELIMITER).append(SqlKeyword.AND).append(SqlKeyword.DELIMITER).append("?");
case CONTAINS:
ContainsQueryOperator containsOp = (ContainsQueryOperator) op;
addBinding(containsOp.value());
return builder.append("instr(").append(column).append(",").append("?").append(")").append(SqlKeyword.DELIMITER).append(SqlKeyword.fromQueryOperator(QueryOperator.Type.GREATER_THAN)).append(SqlKeyword.DELIMITER).append("0");
case NOT_CONTAINS:
NotContainsQueryOperator notContainsOp = (NotContainsQueryOperator) op;
addBinding(notContainsOp.value());
return builder.append("instr(").append(column).append(",").append("?").append(")").append(SqlKeyword.DELIMITER).append(SqlKeyword.fromQueryOperator(QueryOperator.Type.EQUAL)).append(SqlKeyword.DELIMITER).append("0");
case BEGINS_WITH:
BeginsWithQueryOperator beginsWithOp = (BeginsWithQueryOperator) op;
addBinding(beginsWithOp.value() + "%");
return builder.append(column).append(SqlKeyword.DELIMITER).append(SqlKeyword.LIKE).append(SqlKeyword.DELIMITER).append("?");
case EQUAL:
case NOT_EQUAL:
Object operatorValue = getOperatorValue(op);
if (operatorValue == null) {
SqlKeyword sqlNullCheck = op.type() == QueryOperator.Type.EQUAL ? SqlKeyword.IS_NULL : SqlKeyword.IS_NOT_NULL;
return builder.append(column).append(SqlKeyword.DELIMITER).append(sqlNullCheck.toString());
}
case LESS_THAN:
case GREATER_THAN:
case LESS_OR_EQUAL:
case GREATER_OR_EQUAL:
addBinding(getOperatorValue(op));
return builder.append(column).append(SqlKeyword.DELIMITER).append(SqlKeyword.fromQueryOperator(op.type())).append(SqlKeyword.DELIMITER).append("?");
default:
throw new DataStoreException("Tried to parse an unsupported QueryPredicateOperation", "Try changing to one of the supported values from " + "QueryPredicateOperation.Type enum.");
}
}
use of com.amplifyframework.datastore.DataStoreException in project amplify-android by aws-amplify.
the class GsonPendingMutationConverter method fromRecord.
@NonNull
@Override
public <T extends Model> PendingMutation<T> fromRecord(@NonNull PendingMutation.PersistentRecord record) throws DataStoreException {
final Class<?> itemClass;
try {
itemClass = Class.forName(record.getContainedModelClassName());
} catch (ClassNotFoundException classNotFoundException) {
throw new DataStoreException("Could not find a class with the name " + record.getContainedModelClassName(), classNotFoundException, "Verify that you have built this model into your project.");
}
final Type itemType = TypeToken.getParameterized(PendingMutation.class, itemClass).getType();
return gson.fromJson(record.getSerializedMutationData(), itemType);
}
Aggregations