Skip to content

Commit 5cf865c

Browse files
authored
Use metadatabase to query sync metadata. (#270)
* Use metadatabase to query sync metadata. * Added a test * dont attach metadatabase for base suite. * add test for attached metadatabase
1 parent 97b0f96 commit 5cf865c

5 files changed

Lines changed: 136 additions & 7 deletions

File tree

Sources/SQLiteData/CloudKit/SyncEngine.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1670,7 +1670,7 @@
16701670
}
16711671

16721672
func deleteShare(shareRecordID: CKRecord.ID) async throws {
1673-
let shareAndRecordNameAndZone = try await userDatabase.read { db in
1673+
let shareAndRecordNameAndZone = try await metadatabase.read { db in
16741674
try SyncMetadata
16751675
.where(\.isShared)
16761676
.select { ($0.share, $0.recordName, $0.zoneName, $0.ownerName) }
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#if canImport(CloudKit)
2+
import CloudKit
3+
import ConcurrencyExtras
4+
import CustomDump
5+
import InlineSnapshotTesting
6+
import OrderedCollections
7+
import SQLiteData
8+
import SQLiteDataTestSupport
9+
import SnapshotTestingCustomDump
10+
import Testing
11+
12+
extension BaseCloudKitTests {
13+
@MainActor
14+
@Suite(.attachMetadatabase(true))
15+
final class AttachedMetadatabaseTests: BaseCloudKitTests, @unchecked Sendable {
16+
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
17+
@Test func basics() async throws {
18+
let remindersList = RemindersList(id: 1, title: "Personal")
19+
try await userDatabase.userWrite { db in
20+
try db.seed {
21+
remindersList
22+
}
23+
}
24+
try await syncEngine.processPendingRecordZoneChanges(scope: .private)
25+
26+
assertQuery(
27+
RemindersList
28+
.leftJoin(SyncMetadata.all) { $0.syncMetadataID.eq($1.id) },
29+
database: userDatabase.database
30+
) {
31+
"""
32+
┌─────────────────────┬────────────────────────────────────────────────────────────────────┐
33+
│ RemindersList( │ SyncMetadata( │
34+
│ id: 1, │ id: SyncMetadata.ID( │
35+
│ title: "Personal" │ recordPrimaryKey: "1", │
36+
│ ) │ recordType: "remindersLists"
37+
│ │ ), │
38+
│ │ zoneName: "zone", │
39+
│ │ ownerName: "__defaultOwner__", │
40+
│ │ recordName: "1:remindersLists", │
41+
│ │ parentRecordID: nil, │
42+
│ │ parentRecordName: nil, │
43+
│ │ lastKnownServerRecord: CKRecord( │
44+
│ │ recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__), │
45+
│ │ recordType: "remindersLists", │
46+
│ │ parent: nil, │
47+
│ │ share: nil │
48+
│ │ ), │
49+
│ │ _lastKnownServerRecordAllFields: CKRecord( │
50+
│ │ recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__), │
51+
│ │ recordType: "remindersLists", │
52+
│ │ parent: nil, │
53+
│ │ share: nil, │
54+
│ │ id: 1, │
55+
│ │ title: "Personal"
56+
│ │ ), │
57+
│ │ share: nil, │
58+
│ │ _isDeleted: false, │
59+
│ │ hasLastKnownServerRecord: true, │
60+
│ │ isShared: false, │
61+
│ │ userModificationTime: 0 │
62+
│ │ ) │
63+
└─────────────────────┴────────────────────────────────────────────────────────────────────┘
64+
"""
65+
}
66+
}
67+
}
68+
}
69+
#endif

Tests/SQLiteDataTests/CloudKitTests/SharingTests.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2753,6 +2753,52 @@
27532753
"""
27542754
}
27552755
}
2756+
2757+
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
2758+
@Test func deleteShare() async throws {
2759+
let remindersList = RemindersList(id: 1, title: "Personal")
2760+
try await userDatabase.userWrite { db in
2761+
try db.seed {
2762+
remindersList
2763+
}
2764+
}
2765+
try await syncEngine.processPendingRecordZoneChanges(scope: .private)
2766+
2767+
let sharedRecord = try await syncEngine.share(record: remindersList, configure: { _ in })
2768+
2769+
try await syncEngine
2770+
.modifyRecords(scope: .private, deleting: [sharedRecord.share.recordID])
2771+
.notify()
2772+
2773+
assertQuery(SyncMetadata.select(\.share), database: syncEngine.metadatabase) {
2774+
"""
2775+
┌─────┐
2776+
│ nil │
2777+
└─────┘
2778+
"""
2779+
}
2780+
assertInlineSnapshot(of: container, as: .customDump) {
2781+
"""
2782+
MockCloudContainer(
2783+
privateCloudDatabase: MockCloudDatabase(
2784+
databaseScope: .private,
2785+
storage: [
2786+
[0]: CKRecord(
2787+
recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__),
2788+
recordType: "remindersLists",
2789+
parent: nil,
2790+
share: CKReference(recordID: CKRecord.ID(share-1:remindersLists/zone/__defaultOwner__))
2791+
)
2792+
]
2793+
),
2794+
sharedCloudDatabase: MockCloudDatabase(
2795+
databaseScope: .shared,
2796+
storage: []
2797+
)
2798+
)
2799+
"""
2800+
}
2801+
}
27562802
}
27572803
}
27582804
#endif

Tests/SQLiteDataTests/Internal/BaseCloudKitTests.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import os
1111
.dependencies {
1212
$0.currentTime.now = 0
1313
$0.dataManager = InMemoryDataManager()
14-
}
14+
},
15+
.attachMetadatabase(false)
1516
)
1617
class BaseCloudKitTests: @unchecked Sendable {
1718
let userDatabase: UserDatabase

Tests/SQLiteDataTests/Internal/CloudKitTestHelpers.swift

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ extension PrimaryKeyedTable where PrimaryKey.QueryOutput: IdentifierStringConver
2020

2121
@available(iOS 17, macOS 14, tvOS 17, watchOS 10, *)
2222
extension SyncEngine {
23-
struct ModifyRecordsCallback {
24-
fileprivate let operation: @Sendable () async -> Void
25-
func notify() async {
23+
struct ModifyRecordsCallback<ReturnValue> {
24+
fileprivate let operation: @Sendable () async -> ReturnValue
25+
@discardableResult
26+
func notify() async -> ReturnValue {
2627
await operation()
2728
}
2829
}
@@ -31,7 +32,12 @@ extension SyncEngine {
3132
scope: CKDatabase.Scope,
3233
saving recordZonesToSave: [CKRecordZone] = [],
3334
deleting recordZoneIDsToDelete: [CKRecordZone.ID] = []
34-
) throws -> ModifyRecordsCallback {
35+
) throws -> ModifyRecordsCallback<
36+
(
37+
saveResults: [CKRecordZone.ID: Result<CKRecordZone, any Error>],
38+
deleteResults: [CKRecordZone.ID: Result<Void, any Error>]
39+
)
40+
> {
3541
let syncEngine = syncEngine(for: scope)
3642

3743
let (saveResults, deleteResults) = try syncEngine.database.modifyRecordZones(
@@ -52,14 +58,20 @@ extension SyncEngine {
5258
),
5359
syncEngine: syncEngine
5460
)
61+
return (saveResults, deleteResults)
5562
}
5663
}
5764

5865
func modifyRecords(
5966
scope: CKDatabase.Scope,
6067
saving recordsToSave: [CKRecord] = [],
6168
deleting recordIDsToDelete: [CKRecord.ID] = []
62-
) throws -> ModifyRecordsCallback {
69+
) throws -> ModifyRecordsCallback<
70+
(
71+
saveResults: [CKRecord.ID: Result<CKRecord, any Error>],
72+
deleteResults: [CKRecord.ID: Result<Void, any Error>]
73+
)
74+
> {
6375
let syncEngine = syncEngine(for: scope)
6476
let recordsToDeleteByID = Dictionary(
6577
grouping: syncEngine.database.storage.withValue { storage in
@@ -90,6 +102,7 @@ extension SyncEngine {
90102
),
91103
syncEngine: syncEngine
92104
)
105+
return (saveResults, deleteResults)
93106
}
94107
}
95108

0 commit comments

Comments
 (0)