@@ -34,6 +34,8 @@ public actor POSCatalogSyncCoordinator: POSCatalogSyncCoordinatorProtocol {
34
34
private let incrementalSyncService : POSCatalogIncrementalSyncServiceProtocol
35
35
private let grdbManager : GRDBManagerProtocol
36
36
private let maxIncrementalSyncAge : TimeInterval
37
+ private let catalogSizeLimit : Int
38
+ private let catalogSizeChecker : POSCatalogSizeCheckerProtocol
37
39
38
40
/// Tracks ongoing full syncs by site ID to prevent duplicates
39
41
private var ongoingSyncs : Set < Int64 > = [ ]
@@ -43,11 +45,15 @@ public actor POSCatalogSyncCoordinator: POSCatalogSyncCoordinatorProtocol {
43
45
public init ( fullSyncService: POSCatalogFullSyncServiceProtocol ,
44
46
incrementalSyncService: POSCatalogIncrementalSyncServiceProtocol ,
45
47
grdbManager: GRDBManagerProtocol ,
46
- maxIncrementalSyncAge: TimeInterval = 300 ) {
48
+ maxIncrementalSyncAge: TimeInterval = 300 ,
49
+ catalogSizeLimit: Int ? = nil ,
50
+ catalogSizeChecker: POSCatalogSizeCheckerProtocol ) {
47
51
self . fullSyncService = fullSyncService
48
52
self . incrementalSyncService = incrementalSyncService
49
53
self . grdbManager = grdbManager
50
54
self . maxIncrementalSyncAge = maxIncrementalSyncAge
55
+ self . catalogSizeLimit = catalogSizeLimit ?? Constants . defaultSizeLimitForPOSCatalog
56
+ self . catalogSizeChecker = catalogSizeChecker
51
57
}
52
58
53
59
public func performFullSync( for siteID: Int64 ) async throws {
@@ -71,7 +77,20 @@ public actor POSCatalogSyncCoordinator: POSCatalogSyncCoordinatorProtocol {
71
77
DDLogInfo ( " ✅ POSCatalogSyncCoordinator completed full sync for site \( siteID) " )
72
78
}
73
79
80
+ /// Determines if a full sync should be performed based on the age of the last sync
81
+ /// - Parameters:
82
+ /// - siteID: The site ID to check
83
+ /// - maxAge: Maximum age before a sync is considered stale
84
+ /// - Returns: True if a sync should be performed
74
85
public func shouldPerformFullSync( for siteID: Int64 , maxAge: TimeInterval ) async -> Bool {
86
+ return await shouldPerformFullSync ( for: siteID, maxAge: maxAge, maxCatalogSize: catalogSizeLimit)
87
+ }
88
+
89
+ private func shouldPerformFullSync( for siteID: Int64 , maxAge: TimeInterval , maxCatalogSize: Int ) async -> Bool {
90
+ guard await isCatalogSizeWithinLimit ( for: siteID, maxCatalogSize: maxCatalogSize) else {
91
+ return false
92
+ }
93
+
75
94
if !siteExistsInDatabase( siteID: siteID) {
76
95
DDLogInfo ( " 📋 POSCatalogSyncCoordinator: Site \( siteID) not found in database, sync needed " )
77
96
return true
@@ -86,20 +105,35 @@ public actor POSCatalogSyncCoordinator: POSCatalogSyncCoordinatorProtocol {
86
105
let shouldSync = age > maxAge
87
106
88
107
if shouldSync {
89
- DDLogInfo ( " 📋 POSCatalogSyncCoordinator: Last sync for site \( siteID) was \( Int ( age) ) s ago (max: \( Int ( maxAge) ) s), sync needed " )
108
+ DDLogInfo ( " 📋 POSCatalogSyncCoordinator: Last sync for site \( siteID) was \( Int ( age) ) s ago " +
109
+ " (max: \( Int ( maxAge) ) s), sync needed " )
90
110
} else {
91
- DDLogInfo ( " 📋 POSCatalogSyncCoordinator: Last sync for site \( siteID) was \( Int ( age) ) s ago (max: \( Int ( maxAge) ) s), sync not needed " )
111
+ DDLogInfo ( " 📋 POSCatalogSyncCoordinator: Last sync for site \( siteID) was \( Int ( age) ) s ago " +
112
+ " (max: \( Int ( maxAge) ) s), sync not needed " )
92
113
}
93
114
94
115
return shouldSync
95
116
}
96
117
118
+ /// Performs an incremental sync if applicable based on sync conditions
119
+ /// - Parameters:
120
+ /// - siteID: The site ID to sync catalog for
121
+ /// - forceSync: Whether to bypass age checks and always sync
122
+ /// - Throws: POSCatalogSyncError.syncAlreadyInProgress if a sync is already running for this site
97
123
public func performIncrementalSyncIfApplicable( for siteID: Int64 , forceSync: Bool ) async throws {
124
+ try await performIncrementalSyncIfApplicable ( for: siteID, forceSync: forceSync, maxCatalogSize: catalogSizeLimit)
125
+ }
126
+
127
+ private func performIncrementalSyncIfApplicable( for siteID: Int64 , forceSync: Bool , maxCatalogSize: Int ) async throws {
98
128
if ongoingIncrementalSyncs. contains ( siteID) {
99
129
DDLogInfo ( " ⚠️ POSCatalogSyncCoordinator: Incremental sync already in progress for site \( siteID) " )
100
130
throw POSCatalogSyncError . syncAlreadyInProgress ( siteID: siteID)
101
131
}
102
132
133
+ guard await isCatalogSizeWithinLimit ( for: siteID, maxCatalogSize: maxCatalogSize) else {
134
+ return
135
+ }
136
+
103
137
guard let lastFullSyncDate = await lastFullSyncDate ( for: siteID) else {
104
138
DDLogInfo ( " 📋 POSCatalogSyncCoordinator: No full sync performed yet for site \( siteID) , skipping incremental sync " )
105
139
return
@@ -130,6 +164,28 @@ public actor POSCatalogSyncCoordinator: POSCatalogSyncCoordinatorProtocol {
130
164
131
165
// MARK: - Private
132
166
167
+ /// Checks if the catalog size is within the specified sync limit
168
+ /// - Parameters:
169
+ /// - siteID: The site ID to check
170
+ /// - maxCatalogSize: Maximum allowed catalog size for syncing
171
+ /// - Returns: True if catalog size is within limit or if size cannot be determined
172
+ private func isCatalogSizeWithinLimit( for siteID: Int64 , maxCatalogSize: Int ) async -> Bool {
173
+ guard let catalogSize = try ? await catalogSizeChecker. checkCatalogSize ( for: siteID) else {
174
+ DDLogError ( " 📋 POSCatalogSyncCoordinator: Could not get catalog size for site \( siteID) " )
175
+ return false
176
+ }
177
+
178
+ guard catalogSize. totalCount <= maxCatalogSize else {
179
+ DDLogInfo ( " 📋 POSCatalogSyncCoordinator: Site \( siteID) has catalog size \( catalogSize. totalCount) , " +
180
+ " greater than \( maxCatalogSize) , should not sync. " )
181
+ return false
182
+ }
183
+
184
+ DDLogInfo ( " 📋 POSCatalogSyncCoordinator: Site \( siteID) has catalog size \( catalogSize. totalCount) , with " +
185
+ " \( catalogSize. productCount) products and \( catalogSize. variationCount) variations " )
186
+ return true
187
+ }
188
+
133
189
private func lastFullSyncDate( for siteID: Int64 ) async -> Date ? {
134
190
do {
135
191
return try await grdbManager. databaseConnection. read { db in
@@ -164,3 +220,9 @@ public actor POSCatalogSyncCoordinator: POSCatalogSyncCoordinatorProtocol {
164
220
}
165
221
}
166
222
}
223
+
224
+ private extension POSCatalogSyncCoordinator {
225
+ enum Constants {
226
+ static let defaultSizeLimitForPOSCatalog = 1000
227
+ }
228
+ }
0 commit comments