|
358 | 358 | public func start() async throws { |
359 | 359 | try await start().value |
360 | 360 | } |
361 | | - |
| 361 | + |
362 | 362 | /// Determines if the sync engine is currently sending local changes to the CloudKit server. |
363 | 363 | /// |
364 | 364 | /// It is an observable value, which means if it is accessed in a SwiftUI view, or some other |
|
872 | 872 | ) |
873 | 873 |
|
874 | 874 | case .willFetchRecordZoneChanges: |
875 | | - fetchingChangesCount += 1 |
| 875 | + await MainActor.run { |
| 876 | + fetchingChangesCount += 1 |
| 877 | + } |
876 | 878 | case .didFetchRecordZoneChanges: |
877 | | - fetchingChangesCount -= 1 |
| 879 | + await MainActor.run { |
| 880 | + fetchingChangesCount -= 1 |
| 881 | + } |
878 | 882 |
|
879 | 883 | case .willFetchChanges: |
880 | | - fetchingChangesCount += 1 |
| 884 | + await MainActor.run { |
| 885 | + fetchingChangesCount += 1 |
| 886 | + } |
881 | 887 | case .didFetchChanges: |
882 | | - fetchingChangesCount -= 1 |
| 888 | + await MainActor.run { |
| 889 | + fetchingChangesCount -= 1 |
| 890 | + } |
883 | 891 |
|
884 | 892 | case .willSendChanges: |
885 | | - sendingChangesCount += 1 |
| 893 | + await MainActor.run { |
| 894 | + sendingChangesCount += 1 |
| 895 | + } |
886 | 896 | case .didSendChanges: |
887 | | - sendingChangesCount -= 1 |
| 897 | + await MainActor.run { |
| 898 | + sendingChangesCount -= 1 |
| 899 | + } |
888 | 900 |
|
889 | 901 | @unknown default: |
890 | 902 | break |
|
1076 | 1088 | } |
1077 | 1089 | } |
1078 | 1090 |
|
1079 | | - let (sharesToDelete, recordsWithRoot): |
1080 | | - ([CKShare?], [(lastKnownServerRecord: CKRecord?, rootLastKnownServerRecord: CKRecord?)]) = |
1081 | | - await withErrorReporting(.sqliteDataCloudKitFailure) { |
1082 | | - guard !deletedRecordIDs.isEmpty |
1083 | | - else { return ([], []) } |
1084 | | - |
1085 | | - return try await metadatabase.read { db in |
1086 | | - let sharesToDelete = |
1087 | | - try SyncMetadata |
1088 | | - .findAll(deletedRecordIDs) |
1089 | | - .where(\.isShared) |
1090 | | - .select(\.share) |
1091 | | - .fetchAll(db) |
| 1091 | + if syncEngine.database.databaseScope == .shared { |
| 1092 | + let (sharesToDelete, recordsWithRoot): |
| 1093 | + ([CKShare?], [(lastKnownServerRecord: CKRecord?, rootLastKnownServerRecord: CKRecord?)]) = |
| 1094 | + await withErrorReporting(.sqliteDataCloudKitFailure) { |
| 1095 | + guard !deletedRecordIDs.isEmpty |
| 1096 | + else { return ([], []) } |
| 1097 | + |
| 1098 | + return try await metadatabase.read { db in |
| 1099 | + let sharesToDelete = |
| 1100 | + try SyncMetadata |
| 1101 | + .findAll(deletedRecordIDs) |
| 1102 | + .where(\.isShared) |
| 1103 | + .select(\.share) |
| 1104 | + .fetchAll(db) |
1092 | 1105 |
|
1093 | | - let recordsWithRoot = |
1094 | | - try With { |
1095 | | - SyncMetadata |
1096 | | - .findAll(deletedRecordIDs) |
1097 | | - .where { $0.parentRecordName.is(nil) } |
1098 | | - .select { |
1099 | | - RecordWithRoot.Columns( |
1100 | | - parentRecordName: $0.parentRecordName, |
1101 | | - recordName: $0.recordName, |
1102 | | - lastKnownServerRecord: $0.lastKnownServerRecord, |
1103 | | - rootRecordName: $0.recordName, |
1104 | | - rootLastKnownServerRecord: $0.lastKnownServerRecord |
| 1106 | + let recordsWithRoot = |
| 1107 | + try With { |
| 1108 | + SyncMetadata |
| 1109 | + .findAll(deletedRecordIDs) |
| 1110 | + .where { $0.parentRecordName.is(nil) } |
| 1111 | + .select { |
| 1112 | + RecordWithRoot.Columns( |
| 1113 | + parentRecordName: $0.parentRecordName, |
| 1114 | + recordName: $0.recordName, |
| 1115 | + lastKnownServerRecord: $0.lastKnownServerRecord, |
| 1116 | + rootRecordName: $0.recordName, |
| 1117 | + rootLastKnownServerRecord: $0.lastKnownServerRecord |
| 1118 | + ) |
| 1119 | + } |
| 1120 | + .union( |
| 1121 | + all: true, |
| 1122 | + SyncMetadata |
| 1123 | + .join(RecordWithRoot.all) { $1.recordName.is($0.parentRecordName) } |
| 1124 | + .select { metadata, tree in |
| 1125 | + RecordWithRoot.Columns( |
| 1126 | + parentRecordName: metadata.parentRecordName, |
| 1127 | + recordName: metadata.recordName, |
| 1128 | + lastKnownServerRecord: metadata.lastKnownServerRecord, |
| 1129 | + rootRecordName: tree.rootRecordName, |
| 1130 | + rootLastKnownServerRecord: tree.lastKnownServerRecord |
| 1131 | + ) |
| 1132 | + } |
1105 | 1133 | ) |
1106 | | - } |
1107 | | - .union( |
1108 | | - all: true, |
1109 | | - SyncMetadata |
1110 | | - .join(RecordWithRoot.all) { $1.recordName.is($0.parentRecordName) } |
1111 | | - .select { metadata, tree in |
1112 | | - RecordWithRoot.Columns( |
1113 | | - parentRecordName: metadata.parentRecordName, |
1114 | | - recordName: metadata.recordName, |
1115 | | - lastKnownServerRecord: metadata.lastKnownServerRecord, |
1116 | | - rootRecordName: tree.rootRecordName, |
1117 | | - rootLastKnownServerRecord: tree.lastKnownServerRecord |
1118 | | - ) |
1119 | | - } |
1120 | | - ) |
1121 | | - } query: { |
1122 | | - RecordWithRoot |
1123 | | - .select { ($0.lastKnownServerRecord, $0.rootLastKnownServerRecord) } |
1124 | | - } |
1125 | | - .fetchAll(db) |
| 1134 | + } query: { |
| 1135 | + RecordWithRoot |
| 1136 | + .select { ($0.lastKnownServerRecord, $0.rootLastKnownServerRecord) } |
| 1137 | + } |
| 1138 | + .fetchAll(db) |
1126 | 1139 |
|
1127 | | - return (sharesToDelete, recordsWithRoot) |
| 1140 | + return (sharesToDelete, recordsWithRoot) |
| 1141 | + } |
1128 | 1142 | } |
1129 | | - } |
1130 | | - ?? ([], []) |
| 1143 | + ?? ([], []) |
1131 | 1144 |
|
1132 | | - let shareRecordIDsToDelete = sharesToDelete.compactMap(\.?.recordID) |
| 1145 | + let shareRecordIDsToDelete = sharesToDelete.compactMap(\.?.recordID) |
1133 | 1146 |
|
1134 | | - for recordWithRoot in recordsWithRoot { |
1135 | | - guard |
1136 | | - let lastKnownServerRecord = recordWithRoot.lastKnownServerRecord, |
1137 | | - let rootLastKnownServerRecord = recordWithRoot.rootLastKnownServerRecord |
1138 | | - else { continue } |
1139 | | - guard let rootShareRecordID = rootLastKnownServerRecord.share?.recordID |
1140 | | - else { continue } |
1141 | | - guard shareRecordIDsToDelete.contains(rootShareRecordID) |
1142 | | - else { continue } |
1143 | | - changes.removeAll(where: { $0 == .deleteRecord(lastKnownServerRecord.recordID) }) |
1144 | | - syncEngine.state.remove( |
1145 | | - pendingRecordZoneChanges: [.deleteRecord(lastKnownServerRecord.recordID)] |
1146 | | - ) |
| 1147 | + for recordWithRoot in recordsWithRoot { |
| 1148 | + guard |
| 1149 | + let lastKnownServerRecord = recordWithRoot.lastKnownServerRecord, |
| 1150 | + let rootLastKnownServerRecord = recordWithRoot.rootLastKnownServerRecord |
| 1151 | + else { continue } |
| 1152 | + guard let rootShareRecordID = rootLastKnownServerRecord.share?.recordID |
| 1153 | + else { continue } |
| 1154 | + guard shareRecordIDsToDelete.contains(rootShareRecordID) |
| 1155 | + else { continue } |
| 1156 | + changes.removeAll(where: { $0 == .deleteRecord(lastKnownServerRecord.recordID) }) |
| 1157 | + syncEngine.state.remove( |
| 1158 | + pendingRecordZoneChanges: [.deleteRecord(lastKnownServerRecord.recordID)] |
| 1159 | + ) |
| 1160 | + } |
1147 | 1161 | } |
1148 | 1162 |
|
1149 | 1163 | await withErrorReporting(.sqliteDataCloudKitFailure) { |
|
1618 | 1632 | } |
1619 | 1633 |
|
1620 | 1634 | func deleteShare(shareRecordID: CKRecord.ID) async throws { |
1621 | | - try await userDatabase.write { db in |
1622 | | - let shareAndRecordNameAndZone = |
1623 | | - try SyncMetadata |
| 1635 | + let shareAndRecordNameAndZone = try await userDatabase.read { db in |
| 1636 | + try SyncMetadata |
1624 | 1637 | .where(\.isShared) |
1625 | 1638 | .select { ($0.share, $0.recordName, $0.zoneName, $0.ownerName) } |
1626 | 1639 | .fetchAll(db) |
1627 | 1640 | .first(where: { share, _, _, _ in share?.recordID == shareRecordID }) ?? nil |
1628 | | - guard let (_, recordName, zoneName, ownerName) = shareAndRecordNameAndZone |
1629 | | - else { return } |
| 1641 | + } |
| 1642 | + guard let (_, recordName, zoneName, ownerName) = shareAndRecordNameAndZone |
| 1643 | + else { return } |
| 1644 | + let rootRecordID = CKRecord.ID( |
| 1645 | + recordName: recordName, |
| 1646 | + zoneID: CKRecordZone.ID(zoneName: zoneName, ownerName: ownerName) |
| 1647 | + ) |
| 1648 | + let rootRecord = try await container.privateCloudDatabase.record(for: rootRecordID) |
| 1649 | + try await userDatabase.write { db in |
1630 | 1650 | try SyncMetadata |
1631 | 1651 | .find( |
1632 | 1652 | CKRecord.ID( |
1633 | 1653 | recordName: recordName, |
1634 | 1654 | zoneID: CKRecordZone.ID(zoneName: zoneName, ownerName: ownerName) |
1635 | 1655 | ) |
1636 | 1656 | ) |
1637 | | - .update { $0.share = nil } |
| 1657 | + .update { |
| 1658 | + $0.setLastKnownServerRecord(rootRecord) |
| 1659 | + $0.share = nil |
| 1660 | + } |
1638 | 1661 | .execute(db) |
1639 | 1662 | } |
1640 | 1663 | } |
|
0 commit comments