-
Notifications
You must be signed in to change notification settings - Fork 119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(datastore): base sync when sync expression changes #2937
fix(datastore): base sync when sync expression changes #2937
Conversation
…cTimeRegistry&SyncProcessor
1. use serializedSyncExpression in lookupLastSyncTime 2. save serializedSyncExpression along with lastSyncTime
…ate and modified related method call
…ialized with QueryPredicateAdapter
...mplifyframework/datastore/storage/sqlite/migrations/AddSyncExpressionToLastSyncMetadata.java
Outdated
Show resolved
Hide resolved
...mplifyframework/datastore/storage/sqlite/migrations/AddSyncExpressionToLastSyncMetadata.java
Outdated
Show resolved
Hide resolved
aws-datastore/src/main/java/com/amplifyframework/datastore/DataStoreConfiguration.java
Outdated
Show resolved
Hide resolved
...mplifyframework/datastore/storage/sqlite/migrations/AddSyncExpressionToLastSyncMetadata.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets say a customer runs the app for the first time after updating with this fix.
You migrate the database and add null
to the syncExpression. How do you differentiate between a real null
sync expression, and one from the migration? We don't really know if thats accurate or not right? Would we be better or not removing last sync for models? I understand this would force a full sync for all initial app opens on this upgrade.
aws-datastore/src/main/java/com/amplifyframework/datastore/syncengine/SyncTimeRegistry.java
Outdated
Show resolved
Hide resolved
aws-datastore/src/main/java/com/amplifyframework/datastore/syncengine/LastSyncMetadata.java
Show resolved
Hide resolved
aws-datastore/src/main/java/com/amplifyframework/datastore/syncengine/LastSyncMetadata.java
Show resolved
Hide resolved
...e/src/main/java/com/amplifyframework/datastore/storage/sqlite/migrations/ModelMigration.java
Outdated
Show resolved
Hide resolved
...mplifyframework/datastore/storage/sqlite/migrations/AddSyncExpressionToLastSyncMetadata.java
Show resolved
Hide resolved
...mplifyframework/datastore/storage/sqlite/migrations/AddSyncExpressionToLastSyncMetadata.java
Show resolved
Hide resolved
...com/amplifyframework/datastore/storage/sqlite/migrations/AddModelNameToModelMetadataKey.java
Outdated
Show resolved
Hide resolved
...ync/src/main/java/com/amplifyframework/core/model/query/predicate/GsonPredicateAdapters.java
Show resolved
Hide resolved
@tylerjroach Sync expression wouldn't be stored as null if a sync operation occurs - it would be the serialization value of either |
Issue #, if available:
Description of changes:
This is in an effort to address a current issue customers had reported in our Datastore category.
The issue is that the "changing sync expression in Runtime" doesn't work as expected as described in our doc.
For example, when we initialize the DataStorePlugin with a sync expression for Student model to only sync down all the students who are >= 20-year-old, even if we change this sync expression to sync down students who are >= 17-year-old in run-time followed by
Amplify.DataStore.stop({},{})
andAmplify.DataStore.start({}, {})
: the new synced expression will only be applied to the newly-created/updated students, i.e. pre-existing instances of Students whose ages are in between 17 and 20 in remote database won't get synced, which is not as expected.The bug is originated from the
hydrate() method in SyncProcessor.java
, which is being called by thestartApiSync() method in Orchestrator.java
, a component responsible for "Synchronizing changed data between the LocalStorageAdapter and AppSync".To build a Sync Request (
syncModel(..) method in SyncProcessor.java
), we need to pass inIn order to achieve this, our implementation persists the last_sync_timestamp of models in
LastSyncMetadata table
whenever the code initiate a sync request, and uses the persisted last_sync_timestamp from LastSyncMetadata to initiate the next sync. (createHydrationTasks(..) in SyncProcessor.java
)This would allow us to initiate either a Delta sync or Base sync based on the
lastSyncTime
parameter we pass in, which is defined by the nature of AppSync's Sync API.To further explain the cause of this bug, let's keep using the previous example:
After we initiate the first sync with sync expression (age>=20), we would add a new row in LastSyncMetadata, which might look like
[Student(model name), 3(last sync timestamp)]
, assuming the current timestamp is 3.After we change the sync expression in runtime (age>=17), the implementation would:
[Student(model name), 4(last sync timestamp)]
This will lead to the bug behavior described above, because:
AppSync will use BOTH updated_sync_expression(age>=17) and last_sync_timestamp(3) to initiate a delta sync (base sync will be performed only when last_sync_timestamp is 0). And for delta sync, under the hood, this
last_sync_timestamp
will be used to compare with the metadata_lastChangedAt
in each rows of Student table in remote database.So previous students who haven't been updated since last_sync_timestamp(3), i.e. _lastChangedAt<3, won't get synced down, even though they meet the updated sync expression, e.g. a row in remote Student table like
[student1(name), 18(age), 2(_lastChangedAt)]
.But students who are added/updated later will get synced, e.g., a row in remote Student table like
[student2(name), 17(age), 5(_lastChangedAt)]
.The essence of this problem is that: the last_sync_timestamp was only associated with the model, but should be associated with the model and the last_sync_expression being used.
To address this, we need to:
last_sync_expression
being usedThe solution has been broke down into three steps:
How did you test these changes?
(Please add a line here how the changes were tested)
manual testing, new and existing test cases in SyncProcessorTest
Documentation update required?
General Checklist
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.