use of com.amplifyframework.core.model.Model 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.core.model.Model in project amplify-android by aws-amplify.
the class MutationProcessor method update.
// For an item in the outbox, dispatch an update mutation
private <T extends Model> Single<ModelWithMetadata<T>> update(PendingMutation<T> mutation) {
final T updatedItem = mutation.getMutatedItem();
final ModelSchema updatedItemSchema = this.schemaRegistry.getModelSchemaForModelClass(updatedItem.getModelName());
return versionRepository.findModelVersion(updatedItem).flatMap(version -> publishWithStrategy(mutation, (model, onSuccess, onError) -> appSync.update(model, updatedItemSchema, version, mutation.getPredicate(), onSuccess, onError)));
}
use of com.amplifyframework.core.model.Model in project amplify-android by aws-amplify.
the class MutationProcessor method delete.
// For an item in the outbox, dispatch a delete mutation
private <T extends Model> Single<ModelWithMetadata<T>> delete(PendingMutation<T> mutation) {
final T deletedItem = mutation.getMutatedItem();
final ModelSchema deletedItemSchema = this.schemaRegistry.getModelSchemaForModelClass(deletedItem.getModelName());
return versionRepository.findModelVersion(deletedItem).flatMap(version -> publishWithStrategy(mutation, (model, onSuccess, onError) -> appSync.delete(deletedItem, deletedItemSchema, version, mutation.getPredicate(), onSuccess, onError)));
}
use of com.amplifyframework.core.model.Model in project amplify-android by aws-amplify.
the class RxApiBindingTest method mutateEmitsResult.
/**
* When the API behavior emits a result for a mutation, so too should the Rx binding.
* @throws InterruptedException If interrupted while test observer is awaiting terminal event
*/
@Test
public void mutateEmitsResult() throws InterruptedException {
// Arrange: category behaviour will yield a response
Model model = RandomModel.model();
GraphQLResponse<Model> response = new GraphQLResponse<>(model, Collections.emptyList());
GraphQLRequest<Model> deleteRequest = createMockMutationRequest(Model.class);
doAnswer(invocation -> {
final int positionOfResultConsumer = 1;
Consumer<GraphQLResponse<Model>> onResponse = invocation.getArgument(positionOfResultConsumer);
onResponse.accept(response);
return null;
}).when(delegate).mutate(eq(deleteRequest), anyConsumer(), anyConsumer());
// Act: mutation via the Rx binding
TestObserver<GraphQLResponse<Model>> observer = rxApi.mutate(deleteRequest).test();
// Assert: response is propagated via Rx
observer.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
observer.assertValue(response);
verify(delegate).mutate(eq(deleteRequest), anyConsumer(), anyConsumer());
}
use of com.amplifyframework.core.model.Model in project amplify-android by aws-amplify.
the class RxApiBindingTest method mutateEmitsFailure.
/**
* When the API behavior emits a failure for a mutation, so too should the Rx binding.
* @throws InterruptedException If interrupted while test observer is awaiting terminal event
*/
@Test
public void mutateEmitsFailure() throws InterruptedException {
// Arrange category behavior to fail
ApiException expectedFailure = new ApiException("Expected", "Failure");
GraphQLRequest<Model> deleteRequest = createMockMutationRequest(Model.class);
doAnswer(invocation -> {
final int positionOfFailureConsumer = 2;
Consumer<ApiException> onFailure = invocation.getArgument(positionOfFailureConsumer);
onFailure.accept(expectedFailure);
return null;
}).when(delegate).mutate(eq(deleteRequest), anyConsumer(), anyConsumer());
// Act: access it via binding
TestObserver<GraphQLResponse<Model>> observer = rxApi.mutate(deleteRequest).test();
// Assert: failure is propagated
observer.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
observer.assertError(expectedFailure);
verify(delegate).mutate(eq(deleteRequest), anyConsumer(), anyConsumer());
}
Aggregations