-
Notifications
You must be signed in to change notification settings - Fork 121
[Local Catalog] Add incremental sync functionality to POSCatalogSyncCoordinator
#16117
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
[Local Catalog] Add incremental sync functionality to POSCatalogSyncCoordinator
#16117
Conversation
POSCatalogSyncCoordinator
|
|
a467350 to
0ffe5d7
Compare
…nto feat/WOOMOB-1252-sync-coordinator-incremental-sync
| /// Tracks ongoing full syncs by site ID to prevent duplicates | ||
| private var ongoingSyncs: Set<Int64> = [] | ||
| /// Tracks ongoing incremental syncs by site ID to prevent duplicates | ||
| private var ongoingIncrementalSyncs: Set<Int64> = [] |
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.
I don't know whether we really want to be able to do a full sync and an incremental sync for the same site simultaneously.
- Start a full sync that takes 1 minute to download
- 10s later, start an incremental sync which takes 30s to download
- 40s after starting, the incremental sync changes are written to the db
- 1m after starting, the full sync write starts – it deletes everything in the db for that site, and puts new data in.
Let's tackle in a separate ticket, as it's an edge case, but WDYT?
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.
I don't know whether we really want to be able to do a full sync and an incremental sync for the same site simultaneously.
Yea good point, incremental sync should be skipped when a full sync is ongoing. Created an issue WOOMOB-1331.
| if ongoingIncrementalSyncs.contains(siteID) { | ||
| DDLogInfo("⚠️ POSCatalogSyncCoordinator: Incremental sync already in progress for site \(siteID)") | ||
| throw POSCatalogSyncError.syncAlreadyInProgress(siteID: siteID) | ||
| } | ||
|
|
||
| guard let lastFullSyncDate = await lastFullSyncDate(for: siteID) else { | ||
| DDLogInfo("📋 POSCatalogSyncCoordinator: No full sync performed yet for site \(siteID), skipping incremental sync") | ||
| return | ||
| } | ||
|
|
||
| if !forceSync, let lastIncrementalSyncDate = await lastIncrementalSyncDate(for: siteID) { | ||
| let age = Date().timeIntervalSince(lastIncrementalSyncDate) | ||
|
|
||
| if age <= maxIncrementalSyncAge { | ||
| return DDLogInfo("📋 POSCatalogSyncCoordinator: Last incremental sync for site \(siteID) was \(Int(age))s ago, sync not needed") | ||
| } | ||
| } |
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.
Probably worth moving this to a shouldPerform function, even if it's only used privately in this class and not exposed.
I think we should probably use the same approach for both – I don't always enjoy the "if applicable/if needed" uncertainty, but then it is the job of this coordinator to manage when syncs happen, so it's not unreasonable.
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.
What do you think are the use cases / benefits of a separate shouldPerform that is public? It'd be useful for the call site to handle the result, but I don't think we plan to show any UI for it. A private shouldPerform function could make the code more readable though.
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.
I think giving both a private shouldPerform is the best approach for now.
We probably don't ever need to make them public, but some possible future reasons:
- To log analytics when a background task runs about whether we synced, or why we didn't.
- To show the status in settings "will sync" or make different buttons available.
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.
I think giving both a private
shouldPerformis the best approach for now.
Sounds good, we can make it public when the use case calls for it. I created an issue WOOMOB-1333 for making this change.
| private func lastIncrementalSyncDate(for siteID: Int64) async -> Date? { | ||
| do { | ||
| return try await grdbManager.databaseConnection.read { db in | ||
| return try PersistedSite.filter(key: siteID).fetchOne(db)?.lastCatalogIncrementalSyncDate | ||
| } | ||
| } catch { | ||
| DDLogError("⛔️ POSCatalogSyncCoordinator: Error loading site \(siteID) for incremental sync date: \(error)") | ||
| return nil | ||
| } | ||
| } |
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.
I changed this, removing the loadSite/updateSite functions from the persistence service, and saving the dates as part of the catalog, not afterwards.
It's worked out to be much simpler IMO, but I wanted to bring it to your attention, so let me know if you think we should go back

For WOOMOB-1252
Description
This PR adds incremental sync functionality to the
POSCatalogSyncCoordinatorby integrating withPOSCatalogIncrementalSyncServicewhich only syncs changes since the last sync.The implementation adds a new
performIncrementalSyncIfApplicablemethod that intelligently determines when incremental sync is appropriate based on:Key Changes
performIncrementalSyncIfApplicable(for:forceSync:)method to sync coordinatorperformIncrementalSyncIfApplicableso that the call site just makes one call when it's appropriate to trigger an incremental sync. Feel free to share any thoughts on this!forceSyncparameter bypasses age checks for immediate sync when neededSteps to reproduce
As incremental sync hasn't been integrated with POS yet, it can be tested by adding debug code below MainTabBarController.swift#L315 to trigger an incremental sync when tapping on the POS tab:
And then:
Testing information
I tested the above steps in iPad A16 iOS 18.4 simulator.
RELEASE-NOTES.txtif necessary.