Ignore unmappable Core Data entities (#660)

But implement .discard for testing.
This commit is contained in:
Davide 2024-10-02 13:35:49 +02:00 committed by GitHub
parent f602655568
commit 3fbf803518
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 25 additions and 10 deletions

View File

@ -35,7 +35,7 @@ extension AppData {
registry: Registry,
coder: ProfileCoder,
context: NSManagedObjectContext,
onResultError: ((Error) -> Bool)?
onResultError: ((Error) -> CoreDataResultAction)?
) -> any ProfileRepository {
let repository = CoreDataRepository<CDProfile, Profile>(context: context) {
$0.sortDescriptors = [
@ -57,7 +57,7 @@ extension AppData {
cdProfile.lastUpdate = Date()
return cdProfile
} onResultError: {
onResultError?($0) ?? true
onResultError?($0) ?? .ignore
}
return repository

View File

@ -31,10 +31,19 @@ public protocol CoreDataUniqueEntity: NSManagedObject, UniqueEntity {
// Core Data entity must have a unique "uuid" field
}
public enum CoreDataResultAction {
case ignore
case discard
case halt
}
public actor CoreDataRepository<CD, T>: NSObject,
Repository,
NSFetchedResultsControllerDelegate where CD: CoreDataUniqueEntity,
T: UniqueEntity {
private let entityName: String
private let context: NSManagedObjectContext
@ -43,7 +52,7 @@ public actor CoreDataRepository<CD, T>: NSObject,
private let toMapper: (T, NSManagedObjectContext) throws -> CD
private let onResultError: ((Error) -> Bool)? // true = keep going
private let onResultError: ((Error) -> CoreDataResultAction)?
private let entitiesSubject: CurrentValueSubject<EntitiesResult<T>, Never>
@ -55,7 +64,7 @@ public actor CoreDataRepository<CD, T>: NSObject,
beforeFetch: ((NSFetchRequest<CD>) -> Void)? = nil,
fromMapper: @escaping (CD) throws -> T?,
toMapper: @escaping (T, NSManagedObjectContext) throws -> CD,
onResultError: ((Error) -> Bool)? = nil
onResultError: ((Error) -> CoreDataResultAction)? = nil
) {
guard let entityName = CD.entity().name else {
fatalError("Unable to find entity name for \(CD.self)")
@ -193,16 +202,22 @@ private extension CoreDataRepository {
do {
return try self?.fromMapper($0)
} catch {
if let onResultError = self?.onResultError {
switch self?.onResultError?(error) {
case .discard:
self?.context.delete($0)
// on false, discard results
guard onResultError(error) else {
throw ResultError.mapping(error)
}
case .halt:
throw ResultError.mapping(error)
default:
break
}
return nil
}
}
try self?.context.save()
let result = EntitiesResult(entities, isFiltering: controller.fetchRequest.predicate != nil)
self?.entitiesSubject.send(result)
} catch {

View File

@ -50,7 +50,7 @@ extension ProfileManager {
context: store.context
) { error in
pp_log(.app, .error, "Unable to decode result: \(error)")
return true
return .ignore
}
return ProfileManager(repository: repository)