Tusker/Tusker/Caching/CachingDiskStorage.swift

72 lines
1.9 KiB
Swift

//
// CachingDiskStorage.swift
// Tusker
//
// Created by Shadowfacts on 1/17/21.
// Copyright © 2021 Shadowfacts. All rights reserved.
//
import Foundation
import Cache
/// This class wraps a `DiskStorage` and maintains an in-memory cache of whether objects
/// exist on disk to avoid unnecessary disk I/O when calling synchronous methods like
/// `existsObject(forKey:)`.
class CachingDiskStorage<T>: StorageAware {
private let storage: DiskStorage<T>
private var files = [String: FileState]()
init(config: DiskConfig, transformer: Transformer<T>) throws {
storage = try DiskStorage(config: config, transformer: transformer)
}
private func state(for key: String) -> FileState {
return files[key] ?? .unknown
}
func entry(forKey key: String) throws -> Entry<T> {
if state(for: key) == .doesNotExist {
throw StorageError.notFound
}
return try storage.entry(forKey: key)
}
func existsObject(forKey key: String) throws -> Bool {
switch state(for: key) {
case .unknown:
return try storage.existsObject(forKey: key)
case .exists:
return true
case .doesNotExist:
return false
}
}
func removeObject(forKey key: String) throws {
try storage.removeObject(forKey: key)
files[key] = .doesNotExist
}
func setObject(_ object: T, forKey key: String, expiry: Expiry? = nil) throws {
try storage.setObject(object, forKey: key, expiry: expiry)
files[key] = .exists
}
func removeAll() throws {
try storage.removeAll()
files.removeAll()
}
func removeExpiredObjects() throws {
try storage.removeExpiredObjects()
}
}
extension CachingDiskStorage {
private enum FileState {
case unknown, exists, doesNotExist
}
}