Skip to content

Commit 801d7c9

Browse files
authored
[Local Catalog] Incremental sync: persist incremental sync date in Site storage entity (#16108)
2 parents 581525c + f625bab commit 801d7c9

File tree

11 files changed

+257
-16
lines changed

11 files changed

+257
-16
lines changed

Modules/Sources/Fakes/Yosemite.generated.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ extension Yosemite.POSSimpleProduct {
5252
)
5353
}
5454
}
55+
extension Yosemite.POSSite {
56+
/// Returns a "ready to use" type filled with fake values.
57+
///
58+
public static func fake() -> Yosemite.POSSite {
59+
.init(
60+
siteID: .fake(),
61+
lastIncrementalSyncDate: .fake()
62+
)
63+
}
64+
}
5565
extension Yosemite.ProductReviewFromNoteParcel {
5666
/// Returns a "ready to use" type filled with fake values.
5767
///

Modules/Sources/Storage/GRDB/Migrations/V001InitialSchema.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ struct V001InitialSchema {
1919
static func createSiteTable(_ db: Database) throws {
2020
try db.create(table: "site") { siteTable in
2121
siteTable.primaryKey("id", .integer).notNull()
22+
siteTable.column("lastCatalogIncrementalSyncDate", .datetime)
2223
}
2324
}
2425

Modules/Sources/Storage/GRDB/Model/PersistedSite.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ import GRDB
55
public struct PersistedSite: Codable {
66
// periphery:ignore - TODO: remove ignore when populating database
77
public let id: Int64
8+
// periphery:ignore - TODO: remove ignore when populating database
9+
public let lastCatalogIncrementalSyncDate: Date?
810

911
// periphery:ignore - TODO: remove ignore when populating database
10-
public init(id: Int64) {
12+
public init(id: Int64, lastCatalogIncrementalSyncDate: Date? = nil) {
1113
self.id = id
14+
self.lastCatalogIncrementalSyncDate = lastCatalogIncrementalSyncDate
1215
}
1316
}
1417

@@ -19,12 +22,15 @@ extension PersistedSite: FetchableRecord, PersistableRecord {
1922
public enum Columns {
2023
// periphery:ignore - TODO: remove ignore when populating database
2124
static let id = Column(CodingKeys.id)
25+
// periphery:ignore - TODO: remove ignore when populating database
26+
static let lastCatalogIncrementalSyncDate = Column(CodingKeys.lastCatalogIncrementalSyncDate)
2227
}
2328
}
2429

2530
// periphery:ignore - TODO: remove ignore when populating database
2631
private extension PersistedSite {
2732
enum CodingKeys: String, CodingKey {
2833
case id
34+
case lastCatalogIncrementalSyncDate
2935
}
3036
}

Modules/Sources/Yosemite/Model/Copiable/Models+Copiable.generated.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,21 @@ extension Yosemite.POSSimpleProduct {
9393
}
9494
}
9595

96+
extension Yosemite.POSSite {
97+
public func copy(
98+
siteID: CopiableProp<Int64> = .copy,
99+
lastIncrementalSyncDate: NullableCopiableProp<Date> = .copy
100+
) -> Yosemite.POSSite {
101+
let siteID = siteID ?? self.siteID
102+
let lastIncrementalSyncDate = lastIncrementalSyncDate ?? self.lastIncrementalSyncDate
103+
104+
return Yosemite.POSSite(
105+
siteID: siteID,
106+
lastIncrementalSyncDate: lastIncrementalSyncDate
107+
)
108+
}
109+
}
110+
96111
extension Yosemite.ProductReviewFromNoteParcel {
97112
public func copy(
98113
note: CopiableProp<Note> = .copy,
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import Foundation
2+
import Storage
3+
4+
extension PersistedSite {
5+
init(from posSite: POSSite) {
6+
self.init(
7+
id: posSite.siteID,
8+
lastCatalogIncrementalSyncDate: posSite.lastIncrementalSyncDate
9+
)
10+
}
11+
12+
func toPOSSite() -> POSSite {
13+
POSSite(
14+
siteID: id,
15+
lastIncrementalSyncDate: lastCatalogIncrementalSyncDate
16+
)
17+
}
18+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// periphery:ignore:all
2+
import Codegen
3+
import Foundation
4+
5+
public struct POSSite: Equatable, GeneratedCopiable, GeneratedFakeable {
6+
public let siteID: Int64
7+
public let lastIncrementalSyncDate: Date?
8+
9+
public init(siteID: Int64, lastIncrementalSyncDate: Date? = nil) {
10+
self.siteID = siteID
11+
self.lastIncrementalSyncDate = lastIncrementalSyncDate
12+
}
13+
}

Modules/Sources/Yosemite/Tools/POS/POSCatalogIncrementalSyncService.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ public final class POSCatalogIncrementalSyncService: POSCatalogIncrementalSyncSe
2121
private let syncRemote: POSCatalogSyncRemoteProtocol
2222
private let batchSize: Int
2323
private let persistenceService: POSCatalogPersistenceServiceProtocol
24-
private var lastIncrementalSyncDates: [Int64: Date] = [:]
2524
private let batchedLoader: BatchedRequestLoader
2625

2726
public convenience init?(credentials: Credentials?, batchSize: Int = 1, grdbManager: GRDBManagerProtocol) {
@@ -45,7 +44,7 @@ public final class POSCatalogIncrementalSyncService: POSCatalogIncrementalSyncSe
4544
// MARK: - Protocol Conformance
4645

4746
public func startIncrementalSync(for siteID: Int64, lastFullSyncDate: Date) async throws {
48-
let modifiedAfter = lastIncrementalSyncDates[siteID] ?? lastFullSyncDate
47+
let modifiedAfter = try await latestSyncDate(siteID: siteID, lastFullSyncDate: lastFullSyncDate)
4948

5049
DDLogInfo("🔄 Starting incremental catalog sync for site ID: \(siteID), modifiedAfter: \(modifiedAfter)")
5150

@@ -57,8 +56,7 @@ public final class POSCatalogIncrementalSyncService: POSCatalogIncrementalSyncSe
5756
try await persistenceService.persistIncrementalCatalogData(catalog, siteID: siteID)
5857
DDLogInfo("✅ Persisted \(catalog.products.count) products and \(catalog.variations.count) variations to database for siteID \(siteID)")
5958

60-
// TODO: WOOMOB-1289 - replace with store settings persistence
61-
lastIncrementalSyncDates[siteID] = syncStartDate
59+
try await persistenceService.updateSite(.init(siteID: siteID, lastIncrementalSyncDate: syncStartDate))
6260
DDLogInfo("✅ Updated last incremental sync date to \(syncStartDate) for siteID \(siteID)")
6361
} catch {
6462
DDLogError("❌ Failed to sync and persist catalog incrementally: \(error)")
@@ -86,3 +84,11 @@ private extension POSCatalogIncrementalSyncService {
8684
return POSCatalog(products: products, variations: variations)
8785
}
8886
}
87+
88+
// MARK: - Sync date
89+
90+
private extension POSCatalogIncrementalSyncService {
91+
func latestSyncDate(siteID: Int64, lastFullSyncDate: Date) async throws -> Date {
92+
try await persistenceService.loadSite(siteID: siteID)?.lastIncrementalSyncDate ?? lastFullSyncDate
93+
}
94+
}

Modules/Sources/Yosemite/Tools/POS/POSCatalogPersistenceService.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ import Foundation
33
import Storage
44
import GRDB
55

6+
enum POSCatalogPersistenceError: Error, Equatable {
7+
case siteNotFound(siteID: Int64)
8+
}
9+
610
protocol POSCatalogPersistenceServiceProtocol {
711
/// Clears existing data and persists new catalog data
812
/// - Parameters:
@@ -15,6 +19,15 @@ protocol POSCatalogPersistenceServiceProtocol {
1519
/// - catalog: The catalog difference to persist
1620
/// - siteID: The site ID to associate the catalog with
1721
func persistIncrementalCatalogData(_ catalog: POSCatalog, siteID: Int64) async throws
22+
23+
/// Loads the POS site for the given site ID
24+
/// - Parameter siteID: The site ID to load the POSSite for
25+
/// - Returns: The loaded POSSite or nil if not found in storage
26+
func loadSite(siteID: Int64) async throws -> POSSite?
27+
28+
/// Updates the PersistedSite based on POSSite data
29+
/// - Parameter site: The POSSite containing the updated data
30+
func updateSite(_ site: POSSite) async throws
1831
}
1932

2033
final class POSCatalogPersistenceService: POSCatalogPersistenceServiceProtocol {
@@ -136,6 +149,23 @@ final class POSCatalogPersistenceService: POSCatalogPersistenceServiceProtocol {
136149
"\(variationImageCount) variation images, \(variationAttributeCount) variation attributes")
137150
}
138151
}
152+
153+
func loadSite(siteID: Int64) async throws -> POSSite? {
154+
try await grdbManager.databaseConnection.read { db in
155+
try PersistedSite.filter(key: siteID).fetchOne(db)?.toPOSSite()
156+
}
157+
}
158+
159+
func updateSite(_ site: POSSite) async throws {
160+
try await grdbManager.databaseConnection.write { db in
161+
guard try PersistedSite.filter(key: site.siteID).fetchOne(db) != nil else {
162+
throw POSCatalogPersistenceError.siteNotFound(siteID: site.siteID)
163+
}
164+
165+
let persistedSite = PersistedSite(from: site)
166+
try persistedSite.update(db)
167+
}
168+
}
139169
}
140170

141171
private extension POSCatalog {

Modules/Tests/YosemiteTests/Tools/POS/POSCatalogFullSyncServiceTests.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,8 @@ private final class MockPOSCatalogPersistenceService: POSCatalogPersistenceServi
184184
}
185185

186186
func persistIncrementalCatalogData(_ catalog: POSCatalog, siteID: Int64) async throws {}
187+
188+
func loadSite(siteID: Int64) async throws -> POSSite? { nil }
189+
190+
func updateSite(_ site: POSSite) async throws {}
187191
}

Modules/Tests/YosemiteTests/Tools/POS/POSCatalogIncrementalSyncServiceTests.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ private final class MockPOSCatalogPersistenceService: POSCatalogPersistenceServi
183183
private(set) var persistIncrementalCatalogDataLastPersistedSiteID: Int64?
184184
var persistIncrementalCatalogDataError: Error?
185185

186+
private var storedSites: [Int64: POSSite] = [:]
187+
186188
func replaceAllCatalogData(_ catalog: POSCatalog, siteID: Int64) async throws {}
187189

188190
func persistIncrementalCatalogData(_ catalog: POSCatalog, siteID: Int64) async throws {
@@ -193,4 +195,12 @@ private final class MockPOSCatalogPersistenceService: POSCatalogPersistenceServi
193195
throw error
194196
}
195197
}
198+
199+
func loadSite(siteID: Int64) async throws -> POSSite? {
200+
storedSites[siteID]
201+
}
202+
203+
func updateSite(_ site: POSSite) async throws {
204+
storedSites[site.siteID] = site
205+
}
196206
}

0 commit comments

Comments
 (0)