KVHeavyTasksManager

public class KVHeavyTasksManager<
    K,
    Element,
    CustomEvent,
    DataProvider: KVHeavyTaskBaseDataProvider<K, Element, CustomEvent>
> where DataProvider: KVHeavyTaskDataProviderInterface
extension KVHeavyTasksManager: @unchecked Sendable

Comprehensive manager for resource-intensive computational tasks and operations.

KVHeavyTasksManager serves as the central coordination hub for executing, caching, and managing heavy computational tasks. It provides sophisticated concurrency control, intelligent caching, flexible priority strategies, and comprehensive lifecycle management for resource-intensive operations.

Architecture Overview

The manager operates through several interconnected systems:

  • Task Queue Management: Dual-queue system (waiting/running) with configurable capacity and eviction
  • Priority Coordination: FIFO/LIFO strategies with optional task interruption support
  • Cache Integration: Multi-level caching with hit/miss/null/invalid state handling
  • Provider Lifecycle: DataProvider creation, reuse, and cleanup with memory optimization
  • Event Broadcasting: Real-time progress updates and custom event distribution
  • Thread Safety: Complete concurrency protection using semaphore-based synchronization

Key Features

  • Zero-configuration operation: Sensible defaults for immediate use
  • Highly configurable: Every aspect of behavior can be customized
  • Memory efficient: Automatic cleanup and configurable resource limits
  • Performance optimized: Minimal overhead with intelligent caching and provider reuse
  • Robust error handling: Comprehensive error propagation and graceful degradation
  • Production ready: Thread-safe, tested, and optimized for high-load scenarios

Generic Type Parameters

  • K: Key type for task identification (must be Hashable) - used for deduplication and caching
  • Element: Result type returned by completed tasks - cached and delivered to callbacks
  • CustomEvent: Event type for progress updates - broadcast to all registered observers
  • DataProvider: Concrete provider class that executes the actual heavy operations

Usage Example

// Define your custom data provider
class ImageProcessingProvider: KVHeavyTaskBaseDataProvider<String, UIImage, ProcessingProgress>,
                              KVHeavyTaskDataProviderInterface {
    func start() {
        // Implement heavy image processing
        performImageProcessing { progress in
            customEventPublisher(progress)
        } completion: { result in
            resultPublisher(result)
        }
    }

    func stop() -> KVHeavyTaskDataProviderStopAction {
        return .reuse // Preserve processing state for resumption
    }
}

// Configure and create manager
let config = KVHeavyTasksManager<String, UIImage, ProcessingProgress, ImageProcessingProvider>.Config(
    maxNumberOfRunningTasks: 2,
    priorityStrategy: .LIFO(.stop),
    cacheConfig: .init(memoryUsageLimitation: .init(capacity: 100, memory: 50_000_000))
)
let manager = KVHeavyTasksManager<String, UIImage, ProcessingProgress, ImageProcessingProvider>(config: config)

// Execute tasks with progress monitoring
manager.fetch(key: "process_photo_123",
              customEventObserver: { progress in
                  print("Processing progress: \(progress.percentage)%")
              },
              result: { result in
                  switch result {
                  case .success(let image):
                      // Handle processed image
                  case .failure(let error):
                      // Handle processing error
                  }
              })

Thread Safety

All public methods are fully thread-safe and can be called from any queue or thread. The manager uses internal synchronization to coordinate access to shared state while minimizing performance impact through careful lock scope management.

Performance Considerations

  • Queue sizing: Balance memory usage vs task eviction risk
  • Concurrency limits: Optimize for your specific task characteristics and system resources
  • Cache configuration: Tune for your result size and access patterns
  • Priority strategy: Choose based on responsiveness vs predictability requirements
  • Provider lifecycle: Balance setup cost vs memory usage with reuse/dealloc decisions
  • Initializes a new KVHeavyTasksManager with the specified configuration.

    This initializer sets up all internal systems including queues, cache, and synchronization primitives. The configuration is immutable after initialization to ensure consistent behavior.

    Note

    Initialization is lightweight and safe to call from any thread

    Declaration

    Swift

    public init(config: Config)

    Parameters

    config

    Complete configuration defining all manager behavior

  • Immutable configuration that defines all manager behavior.

    This configuration is set at initialization and cannot be changed during the manager’s lifetime, ensuring consistent and predictable behavior for all operations.

    Declaration

    Swift

    public let config: Config
  • Configuration structure that controls all aspects of task manager behavior.

    This configuration is immutable after manager initialization, ensuring consistent behavior throughout the manager’s lifecycle. Choose settings based on your specific use case requirements for performance, memory usage, and task prioritization needs.

    See more

    Declaration

    Swift

    struct Config
  • Error types emitted by KVHeavyTasksManager operations.

    Note

    These errors cover configuration and queue-capacity conditions that prevent a task from executing under the current constraints.
    See more

    Declaration

    Swift

    enum Errors : Error
  • Fetch a single key using a heavy DataProvider, optionally observing custom events.

    This method registers observers and callbacks, consults the cache, and schedules execution according to the configured priority strategy and concurrency limits.

    Warning

    If maxNumberOfRunningTasks is <= 0, the result will receive .failure(Errors.invalidConcurrencyConfiguration) and no work will be performed.

    Declaration

    Swift

    func fetch(
        key: K,
        customEventObserver: DataProvider.CustomEventPublisher? = nil,
        result resultCallback: DataProvider.ResultPublisher? = nil
    )

    Parameters

    key

    Unique key to fetch.

    customEventObserver

    Optional observer for real-time progress/status updates.

    result

    Optional callback invoked once with the final result for key.

  • Fetch a single key asynchronously using a heavy DataProvider.

    Registers the optional event observer, then returns a Result once the task completes.

    Note

    If maxNumberOfRunningTasks is <= 0, this method returns .failure(Errors.invalidConcurrencyConfiguration) immediately.

    Declaration

    Swift

    func asyncFetch(
        key: K,
        customEventObserver: DataProvider.CustomEventPublisher? = nil
    ) async -> Result<Element?, Error>

    Parameters

    key

    Unique key to fetch.

    customEventObserver

    Optional observer for real-time progress/status updates.

    Return Value

    A Result containing the fetched element or an error.