Encapsulate *Persistence responsibilities (#305)

Do not leave the choice of a repository context up to the library
consumer. Instead, provide a specific factory (*Persistence) for each
module.
This commit is contained in:
Davide De Rosa 2023-05-27 12:32:53 +02:00 committed by GitHub
parent efcda495bc
commit a78a7b18b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 46 additions and 40 deletions

View File

@ -33,18 +33,18 @@ import TunnelKitManager
final class CoreContext {
let store: KeyValueStore
private let profilesPersistence: CoreDataPersistentStore
private let providersPersistence: ProvidersPersistence
private let providersPersistence: CoreDataPersistentStore
var urlsForProfiles: [URL]? {
profilesPersistence.containerURLs
}
private let vpnPersistence: VPNPersistence
var urlsForProviders: [URL]? {
providersPersistence.containerURLs
}
var urlsForProfiles: [URL]? {
vpnPersistence.containerURLs
}
let upgradeManager: UpgradeManager
let providerManager: ProviderManager
@ -67,7 +67,7 @@ final class CoreContext {
pp_log.info("Logging to: \(logger.logFile!)")
let persistenceManager = PersistenceManager(store: store)
profilesPersistence = persistenceManager.profilesPersistence(
vpnPersistence = persistenceManager.vpnPersistence(
withName: Constants.Persistence.profilesContainerName
)
providersPersistence = persistenceManager.providersPersistence(
@ -89,17 +89,17 @@ final class CoreContext {
Constants.Repos.api,
timeout: Constants.Services.connectivityTimeout
),
webServicesRepository: PassepartoutPersistence.webServicesRepository(providersPersistence)
webServicesRepository: providersPersistence.webServicesRepository()
)
providerManager = ProviderManager(
localProvidersRepository: PassepartoutPersistence.localProvidersRepository(providersPersistence),
localProvidersRepository: providersPersistence.localProvidersRepository(),
remoteProvidersStrategy: remoteProvidersStrategy
)
profileManager = ProfileManager(
store: store,
providerManager: providerManager,
profileRepository: PassepartoutPersistence.profileRepository(profilesPersistence),
profileRepository: vpnPersistence.profileRepository(),
keychain: KeychainSecretRepository(appGroup: Constants.App.appGroupId),
keychainEntry: Unlocalized.Keychain.passwordEntry,
keychainLabel: Unlocalized.Keychain.passwordLabel

View File

@ -39,12 +39,12 @@ final class PersistenceManager {
}
}
func profilesPersistence(withName containerName: String) -> CoreDataPersistentStore {
PassepartoutPersistence.profilesStore(withName: containerName, cloudKit: true, author: persistenceAuthor)
func vpnPersistence(withName containerName: String) -> VPNPersistence {
VPNPersistence(withName: containerName, cloudKit: true, author: persistenceAuthor)
}
func providersPersistence(withName containerName: String) -> CoreDataPersistentStore {
PassepartoutPersistence.providersStore(withName: containerName, cloudKit: false, author: persistenceAuthor)
func providersPersistence(withName containerName: String) -> ProvidersPersistence {
ProvidersPersistence(withName: containerName, cloudKit: false, author: persistenceAuthor)
}
}

View File

@ -35,9 +35,6 @@ public class Passepartout {
public var logger: Logger = DefaultLogger()
}
public enum PassepartoutPersistence {
}
public struct PassepartoutError: Error, Equatable {
private let string: String

View File

@ -1,5 +1,5 @@
//
// Persistence.swift
// ProvidersPersistence.swift
// Passepartout
//
// Created by Davide De Rosa on 4/7/22.
@ -29,30 +29,34 @@ import PassepartoutCore
import PassepartoutProviders
import PassepartoutServices
extension PassepartoutPersistence {
private static let providersDataModel: NSManagedObjectModel = {
public final class ProvidersPersistence {
private static let dataModel: NSManagedObjectModel = {
guard let model = NSManagedObjectModel.mergedModel(from: [.module]) else {
fatalError("Could not load PassepartoutProviders model")
}
return model
}()
public static func providersStore(withName containerName: String, cloudKit: Bool, author: String?) -> CoreDataPersistentStore {
.init(
private let store: CoreDataPersistentStore
public var containerURLs: [URL]? {
store.containerURLs
}
public init(withName containerName: String, cloudKit: Bool, author: String?) {
store = .init(
withName: containerName,
model: providersDataModel,
model: Self.dataModel,
cloudKit: cloudKit,
author: author
)
}
}
extension PassepartoutPersistence {
public static func webServicesRepository(_ store: CoreDataPersistentStore) -> WebServicesRepository {
public func webServicesRepository() -> WebServicesRepository {
CDWebServicesRepository(store.context)
}
public static func localProvidersRepository(_ store: CoreDataPersistentStore) -> LocalProvidersRepository {
public func localProvidersRepository() -> LocalProvidersRepository {
CDLocalProvidersRepository(store.context)
}
}

View File

@ -1,5 +1,5 @@
//
// Persistence.swift
// VPNPersistence.swift
// Passepartout
//
// Created by Davide De Rosa on 4/7/22.
@ -28,25 +28,30 @@ import Foundation
import PassepartoutCore
import PassepartoutVPN
extension PassepartoutPersistence {
private static let profilesDataModel: NSManagedObjectModel = {
public final class VPNPersistence {
private static let dataModel: NSManagedObjectModel = {
guard let model = NSManagedObjectModel.mergedModel(from: [.module]) else {
fatalError("Could not load PassepartoutProfiles model")
}
return model
}()
public static func profilesStore(withName containerName: String, cloudKit: Bool, author: String?) -> CoreDataPersistentStore {
.init(
private let store: CoreDataPersistentStore
public var containerURLs: [URL]? {
store.containerURLs
}
public init(withName containerName: String, cloudKit: Bool, author: String?) {
store = .init(
withName: containerName,
model: profilesDataModel,
model: Self.dataModel,
cloudKit: cloudKit,
author: author
)
}
}
extension PassepartoutPersistence {
public static func profileRepository(_ store: CoreDataPersistentStore) -> ProfileRepository {
public func profileRepository() -> ProfileRepository {
CDProfileRepository(store.context)
}
}

View File

@ -31,7 +31,7 @@ import PassepartoutProviders
import XCTest
final class ProvidersTests: XCTestCase {
private var persistence: CoreDataPersistentStore!
private var persistence: ProvidersPersistence!
private var manager: ProviderManager!
@ -39,16 +39,16 @@ final class ProvidersTests: XCTestCase {
override func setUp() {
let model = NSManagedObjectModel.mergedModel(from: [.module])!
persistence = CoreDataPersistentStore(withName: "ProvidersTests", model: model, cloudKit: false, author: nil)
persistence = ProvidersPersistence(withName: "ProvidersTests", cloudKit: false, author: nil)
let remoteStrategy = APIRemoteProvidersStrategy(
appBuild: 10000,
bundleServices: APIWebServices.bundledServices(withVersion: "v5"),
remoteServices: APIWebServices("v5", URL(string: "https://passepartoutvpn.app/api/")!, timeout: nil),
webServicesRepository: PassepartoutPersistence.webServicesRepository(persistence)
webServicesRepository: persistence.webServicesRepository()
)
manager = ProviderManager(
localProvidersRepository: PassepartoutPersistence.localProvidersRepository(persistence),
localProvidersRepository: persistence.localProvidersRepository(),
remoteProvidersStrategy: remoteStrategy
)
// persistence.truncate()