From 0a2b47483735a23c9f0e9612bcf55b212274714d Mon Sep 17 00:00:00 2001 From: leogdion Date: Fri, 4 Oct 2024 20:40:49 -0400 Subject: [PATCH] added auto-save and improved monitoring (#5) --- Sources/DataThespian/BackgroundDatabase.swift | 6 +++--- Sources/DataThespian/Database.swift | 1 + Sources/DataThespian/DatabaseKey.swift | 4 ++++ .../DataThespian/ManagedObjectMetadata.swift | 9 +++++---- Sources/DataThespian/ModelActorDatabase.swift | 20 ++++++++++++++++++- 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/Sources/DataThespian/BackgroundDatabase.swift b/Sources/DataThespian/BackgroundDatabase.swift index 1cc930a..e7edaac 100644 --- a/Sources/DataThespian/BackgroundDatabase.swift +++ b/Sources/DataThespian/BackgroundDatabase.swift @@ -42,7 +42,7 @@ public func delete(where predicate: Predicate?) async throws { try await self.database.delete(where: predicate) } - + public func save() async throws { try await self.database.save() } public func insert(_ closuer: @escaping @Sendable () -> some PersistentModel) async -> PersistentIdentifier { await self.database.insert(closuer) } @@ -90,10 +90,10 @@ private var database: any Database { get async { await container.database } } - public convenience init(modelContainer: ModelContainer) { + public convenience init(modelContainer: ModelContainer, autosaveEnabled: Bool = false) { self.init { assert(isMainThread: false) - return ModelActorDatabase(modelContainer: modelContainer) + return ModelActorDatabase(modelContainer: modelContainer, autosaveEnabled: autosaveEnabled) } } diff --git a/Sources/DataThespian/Database.swift b/Sources/DataThespian/Database.swift index 7ce6e95..93a0a69 100644 --- a/Sources/DataThespian/Database.swift +++ b/Sources/DataThespian/Database.swift @@ -34,6 +34,7 @@ public import SwiftData public protocol Database: Sendable { + func save() async throws @discardableResult func delete( _ modelType: T.Type, withID id: PersistentIdentifier diff --git a/Sources/DataThespian/DatabaseKey.swift b/Sources/DataThespian/DatabaseKey.swift index df46658..6ca2a39 100644 --- a/Sources/DataThespian/DatabaseKey.swift +++ b/Sources/DataThespian/DatabaseKey.swift @@ -36,6 +36,10 @@ public import SwiftUI fileprivate struct DefaultDatabase: Database { + public func save() async throws { + assertionFailure("No Database Set.") + throw NotImplmentedError.instance + } func delete(_: (some PersistentModel).Type, withID _: PersistentIdentifier) async -> Bool { assertionFailure("No Database Set.") return false diff --git a/Sources/DataThespian/ManagedObjectMetadata.swift b/Sources/DataThespian/ManagedObjectMetadata.swift index 0a09ce7..be45fd3 100644 --- a/Sources/DataThespian/ManagedObjectMetadata.swift +++ b/Sources/DataThespian/ManagedObjectMetadata.swift @@ -51,10 +51,11 @@ assertionFailure(error: error) return nil } - self.init( - entityName: managedObject.entity.managedObjectClassName, - persistentIdentifier: persistentIdentifier - ) + guard let entityName = managedObject.entity.name else { + assertionFailure("Missing entity name.") + return nil + } + self.init(entityName: entityName, persistentIdentifier: persistentIdentifier) } } #endif diff --git a/Sources/DataThespian/ModelActorDatabase.swift b/Sources/DataThespian/ModelActorDatabase.swift index c064398..09532ad 100644 --- a/Sources/DataThespian/ModelActorDatabase.swift +++ b/Sources/DataThespian/ModelActorDatabase.swift @@ -33,7 +33,7 @@ public import SwiftData - @ModelActor public actor ModelActorDatabase: Database, Loggable { + public actor ModelActorDatabase: Database, Loggable { public func delete(_: T.Type, withID id: PersistentIdentifier) async -> Bool { guard let model: T = self.modelContext.registeredModel(for: id) else { return false } @@ -88,6 +88,24 @@ try block(modelContext) } } + public func save() throws { + assert(isMainThread: false) + try self.modelContext.save() + } + public nonisolated let modelExecutor: any SwiftData.ModelExecutor + public nonisolated let modelContainer: SwiftData.ModelContainer + public init(modelContainer: SwiftData.ModelContainer, autosaveEnabled: Bool = false) { + let modelContext = ModelContext(modelContainer) + modelContext.autosaveEnabled = autosaveEnabled + let modelExecutor = DefaultSerialModelExecutor(modelContext: modelContext) + self.init(modelExecutor: modelExecutor, modelContainer: modelContainer) + } + private init(modelExecutor: any ModelExecutor, modelContainer: ModelContainer) { + self.modelExecutor = modelExecutor + self.modelContainer = modelContainer + } } + extension ModelActorDatabase: SwiftData.ModelActor {} + #endif