Search in sources :

Example 16 with Model

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&lt;T&gt; 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);
}
Also used : DataStoreConfigurationProvider(com.amplifyframework.datastore.DataStoreConfigurationProvider) Single(io.reactivex.rxjava3.core.Single) DataStoreErrorHandler(com.amplifyframework.datastore.DataStoreErrorHandler) BehaviorProcessor(io.reactivex.rxjava3.processors.BehaviorProcessor) NonNull(androidx.annotation.NonNull) ModelWithMetadata(com.amplifyframework.datastore.appsync.ModelWithMetadata) GraphQLRequest(com.amplifyframework.api.graphql.GraphQLRequest) ModelProvider(com.amplifyframework.core.model.ModelProvider) DataStoreChannelEventName(com.amplifyframework.datastore.DataStoreChannelEventName) AppSync(com.amplifyframework.datastore.appsync.AppSync) SyncQueriesStartedEvent(com.amplifyframework.datastore.events.SyncQueriesStartedEvent) AtomicReference(java.util.concurrent.atomic.AtomicReference) ApiException(com.amplifyframework.api.ApiException) ArrayList(java.util.ArrayList) SchemaRegistry(com.amplifyframework.core.model.SchemaRegistry) Time(com.amplifyframework.util.Time) Schedulers(io.reactivex.rxjava3.schedulers.Schedulers) Consumer(com.amplifyframework.core.Consumer) ModelSchema(com.amplifyframework.core.model.ModelSchema) PaginatedResult(com.amplifyframework.api.graphql.PaginatedResult) QueryPredicate(com.amplifyframework.core.model.query.predicate.QueryPredicate) HubEvent(com.amplifyframework.hub.HubEvent) Amplify(com.amplifyframework.core.Amplify) Flowable(io.reactivex.rxjava3.core.Flowable) HubChannel(com.amplifyframework.hub.HubChannel) SerializedModel(com.amplifyframework.core.model.SerializedModel) Model(com.amplifyframework.core.model.Model) Completable(io.reactivex.rxjava3.core.Completable) Logger(com.amplifyframework.logging.Logger) Objects(java.util.Objects) DataStoreException(com.amplifyframework.datastore.DataStoreException) List(java.util.List) Cancelable(com.amplifyframework.core.async.Cancelable) AmplifyDisposables(com.amplifyframework.datastore.AmplifyDisposables) ForEach(com.amplifyframework.util.ForEach) Collections(java.util.Collections) GraphQLRequest(com.amplifyframework.api.graphql.GraphQLRequest) ModelWithMetadata(com.amplifyframework.datastore.appsync.ModelWithMetadata) QueryPredicate(com.amplifyframework.core.model.query.predicate.QueryPredicate) AtomicReference(java.util.concurrent.atomic.AtomicReference)

Example 17 with Model

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)));
}
Also used : Amplify(com.amplifyframework.core.Amplify) Single(io.reactivex.rxjava3.core.Single) HubChannel(com.amplifyframework.hub.HubChannel) SerializedModel(com.amplifyframework.core.model.SerializedModel) NonNull(androidx.annotation.NonNull) ModelWithMetadata(com.amplifyframework.datastore.appsync.ModelWithMetadata) Model(com.amplifyframework.core.model.Model) AppSync(com.amplifyframework.datastore.appsync.AppSync) Completable(io.reactivex.rxjava3.core.Completable) OutboxStatusEvent(com.amplifyframework.datastore.events.OutboxStatusEvent) AppSyncConflictUnhandledError(com.amplifyframework.datastore.appsync.AppSyncConflictUnhandledError) Logger(com.amplifyframework.logging.Logger) SchemaRegistry(com.amplifyframework.core.model.SchemaRegistry) Objects(java.util.Objects) TimeUnit(java.util.concurrent.TimeUnit) Schedulers(io.reactivex.rxjava3.schedulers.Schedulers) DataStoreException(com.amplifyframework.datastore.DataStoreException) Consumer(com.amplifyframework.core.Consumer) List(java.util.List) CompositeDisposable(io.reactivex.rxjava3.disposables.CompositeDisposable) ModelSchema(com.amplifyframework.core.model.ModelSchema) GraphQLResponse(com.amplifyframework.api.graphql.GraphQLResponse) HubEvent(com.amplifyframework.hub.HubEvent) ModelSchema(com.amplifyframework.core.model.ModelSchema)

