Skip to content

Instantly share code, notes, and snippets.

@juanarzola
Last active August 20, 2024 23:37
Show Gist options
  • Save juanarzola/9aa64312425e97cb42c33abf93d3d34a to your computer and use it in GitHub Desktop.
Save juanarzola/9aa64312425e97cb42c33abf93d3d34a to your computer and use it in GitHub Desktop.
Convenience extension for running ModelActor code in the background
extension ModelContainer {
// non-throwing version
nonisolated func runNonisolated<ResultType, ActorType: InitWithModelContainer>(
action: @Sendable (_ actor: ActorType) async -> ResultType
) async -> ResultType {
let actor = ActorType(modelContainer: self)
let result = await action(actor)
return result
}
// throwing version
nonisolated func runNonisolated<ResultType, ActorType: InitWithModelContainer>(
action: @Sendable (_ actor: ActorType) async throws -> ResultType
) async throws -> ResultType {
let actor = ActorType(modelContainer: self)
let result = try await action(actor)
return result
}
}
protocol InitWithModelContainer {
init(modelContainer: ModelContainer)
}
// MARK: - Usage:
// Conform your @ModelActor to InitWithModelContainer (nothing needs to be implemented, the macro does it)
@ModelActor
actor StudyStatsActor: InitWithModelContainer {
func stats(forMonth:)
}
// Calling runNonisolated (in this case, from a MainActor task):
.task {
// closure must be sendable
self.stats = await modelContext.container.runNonisolated { (actor: StudyStatsActor) in
await actor.stats(forMonth: self.month, in: calendar)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment