From 4665a7b556d12b86863a7323abbecbb206ede6e5 Mon Sep 17 00:00:00 2001 From: poojamat Date: Wed, 10 Nov 2021 10:14:24 -0800 Subject: [PATCH] Send snapshot on updates which render an item in list to not qualify a predicate. --- .../SQLiteStorageAdapterObserveQueryTest.java | 99 ++++++++++++++----- .../storage/sqlite/ObserveQueryExecutor.java | 18 +++- 2 files changed, 90 insertions(+), 27 deletions(-) diff --git a/aws-datastore/src/androidTest/java/com/amplifyframework/datastore/storage/sqlite/SQLiteStorageAdapterObserveQueryTest.java b/aws-datastore/src/androidTest/java/com/amplifyframework/datastore/storage/sqlite/SQLiteStorageAdapterObserveQueryTest.java index d7cf02b1b6..19a4f8452f 100644 --- a/aws-datastore/src/androidTest/java/com/amplifyframework/datastore/storage/sqlite/SQLiteStorageAdapterObserveQueryTest.java +++ b/aws-datastore/src/androidTest/java/com/amplifyframework/datastore/storage/sqlite/SQLiteStorageAdapterObserveQueryTest.java @@ -311,22 +311,20 @@ public void querySavedDataWithNumericalPredicates() throws DataStoreException, I // 1, 4, 5, 6 QueryPredicate predicate = Post.RATING.ge(4) .and(Post.RATING.lt(7)) - .or( - Post.RATING.eq(1) - .and(Post.RATING.ne(7)) - ); + .or(Post.RATING.eq(1) + .and(Post.RATING.ne(7))); - Consumer observationStarted = value -> { - }; + Consumer observationStarted = value -> { }; AtomicInteger count = new AtomicInteger(0); Consumer> onQuerySnapshot = value -> { if (count.get() == 0) { + assertEquals(4, value.getItems().size()); assertTrue(value.getItems().contains(savedModels.get(1))); assertTrue(value.getItems().contains(savedModels.get(4))); assertTrue(value.getItems().contains(savedModels.get(5))); assertTrue(value.getItems().contains(savedModels.get(6))); latch.countDown(); - } else if (count.get() == 1) { + }else if (count.get() == 2) { assertEquals(5, value.getItems().size()); assertTrue(value.getItems().contains(savedModels.get(1))); assertTrue(value.getItems().contains(savedModels.get(4))); @@ -337,10 +335,8 @@ public void querySavedDataWithNumericalPredicates() throws DataStoreException, I } count.incrementAndGet(); }; - Consumer onObservationError = value -> { - }; - Action onObservationComplete = () -> { - }; + Consumer onObservationError = value -> { }; + Action onObservationComplete = () -> { }; adapter.observeQuery( Post.class, @@ -351,8 +347,7 @@ public void querySavedDataWithNumericalPredicates() throws DataStoreException, I onObservationComplete); assertTrue(latch.await(5, TimeUnit.SECONDS)); - - for (int counter = 0; counter < 2; counter++) { + for (int counter = 3; counter < 5; counter++) { final Post post = Post.builder() .title("titlePrefix:" + counter + "change") .status(PostStatus.INACTIVE) @@ -428,23 +423,18 @@ public void querySavedDataWithPredicatesOnForeignKey() throws DataStoreException .name("Jane Doe") .build(); adapter.save(blogOwner); - final Blog blog = Blog.builder() .name("Jane's Commercial Real Estate Blog") .owner(blogOwner) .build(); adapter.save(blog); CountDownLatch latch = new CountDownLatch(1); - Consumer observationStarted = value -> { - }; + Consumer observationStarted = value -> { }; Consumer> onQuerySnapshot = value -> { assertTrue(value.getItems().contains(blog)); - latch.countDown(); - }; - Consumer onObservationError = value -> { - }; - Action onObservationComplete = () -> { - }; + latch.countDown(); }; + Consumer onObservationError = value -> { }; + Action onObservationComplete = () -> { }; adapter.observeQuery( Blog.class, @@ -609,7 +599,6 @@ public void queryWithOrderByRelatedModel() throws DataStoreException, Interrupte * @throws DataStoreException On unexpected failure manipulating items in/out of DataStore * @throws InterruptedException On unexpected failure manipulating items in/out of DataStore */ - @Ignore("Failing in build") @Test public void querySavedDataWithMultipleItemsThenItemSaves() throws DataStoreException, InterruptedException { CountDownLatch latch = new CountDownLatch(1); @@ -658,4 +647,68 @@ public void querySavedDataWithMultipleItemsThenItemSaves() throws DataStoreExcep } assertTrue(changeLatch.await(9, TimeUnit.SECONDS)); } + + /** + * Test querying the saved item in the SQLite database with observeQuery. + * + * @throws DataStoreException On unexpected failure manipulating items in/out of DataStore + * @throws InterruptedException On unexpected failure manipulating items in/out of DataStore + */ + @Test + public void querySavedDataWithMultipleItemsThenUpdateOnItemSoItNoLongerSatisfiesPredicate() throws DataStoreException, InterruptedException { + CountDownLatch latch = new CountDownLatch(1); + CountDownLatch changeLatch = new CountDownLatch(1); + Consumer observationStarted = value -> { }; + Consumer onObservationError = value -> { }; + Action onObservationComplete = () -> { }; + final List savedModels = new ArrayList<>(); + final int numModels = 5; + //Blogowner to be updated + final BlogOwner blogOwnerToBeUpdated = BlogOwner.builder() + .name("namePrefix:") + .build(); + adapter.save(blogOwnerToBeUpdated); + savedModels.add(blogOwnerToBeUpdated); + AtomicInteger count = new AtomicInteger(0); + for (int counter = 1; counter < numModels; counter++) { + final BlogOwner blogOwner = BlogOwner.builder() + .name("namePrefix:" + counter) + .build(); + adapter.save(blogOwner); + savedModels.add(blogOwner); + } + + Consumer> onQuerySnapshot = value -> { + if (count.get() == 0) { + for (BlogOwner blogOwner : savedModels) { + assertTrue(value.getItems().contains(blogOwner)); + } + assertEquals(5, value.getItems().size()); + latch.countDown(); + } else { + assertEquals(4, value.getItems().size()); + changeLatch.countDown(); + } + count.incrementAndGet(); + }; + adapter.observeQuery( + BlogOwner.class, + new ObserveQueryOptions(BlogOwner.NAME.beginsWith("namePrefix"), null), + observationStarted, + onQuerySnapshot, + onObservationError, + onObservationComplete); + + assertTrue(latch.await(30, TimeUnit.SECONDS)); + final BlogOwner blogOwnerUpdated = blogOwnerToBeUpdated.copyOfBuilder() + .name("updated").build(); + try { + adapter.save(blogOwnerUpdated); + } catch (DataStoreException exception) { + exception.printStackTrace(); + } + + savedModels.add(blogOwnerUpdated); + assertTrue(changeLatch.await(900000, TimeUnit.SECONDS)); + } } diff --git a/aws-datastore/src/main/java/com/amplifyframework/datastore/storage/sqlite/ObserveQueryExecutor.java b/aws-datastore/src/main/java/com/amplifyframework/datastore/storage/sqlite/ObserveQueryExecutor.java index 35e622e178..0ca383f211 100644 --- a/aws-datastore/src/main/java/com/amplifyframework/datastore/storage/sqlite/ObserveQueryExecutor.java +++ b/aws-datastore/src/main/java/com/amplifyframework/datastore/storage/sqlite/ObserveQueryExecutor.java @@ -135,15 +135,25 @@ public void observeQuery( onObservationStarted.accept(this); Consumer onItemChanged = value -> { + @SuppressWarnings("unchecked") StorageItemChange itemChanged = (StorageItemChange) value; - updateCompleteItemMap(itemChanged); - collect(itemChanged, onQuerySnapshot, itemClass, options, onObservationError); + try{ + if(sqlQueryProcessor.modelExists(itemChanged.item(), options.getQueryPredicate())){ + updateCompleteItemMap(itemChanged); + } else if(itemChanged.type() == StorageItemChange.Type.UPDATE){ + completeItemMap.remove(itemChanged.item().getId()); + } + collect(itemChanged, onQuerySnapshot, itemClass, options, onObservationError); + } catch (DataStoreException exception) { + onObservationError.accept(exception); + } + + }; threadPool.submit(() -> queryLocalData(itemClass, options, onQuerySnapshot, onObservationError)); disposable = itemChangeSubject - .filter(x -> x.item().getClass().isAssignableFrom(itemClass) && - sqlQueryProcessor.modelExists(x.item(), options.getQueryPredicate())) + .filter(x -> x.item().getClass().isAssignableFrom(itemClass)) .subscribe( onItemChanged::accept, failure -> {