Example 18 with Model

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)));
}
Also used : Amplify(com.amplifyframework.core.Amplify) Single(io.reactivex.rxjava3.core.Single) HubChannel(com.amplifyframework.hub.HubChannel) SerializedModel(com.amplifyframework.core.model.SerializedModel) NonNull(androidx.annotation.NonNull) ModelWithMetadata(com.amplifyframework.datastore.appsync.ModelWithMetadata) Model(com.amplifyframework.core.model.Model) AppSync(com.amplifyframework.datastore.appsync.AppSync) Completable(io.reactivex.rxjava3.core.Completable) OutboxStatusEvent(com.amplifyframework.datastore.events.OutboxStatusEvent) AppSyncConflictUnhandledError(com.amplifyframework.datastore.appsync.AppSyncConflictUnhandledError) Logger(com.amplifyframework.logging.Logger) SchemaRegistry(com.amplifyframework.core.model.SchemaRegistry) Objects(java.util.Objects) TimeUnit(java.util.concurrent.TimeUnit) Schedulers(io.reactivex.rxjava3.schedulers.Schedulers) DataStoreException(com.amplifyframework.datastore.DataStoreException) Consumer(com.amplifyframework.core.Consumer) List(java.util.List) CompositeDisposable(io.reactivex.rxjava3.disposables.CompositeDisposable) ModelSchema(com.amplifyframework.core.model.ModelSchema) GraphQLResponse(com.amplifyframework.api.graphql.GraphQLResponse) HubEvent(com.amplifyframework.hub.HubEvent) ModelSchema(com.amplifyframework.core.model.ModelSchema)

Example 19 with Model

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());
}
Also used : RandomModel(com.amplifyframework.testutils.random.RandomModel) Model(com.amplifyframework.core.model.Model) GraphQLResponse(com.amplifyframework.api.graphql.GraphQLResponse) Test(org.junit.Test)

Example 20 with Model

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());
}
Also used : RandomModel(com.amplifyframework.testutils.random.RandomModel) Model(com.amplifyframework.core.model.Model) GraphQLResponse(com.amplifyframework.api.graphql.GraphQLResponse) ApiException(com.amplifyframework.api.ApiException) Test(org.junit.Test)

Aggregations

Model (com.amplifyframework.core.model.Model)62 Test (org.junit.Test)37 DataStoreException (com.amplifyframework.datastore.DataStoreException)34 ModelSchema (com.amplifyframework.core.model.ModelSchema)32 SerializedModel (com.amplifyframework.core.model.SerializedModel)30 AmplifyException (com.amplifyframework.AmplifyException)23 Cancelable (com.amplifyframework.core.async.Cancelable)22 Action (com.amplifyframework.core.Action)19 Consumer (com.amplifyframework.core.Consumer)19 StorageItemChange (com.amplifyframework.datastore.storage.StorageItemChange)19 BlogOwner (com.amplifyframework.testmodels.commentsblog.BlogOwner)19 ArrayList (java.util.ArrayList)19 List (java.util.List)19 SchemaRegistry (com.amplifyframework.core.model.SchemaRegistry)18 RandomModel (com.amplifyframework.testutils.random.RandomModel)17 GraphQLResponse (com.amplifyframework.api.graphql.GraphQLResponse)16 QueryPredicates (com.amplifyframework.core.model.query.predicate.QueryPredicates)16 TimeUnit (java.util.concurrent.TimeUnit)16 Collections (java.util.Collections)15 ObserveQueryOptions (com.amplifyframework.core.model.query.ObserveQueryOptions)13