Skip to content

Commit

Permalink
Fixed an issue where loading from a fresh datastore would throw an error
Browse files Browse the repository at this point in the history
Fixes #163
  • Loading branch information
dimitribouniol committed Mar 6, 2024
1 parent e4fe1fa commit a277a94
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 34 deletions.
77 changes: 44 additions & 33 deletions Sources/CodableDatastore/Datastore/Datastore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,9 @@ extension Datastore {
return instance
} catch DatastoreInterfaceError.instanceNotFound {
return nil
} catch DatastoreInterfaceError.datastoreKeyNotFound {
/// There isn't a datastore yet, so no entries would exist either.
return nil
} catch {
throw error
}
Expand All @@ -496,12 +499,16 @@ extension Datastore {
actionName: nil,
options: [.readOnly]
) { transaction, _ in
try await transaction.primaryIndexScan(range: range.applying(order), datastoreKey: self.key) { versionData, instanceData in
let entryVersion = try Version(versionData)
let decoder = try await self.decoder(for: entryVersion)
let decodedValue = try await decoder(instanceData)

try await provider.yield(decodedValue)
do {
try await transaction.primaryIndexScan(range: range.applying(order), datastoreKey: self.key) { versionData, instanceData in
let entryVersion = try Version(versionData)
let decoder = try await self.decoder(for: entryVersion)
let decodedValue = try await decoder(instanceData)

try await provider.yield(decodedValue)
}
} catch DatastoreInterfaceError.datastoreKeyNotFound {
/// There isn't a datastore yet, so no entries would exist either. Do nothing and let the stream end.
}
}
}
Expand Down Expand Up @@ -542,34 +549,38 @@ extension Datastore {
actionName: nil,
options: [.readOnly]
) { transaction, _ in
let isDirectIndex = self.directIndexes.contains { $0.path == indexPath.path }

if isDirectIndex {
try await transaction.directIndexScan(
range: range.applying(order),
indexName: indexPath.path,
datastoreKey: self.key
) { versionData, instanceData in
let entryVersion = try Version(versionData)
let decoder = try await self.decoder(for: entryVersion)
let instance = try await decoder(instanceData).instance

try await provider.yield(instance)
}
} else {
try await transaction.secondaryIndexScan(
range: range.applying(order),
indexName: indexPath.path,
datastoreKey: self.key
) { (identifier: IdentifierType) in
let persistedEntry = try await transaction.primaryIndexCursor(for: identifier, datastoreKey: self.key)

let entryVersion = try Version(persistedEntry.versionData)
let decoder = try await self.decoder(for: entryVersion)
let instance = try await decoder(persistedEntry.instanceData).instance

try await provider.yield(instance)
do {
let isDirectIndex = self.directIndexes.contains { $0.path == indexPath.path }

if isDirectIndex {
try await transaction.directIndexScan(
range: range.applying(order),
indexName: indexPath.path,
datastoreKey: self.key
) { versionData, instanceData in
let entryVersion = try Version(versionData)
let decoder = try await self.decoder(for: entryVersion)
let instance = try await decoder(instanceData).instance

try await provider.yield(instance)
}
} else {
try await transaction.secondaryIndexScan(
range: range.applying(order),
indexName: indexPath.path,
datastoreKey: self.key
) { (identifier: IdentifierType) in
let persistedEntry = try await transaction.primaryIndexCursor(for: identifier, datastoreKey: self.key)

let entryVersion = try Version(persistedEntry.versionData)
let decoder = try await self.decoder(for: entryVersion)
let instance = try await decoder(persistedEntry.instanceData).instance

try await provider.yield(instance)
}
}
} catch DatastoreInterfaceError.datastoreKeyNotFound {
/// There isn't a datastore yet, so no entries would exist either. Do nothing and let the stream end.
}
}
}
Expand Down
14 changes: 13 additions & 1 deletion Tests/CodableDatastoreTests/DiskPersistenceDatastoreTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ final class DiskPersistenceDatastoreTests: XCTestCase {
]
)

let count = try await datastore.count
XCTAssertEqual(count, 0)

let entry0 = try await datastore.load("0")
XCTAssertNil(entry0)

try await datastore.persist(TestStruct(id: "3", value: "My name is Dimitri"))
try await datastore.persist(TestStruct(id: "1", value: "Hello, World!"))
try await datastore.persist(TestStruct(id: "2", value: "Twenty Three is Number One"))
Expand All @@ -96,6 +102,8 @@ final class DiskPersistenceDatastoreTests: XCTestCase {
let count = try await datastore.count
XCTAssertEqual(count, 3)

let entry0 = try await datastore.load("0")
XCTAssertNil(entry0)
let entry1 = try await datastore.load("1")
XCTAssertEqual(entry1?.value, "Hello, World!")
let entry2 = try await datastore.load("2")
Expand Down Expand Up @@ -215,6 +223,10 @@ final class DiskPersistenceDatastoreTests: XCTestCase {
]
)

/// Read before persisting anything
var values = try await datastore.load(...).map { $0.value }.reduce(into: []) { $0.append($1) }
XCTAssertEqual(values, [])

for n in 0..<200 {
try await datastore.persist(TestStruct(id: n*2, value: "\(n*2)"))
}
Expand All @@ -223,7 +235,7 @@ final class DiskPersistenceDatastoreTests: XCTestCase {
XCTAssertEqual(count, 200)

/// Simple ranges
var values = try await datastore.load(5..<9).map { $0.value }.reduce(into: []) { $0.append($1) }
values = try await datastore.load(5..<9).map { $0.value }.reduce(into: []) { $0.append($1) }
XCTAssertEqual(values, ["6", "8"])

values = try await datastore.load((5..<9).reversed).map { $0.value }.reduce(into: []) { $0.append($1) }
Expand Down

0 comments on commit a277a94

Please sign in to comment.