Skip to content
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

feat(datastore): selective sync on initial sync & incoming subscription models #884

Merged
merged 8 commits into from
Dec 1, 2020

Conversation

wooj2
Copy link
Contributor

@wooj2 wooj2 commented Nov 11, 2020

Smoke tested with a basic case.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@codecov
Copy link

codecov bot commented Nov 11, 2020

Codecov Report

Merging #884 (ed035e9) into main (840fc3e) will increase coverage by 0.09%.
The diff coverage is 90.80%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #884      +/-   ##
==========================================
+ Coverage   66.00%   66.09%   +0.09%     
==========================================
  Files         874      875       +1     
  Lines       34608    34769     +161     
==========================================
+ Hits        22843    22982     +139     
- Misses      11765    11787      +22     
Flag Coverage Δ
API_plugin_unit_test 62.49% <ø> (-0.16%) ⬇️
Analytics_plugin_unit_test 72.38% <ø> (ø)
Auth_plugin_unit_test 39.11% <ø> (ø)
DataStore_plugin_unit_test 83.14% <90.80%> (+0.11%) ⬆️
Predictions_plugin_unit_test 42.11% <ø> (ø)
Storage_plugin_unit_test 74.74% <ø> (ø)
build_test_amplify 63.11% <ø> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
...Sync/IncomingAsyncSubscriptionEventPublisher.swift 45.98% <ø> (ø)
...ionSync/Support/MockModelReconciliationQueue.swift 75.00% <ø> (ø)
...tionSync/Support/ReconciliationQueueTestBase.swift 83.33% <ø> (ø)
...tionSync/AWSIncomingEventReconciliationQueue.swift 50.00% <69.23%> (+2.22%) ⬆️
...s/Sync/InitialSync/InitialSyncOperationTests.swift 95.66% <89.55%> (-0.89%) ⬇️
...onSync/ModelReconciliationQueueBehaviorTests.swift 93.30% <91.07%> (-0.55%) ⬇️
...taStoreCategoryPlugin/DataStoreConfiguration.swift 86.36% <100.00%> (+1.36%) ⬆️
...aStoreCategoryPlugin/DataStoreSyncExpression.swift 100.00% <100.00%> (ø)
...Plugin/Sync/InitialSync/InitialSyncOperation.swift 80.00% <100.00%> (+0.63%) ⬆️
...ataStoreCategoryPlugin/Sync/RemoteSyncEngine.swift 92.89% <100.00%> (+0.17%) ⬆️
... and 8 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 840fc3e...ed035e9. Read the comment docs.

@wooj2 wooj2 requested a review from palpatim November 11, 2020 21:53
@wooj2 wooj2 marked this pull request as ready for review November 24, 2020 18:23
self.errorHandler = errorHandler
self.conflictHandler = conflictHandler
self.syncInterval = syncInterval
self.syncMaxRecords = syncMaxRecords
self.syncPageSize = syncPageSize
self.syncExpressions = syncExpressions
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as our ultimate behavior is the same, I'm not too interested in hewing closely to Android platform conventions. Even with named arguments and defaults, a pattern like:

let foo = DataStoreConfiguration(
    errorHandler: self.handleDataStoreError,
    conflictHandler: self.handleDataStoreConflict,
    syncInterval: 86_400,
    syncMaxRecords: 10_000,
    syncPageSize: 100,
    syncExpressions: [(Post.foo == getLatestValue()), (Post.bar < getSomeOtherValue()) ]
)

is pretty unwieldy. Even if we provide defaults, the named arguments must be provided in the same order, which adds friction to the customer's implementation.

Consider encapsulating the initializer arguments in purpose-built types (we have pluginOptions on our config types), or adopting a different construction pattern (Builder, for example) to let the customer have an easier time of initializing these.

Copy link
Contributor Author

@wooj2 wooj2 Nov 25, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regrading the configuraiton object being unwieldy, that is the worst case scenario. For customers only wanting to specify a selective sync, it would look something like this:

            let syncExpression1 = DataStoreSyncExpression.syncExpression(Todo.schema, where: {
                Todo.keys.tag == AppDelegate.tagToSearch
            })
            let dataStorePlugin = AWSDataStorePlugin(modelRegistration: AmplifyModels(),
                                                     configuration: .custom(syncExpressions: [syncExpression1]))

Are you still concerned about bloating this interface?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error handler and conflict handler seem like reasonable things to specify as well, but I'm guessing we don't have any data on how many customers are using which of the config options. It seems to me that 4 free-floating and yet sync-related arguments is excessive, but it's ultimately a judgement call, so consider this as my vote against it. I'm willing to be outvoted. :)

@wooj2 wooj2 changed the title feat(datastore): draft of selective sync on initial sync operation feat(datastore): selective sync on initial sync operation & incoming models on subscriptions Nov 24, 2020
@wooj2 wooj2 changed the title feat(datastore): selective sync on initial sync operation & incoming models on subscriptions feat(datastore): selective sync on initial sync & incoming subscription models Nov 24, 2020
@wooj2 wooj2 requested a review from diegocstn November 25, 2020 17:40
Copy link
Member

@palpatim palpatim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The overall design makes sense, but I'm not joyful about the growth of the DataStoreConfiguration interface, and I don't like passing that whole configuration object around to the underlying components. Comments inline

self.errorHandler = errorHandler
self.conflictHandler = conflictHandler
self.syncInterval = syncInterval
self.syncMaxRecords = syncMaxRecords
self.syncPageSize = syncPageSize
self.syncExpressions = syncExpressions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as our ultimate behavior is the same, I'm not too interested in hewing closely to Android platform conventions. Even with named arguments and defaults, a pattern like:

let foo = DataStoreConfiguration(
    errorHandler: self.handleDataStoreError,
    conflictHandler: self.handleDataStoreConflict,
    syncInterval: 86_400,
    syncMaxRecords: 10_000,
    syncPageSize: 100,
    syncExpressions: [(Post.foo == getLatestValue()), (Post.bar < getSomeOtherValue()) ]
)

is pretty unwieldy. Even if we provide defaults, the named arguments must be provided in the same order, which adds friction to the customer's implementation.

Consider encapsulating the initializer arguments in purpose-built types (we have pluginOptions on our config types), or adopting a different construction pattern (Builder, for example) to let the customer have an easier time of initializing these.

@wooj2 wooj2 added this to the 1.5.0 milestone Nov 29, 2020
@wooj2 wooj2 merged commit 6ea2f1e into main Dec 1, 2020
@wooj2 wooj2 deleted the feature/selsync branch December 1, 2020 20:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants