Skip to content

Commit a082672

Browse files
Fixed an issue where extra index manifests were created on certain writes and updates
Closes #147, #227
1 parent 4ad5a0e commit a082672

File tree

2 files changed

+160
-3
lines changed

2 files changed

+160
-3
lines changed

Sources/CodableDatastore/Persistence/Disk Persistence/Transaction/Transaction.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -950,7 +950,7 @@ extension DiskPersistence.Transaction {
950950
)
951951
createdIndexes.insert(newIndex)
952952
if createdIndexes.contains(existingIndex) {
953-
createdIndexes.insert(existingIndex)
953+
createdIndexes.remove(existingIndex)
954954
} else {
955955
deletedIndexes.insert(existingIndex)
956956
}
@@ -1044,7 +1044,7 @@ extension DiskPersistence.Transaction {
10441044
)
10451045
createdIndexes.insert(newIndex)
10461046
if createdIndexes.contains(existingIndex) {
1047-
createdIndexes.insert(existingIndex)
1047+
createdIndexes.remove(existingIndex)
10481048
} else {
10491049
deletedIndexes.insert(existingIndex)
10501050
}
@@ -1120,7 +1120,7 @@ extension DiskPersistence.Transaction {
11201120
)
11211121
createdIndexes.insert(newIndex)
11221122
if createdIndexes.contains(existingIndex) {
1123-
createdIndexes.insert(existingIndex)
1123+
createdIndexes.remove(existingIndex)
11241124
} else {
11251125
deletedIndexes.insert(existingIndex)
11261126
}

Tests/CodableDatastoreTests/DiskPersistenceDatastoreTests.swift

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,163 @@ final class DiskPersistenceDatastoreTests: XCTestCase, @unchecked Sendable {
2323
try? FileManager.default.removeItem(at: temporaryStoreURL)
2424
}
2525

26+
func testCreatingEmptyPersistence() async throws {
27+
struct TestFormat: DatastoreFormat {
28+
enum Version: Int, CaseIterable {
29+
case zero
30+
}
31+
32+
struct Instance: Codable, Identifiable {
33+
var id: String
34+
var value: String
35+
var index: Int
36+
var bucket: Int
37+
}
38+
39+
static let defaultKey: DatastoreKey = "test"
40+
static let currentVersion = Version.zero
41+
42+
let index = OneToOneIndex(\.index)
43+
@Direct var bucket = Index(\.bucket)
44+
}
45+
46+
let persistence = try DiskPersistence(readWriteURL: temporaryStoreURL)
47+
48+
_ = Datastore.JSONStore(
49+
persistence: persistence,
50+
format: TestFormat.self,
51+
migrations: [
52+
.zero: { data, decoder in
53+
try decoder.decode(TestFormat.Instance.self, from: data)
54+
}
55+
]
56+
)
57+
58+
try await persistence.createPersistenceIfNecessary()
59+
60+
let snapshotContents = try FileManager().contentsOfDirectory(at: temporaryStoreURL.appendingPathComponent("Snapshots", isDirectory: true), includingPropertiesForKeys: nil)
61+
XCTAssertEqual(snapshotContents.count, 0)
62+
}
63+
64+
func testCreatingEmptyDatastoreIndexesAfterRead() async throws {
65+
struct TestFormat: DatastoreFormat {
66+
enum Version: Int, CaseIterable {
67+
case zero
68+
}
69+
70+
struct Instance: Codable, Identifiable {
71+
var id: String
72+
var value: String
73+
var index: Int
74+
var bucket: Int
75+
}
76+
77+
static let defaultKey: DatastoreKey = "test"
78+
static let currentVersion = Version.zero
79+
80+
let index = OneToOneIndex(\.index)
81+
@Direct var bucket = Index(\.bucket)
82+
}
83+
84+
let persistence = try DiskPersistence(readWriteURL: temporaryStoreURL)
85+
86+
let datastore = Datastore.JSONStore(
87+
persistence: persistence,
88+
format: TestFormat.self,
89+
migrations: [
90+
.zero: { data, decoder in
91+
try decoder.decode(TestFormat.Instance.self, from: data)
92+
}
93+
]
94+
)
95+
96+
let count = try await datastore.count
97+
XCTAssertEqual(count, 0)
98+
99+
// TODO: Add code to verify that the Datastores directory is empty. This is true as of 2024-10-10, but has only been validated manually.
100+
}
101+
102+
func testCreatingEmptyDatastoreIndexesAfterSingleWrite() async throws {
103+
struct TestFormat: DatastoreFormat {
104+
enum Version: Int, CaseIterable {
105+
case zero
106+
}
107+
108+
struct Instance: Codable, Identifiable {
109+
var id: String
110+
var value: String
111+
var index: Int
112+
var bucket: Int
113+
}
114+
115+
static let defaultKey: DatastoreKey = "test"
116+
static let currentVersion = Version.zero
117+
118+
let index = OneToOneIndex(\.index)
119+
@Direct var bucket = Index(\.bucket)
120+
}
121+
122+
let persistence = try DiskPersistence(readWriteURL: temporaryStoreURL)
123+
124+
let datastore = Datastore.JSONStore(
125+
persistence: persistence,
126+
format: TestFormat.self,
127+
migrations: [
128+
.zero: { data, decoder in
129+
try decoder.decode(TestFormat.Instance.self, from: data)
130+
}
131+
]
132+
)
133+
134+
try await datastore.persist(.init(id: "0", value: "0", index: 0, bucket: 0))
135+
136+
let count = try await datastore.count
137+
XCTAssertEqual(count, 1)
138+
139+
// TODO: Add code to verify that the Index directories have a single manifest each. This is true as of 2024-10-10, but has only been validated manually.
140+
}
141+
142+
func testCreatingUnreferencedDatastoreIndexesAfterUpdate() async throws {
143+
struct TestFormat: DatastoreFormat {
144+
enum Version: Int, CaseIterable {
145+
case zero
146+
}
147+
148+
struct Instance: Codable, Identifiable {
149+
var id: String
150+
var value: String
151+
var index: Int
152+
var bucket: Int
153+
}
154+
155+
static let defaultKey: DatastoreKey = "test"
156+
static let currentVersion = Version.zero
157+
158+
let index = OneToOneIndex(\.index)
159+
@Direct var bucket = Index(\.bucket)
160+
}
161+
162+
let persistence = try DiskPersistence(readWriteURL: temporaryStoreURL)
163+
164+
let datastore = Datastore.JSONStore(
165+
persistence: persistence,
166+
format: TestFormat.self,
167+
migrations: [
168+
.zero: { data, decoder in
169+
try decoder.decode(TestFormat.Instance.self, from: data)
170+
}
171+
]
172+
)
173+
174+
try await datastore.persist(.init(id: "0", value: "0", index: 0, bucket: 0))
175+
try await datastore.persist(.init(id: "0", value: "0", index: 0, bucket: 0))
176+
177+
let count = try await datastore.count
178+
XCTAssertEqual(count, 1)
179+
180+
// TODO: Add code to verify that the Index directories have exactly two index manifests each. This is true as of 2024-10-10, but has only been validated manually.
181+
}
182+
26183
func testWritingEntry() async throws {
27184
struct TestFormat: DatastoreFormat {
28185
enum Version: Int, CaseIterable {

0 commit comments

Comments
 (0)