Skip to content

Commit 71085a0

Browse files
committed
Initial rework of conflict detection
1 parent 8277983 commit 71085a0

1 file changed

Lines changed: 33 additions & 1 deletion

File tree

Sources/SQLiteData/CloudKit/SyncEngine.swift

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1943,7 +1943,39 @@
19431943
return
19441944
}
19451945

1946-
serverRecord.userModificationTime = metadata.userModificationTime
1946+
let ancestorRecord = metadata._lastKnownServerRecordAllFields
1947+
1948+
let hasServerChanged: Bool = {
1949+
guard
1950+
let ancestorRecord,
1951+
let ancestorChangeTag = ancestorRecord.recordChangeTag,
1952+
let serverChangeTag = serverRecord.recordChangeTag
1953+
else {
1954+
// Without an ancestor, the server record is upserted as-is. In the unlikely edge
1955+
// case where a matching client row exists, it gets overwritten.
1956+
return true
1957+
}
1958+
return ancestorChangeTag != serverChangeTag
1959+
}()
1960+
1961+
let hasClientChanged: Bool = {
1962+
// Without an ancestor, we can't detect client changes (no baseline to compare
1963+
// against). This effectively falls through to server wins.
1964+
guard let ancestorRecord else { return false }
1965+
return metadata.userModificationTime > ancestorRecord.userModificationTime
1966+
}()
1967+
1968+
let hasConflict = hasServerChanged && hasClientChanged
1969+
print("hasServerChanged", hasServerChanged, "hasClientChanged", hasClientChanged, "hasConflict", hasConflict)
1970+
1971+
if hasConflict {
1972+
// Sets the record-level userModificationTime to the max of the client and server
1973+
// modification times, which effectively records the time at which the conflict
1974+
// resolution has happened. The resolved record is then stored as the new last-known
1975+
// server record, ensuring that per-field timestamps on the next upload reflect
1976+
// the resolution time rather than the server's original timestamps.
1977+
serverRecord.userModificationTime = metadata.userModificationTime
1978+
}
19471979

19481980
func open<T>(_ table: some SynchronizableTable<T>) throws {
19491981
var columnNamesToUpsert = Set(T.TableColumns.writableColumns.map(\.name))

0 commit comments

Comments
 (0)