@@ -34,6 +34,8 @@ public actor POSCatalogSyncCoordinator: POSCatalogSyncCoordinatorProtocol {
3434 private let incrementalSyncService : POSCatalogIncrementalSyncServiceProtocol
3535 private let grdbManager : GRDBManagerProtocol
3636 private let maxIncrementalSyncAge : TimeInterval
37+ private let catalogSizeLimit : Int
38+ private let catalogSizeChecker : POSCatalogSizeCheckerProtocol
3739
3840 /// Tracks ongoing full syncs by site ID to prevent duplicates
3941 private var ongoingSyncs : Set < Int64 > = [ ]
@@ -43,11 +45,15 @@ public actor POSCatalogSyncCoordinator: POSCatalogSyncCoordinatorProtocol {
4345 public init ( fullSyncService: POSCatalogFullSyncServiceProtocol ,
4446 incrementalSyncService: POSCatalogIncrementalSyncServiceProtocol ,
4547 grdbManager: GRDBManagerProtocol ,
46- maxIncrementalSyncAge: TimeInterval = 300 ) {
48+ maxIncrementalSyncAge: TimeInterval = 300 ,
49+ catalogSizeLimit: Int ? = nil ,
50+ catalogSizeChecker: POSCatalogSizeCheckerProtocol ) {
4751 self . fullSyncService = fullSyncService
4852 self . incrementalSyncService = incrementalSyncService
4953 self . grdbManager = grdbManager
5054 self . maxIncrementalSyncAge = maxIncrementalSyncAge
55+ self . catalogSizeLimit = catalogSizeLimit ?? Constants . defaultSizeLimitForPOSCatalog
56+ self . catalogSizeChecker = catalogSizeChecker
5157 }
5258
5359 public func performFullSync( for siteID: Int64 ) async throws {
@@ -71,7 +77,20 @@ public actor POSCatalogSyncCoordinator: POSCatalogSyncCoordinatorProtocol {
7177 DDLogInfo ( " ✅ POSCatalogSyncCoordinator completed full sync for site \( siteID) " )
7278 }
7379
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
7485 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+
7594 if !siteExistsInDatabase( siteID: siteID) {
7695 DDLogInfo ( " 📋 POSCatalogSyncCoordinator: Site \( siteID) not found in database, sync needed " )
7796 return true
@@ -86,20 +105,35 @@ public actor POSCatalogSyncCoordinator: POSCatalogSyncCoordinatorProtocol {
86105 let shouldSync = age > maxAge
87106
88107 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 " )
90110 } 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 " )
92113 }
93114
94115 return shouldSync
95116 }
96117
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
97123 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 {
98128 if ongoingIncrementalSyncs. contains ( siteID) {
99129 DDLogInfo ( " ⚠️ POSCatalogSyncCoordinator: Incremental sync already in progress for site \( siteID) " )
100130 throw POSCatalogSyncError . syncAlreadyInProgress ( siteID: siteID)
101131 }
102132
133+ guard await isCatalogSizeWithinLimit ( for: siteID, maxCatalogSize: maxCatalogSize) else {
134+ return
135+ }
136+
103137 guard let lastFullSyncDate = await lastFullSyncDate ( for: siteID) else {
104138 DDLogInfo ( " 📋 POSCatalogSyncCoordinator: No full sync performed yet for site \( siteID) , skipping incremental sync " )
105139 return
@@ -130,6 +164,28 @@ public actor POSCatalogSyncCoordinator: POSCatalogSyncCoordinatorProtocol {
130164
131165 // MARK: - Private
132166
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+
133189 private func lastFullSyncDate( for siteID: Int64 ) async -> Date ? {
134190 do {
135191 return try await grdbManager. databaseConnection. read { db in
@@ -164,3 +220,9 @@ public actor POSCatalogSyncCoordinator: POSCatalogSyncCoordinatorProtocol {
164220 }
165221 }
166222}
223+
224+ private extension POSCatalogSyncCoordinator {
225+ enum Constants {
226+ static let defaultSizeLimitForPOSCatalog = 1000
227+ }
228+ }
0 commit comments