225 lines
8.0 KiB
Swift
225 lines
8.0 KiB
Swift
//
|
|
// ModelDownloadManagerProtocol.swift
|
|
// MNNLLMiOS
|
|
//
|
|
// Created by 游薪渝(揽清) on 2025/8/27.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
/// Protocol defining the interface for model download managers
|
|
///
|
|
/// This protocol enables dependency injection and provides a common contract for different download implementations.
|
|
/// It supports concurrent downloads, progress tracking, and cancellation functionality.
|
|
///
|
|
/// Key Features:
|
|
/// - Asynchronous download operations with progress callbacks
|
|
/// - Cancellation support with resume capability
|
|
/// - Actor-based thread safety
|
|
/// - Flexible destination path configuration
|
|
///
|
|
/// Usage:
|
|
/// ```swift
|
|
/// let manager: ModelDownloadManagerProtocol = ModelDownloadManager(...)
|
|
/// try await manager.downloadModel(
|
|
/// to: "models",
|
|
/// modelId: "example-model",
|
|
/// modelName: "ExampleModel"
|
|
/// ) { progress in
|
|
/// print("Progress: \(progress * 100)%")
|
|
/// }
|
|
/// ```
|
|
@available(iOS 13.4, macOS 10.15, *)
|
|
public protocol ModelDownloadManagerProtocol: Actor, Sendable {
|
|
/// Downloads a model from the repository with progress tracking
|
|
///
|
|
/// This method initiates an asynchronous download operation for the specified model.
|
|
/// It supports resume functionality and provides real-time progress updates.
|
|
///
|
|
/// - Parameters:
|
|
/// - destinationFolder: Base folder where the model will be downloaded
|
|
/// - modelId: Unique identifier for the model in the repository
|
|
/// - modelName: Display name of the model (used for folder creation)
|
|
/// - progress: Optional closure called with download progress (0.0 to 1.0)
|
|
/// - Throws: ModelScopeError for network, file system, or validation failures
|
|
func downloadModel(
|
|
to destinationFolder: String,
|
|
modelId: String,
|
|
modelName: String,
|
|
progress: ((Double) -> Void)?
|
|
) async throws
|
|
|
|
/// Cancels the current download operation
|
|
///
|
|
/// This method gracefully stops the download process while preserving temporary files
|
|
/// to support resume functionality in future download attempts.
|
|
func cancelDownload() async
|
|
}
|
|
|
|
/// Type-erased wrapper for ModelDownloadManagerProtocol
|
|
///
|
|
/// This class provides a concrete type that can be stored as a property while maintaining protocol flexibility.
|
|
/// It wraps any ModelDownloadManagerProtocol implementation and forwards method calls to the underlying manager.
|
|
///
|
|
/// Key Benefits:
|
|
/// - Enables storing protocol instances as properties
|
|
/// - Maintains type safety while providing flexibility
|
|
/// - Supports dependency injection patterns
|
|
/// - Preserves all protocol functionality
|
|
///
|
|
/// Usage:
|
|
/// ```swift
|
|
/// let concreteManager = ModelDownloadManager(...)
|
|
/// let anyManager = AnyModelDownloadManager(concreteManager)
|
|
/// // Can now store anyManager as a property
|
|
/// ```
|
|
@available(iOS 13.4, macOS 10.15, *)
|
|
public actor AnyModelDownloadManager: ModelDownloadManagerProtocol {
|
|
private let _downloadModel: (String, String, String, ((Double) -> Void)?) async throws -> Void
|
|
private let _cancelDownload: () async -> Void
|
|
|
|
/// Creates a type-erased wrapper around any ModelDownloadManagerProtocol implementation
|
|
///
|
|
/// - Parameter manager: The concrete download manager to wrap
|
|
public init<T: ModelDownloadManagerProtocol>(_ manager: T) {
|
|
_downloadModel = { destinationFolder, modelId, modelName, progress in
|
|
try await manager.downloadModel(
|
|
to: destinationFolder,
|
|
modelId: modelId,
|
|
modelName: modelName,
|
|
progress: progress
|
|
)
|
|
}
|
|
_cancelDownload = {
|
|
await manager.cancelDownload()
|
|
}
|
|
}
|
|
|
|
public func downloadModel(
|
|
to destinationFolder: String,
|
|
modelId: String,
|
|
modelName: String,
|
|
progress: ((Double) -> Void)? = nil
|
|
) async throws {
|
|
try await _downloadModel(destinationFolder, modelId, modelName, progress)
|
|
}
|
|
|
|
public func cancelDownload() async {
|
|
await _cancelDownload()
|
|
}
|
|
}
|
|
|
|
/// Factory protocol for creating download managers
|
|
///
|
|
/// This protocol enables different creation strategies while maintaining type safety.
|
|
/// It provides a standardized way to create download managers with various configurations.
|
|
///
|
|
/// Key Features:
|
|
/// - Supports multiple download manager implementations
|
|
/// - Enables dependency injection and testing
|
|
/// - Provides consistent creation interface
|
|
/// - Supports different model sources
|
|
///
|
|
/// Usage:
|
|
/// ```swift
|
|
/// let factory: ModelDownloadManagerFactory = DefaultModelDownloadManagerFactory()
|
|
/// let manager = factory.createDownloadManager(
|
|
/// repoPath: "owner/model-name",
|
|
/// source: .modelScope
|
|
/// )
|
|
/// ```
|
|
@available(iOS 13.4, macOS 10.15, *)
|
|
public protocol ModelDownloadManagerFactory {
|
|
/// Creates a download manager for the specified repository and source
|
|
///
|
|
/// - Parameters:
|
|
/// - repoPath: Repository path in format "owner/model-name"
|
|
/// - source: The model source (ModelScope or Modeler)
|
|
/// - Returns: A download manager conforming to ModelDownloadManagerProtocol
|
|
func createDownloadManager(
|
|
repoPath: String,
|
|
source: ModelSource
|
|
) -> any ModelDownloadManagerProtocol
|
|
}
|
|
|
|
/// Default factory implementation that creates OptimizedModelScopeDownloadManager instances
|
|
///
|
|
/// This factory provides the standard implementation for creating download managers with
|
|
/// advanced features including dynamic concurrency control, optimized performance settings,
|
|
/// and comprehensive configuration options.
|
|
@available(iOS 13.4, macOS 10.15, *)
|
|
public struct DefaultModelDownloadManagerFactory: ModelDownloadManagerFactory {
|
|
private let config: DownloadConfig
|
|
private let sessionConfig: URLSessionConfiguration
|
|
private let enableLogging: Bool
|
|
private let concurrencyConfig: DynamicConcurrencyConfig
|
|
|
|
/// Creates a factory with specified configuration
|
|
///
|
|
/// - Parameters:
|
|
/// - config: Download configuration settings
|
|
/// - sessionConfig: URLSession configuration
|
|
/// - enableLogging: Whether to enable debug logging
|
|
/// - concurrencyConfig: Dynamic concurrency configuration
|
|
public init(
|
|
config: DownloadConfig = .default,
|
|
sessionConfig: URLSessionConfiguration = .default,
|
|
enableLogging: Bool = true,
|
|
concurrencyConfig: DynamicConcurrencyConfig = .default
|
|
) {
|
|
self.config = config
|
|
self.sessionConfig = sessionConfig
|
|
self.enableLogging = enableLogging
|
|
self.concurrencyConfig = concurrencyConfig
|
|
}
|
|
|
|
public func createDownloadManager(
|
|
repoPath: String,
|
|
source: ModelSource
|
|
) -> any ModelDownloadManagerProtocol {
|
|
return ModelDownloadManager(
|
|
repoPath: repoPath,
|
|
config: config,
|
|
sessionConfig: sessionConfig,
|
|
enableLogging: enableLogging,
|
|
source: source,
|
|
concurrencyConfig: concurrencyConfig
|
|
)
|
|
}
|
|
}
|
|
|
|
/// Legacy factory implementation that creates ModelScopeDownloadManager instances
|
|
///
|
|
/// This factory is provided for backward compatibility and testing purposes.
|
|
/// It creates the original ModelScopeDownloadManager without advanced optimizations.
|
|
@available(iOS 13.4, macOS 10.15, *)
|
|
public struct LegacyModelDownloadManagerFactory: ModelDownloadManagerFactory {
|
|
private let sessionConfig: URLSessionConfiguration
|
|
private let enableLogging: Bool
|
|
|
|
/// Creates a legacy factory with specified configuration
|
|
///
|
|
/// - Parameters:
|
|
/// - sessionConfig: URLSession configuration
|
|
/// - enableLogging: Whether to enable debug logging
|
|
public init(
|
|
sessionConfig: URLSessionConfiguration = .default,
|
|
enableLogging: Bool = true
|
|
) {
|
|
self.sessionConfig = sessionConfig
|
|
self.enableLogging = enableLogging
|
|
}
|
|
|
|
public func createDownloadManager(
|
|
repoPath: String,
|
|
source: ModelSource
|
|
) -> any ModelDownloadManagerProtocol {
|
|
return ModelScopeDownloadManager(
|
|
repoPath: repoPath,
|
|
config: sessionConfig,
|
|
enableLogging: enableLogging,
|
|
source: source
|
|
)
|
|
}
|
|
}
|