diff --git a/Source/Shared/Storage/DiskStorage.swift b/Source/Shared/Storage/DiskStorage.swift index 2dcb969..f41238c 100644 --- a/Source/Shared/Storage/DiskStorage.swift +++ b/Source/Shared/Storage/DiskStorage.swift @@ -143,6 +143,64 @@ extension DiskStorage: StorageAware { try removeResourceObjects(resourceObjects, totalSize: totalSize) } + public func removeExpiredObjects(expiryPeriod: TimeInterval? = nil) throws { + let storageURL = URL(fileURLWithPath: path) + let resourceKeys: [URLResourceKey] = [ + .isDirectoryKey, + .contentModificationDateKey, + .contentAccessDateKey, + .totalFileAllocatedSizeKey + ] + + var resourceObjects = [ResourceObject]() + var filesToDelete = [URL]() + var totalSize: UInt = 0 + + let fileEnumerator = fileManager.enumerator( + at: storageURL, + includingPropertiesForKeys: resourceKeys, + options: .skipsHiddenFiles, + errorHandler: nil + ) + + guard let urlArray = fileEnumerator?.allObjects as? [URL] else { + throw Error.fileEnumeratorFailed + } + + for url in urlArray { + let resourceValues = try url.resourceValues(forKeys: Set(resourceKeys)) + guard resourceValues.isDirectory != true else { + continue + } + + if let expiryPeriod = expiryPeriod, + let accessDate = resourceValues.contentAccessDate, + accessDate.addingTimeInterval(expiryPeriod) < Date() { + filesToDelete.append(url) + continue + } else if expiryPeriod == nil, + let expiryDate = resourceValues.contentModificationDate, + expiryDate.inThePast { + filesToDelete.append(url) + continue + } + + if let fileSize = resourceValues.totalFileAllocatedSize { + totalSize += UInt(fileSize) + resourceObjects.append((url: url, resourceValues: resourceValues)) + } + } + + // Remove expired + for url in filesToDelete { + try fileManager.removeItem(at: url) + onRemove?(url.path) + } + + // Enforce size limits + try removeResourceObjects(resourceObjects, totalSize: totalSize) +} + public func removeInMemoryObject(forKey key: Key) throws { } } diff --git a/Source/Shared/Storage/HybridStorage.swift b/Source/Shared/Storage/HybridStorage.swift index 9844803..7ad4b24 100644 --- a/Source/Shared/Storage/HybridStorage.swift +++ b/Source/Shared/Storage/HybridStorage.swift @@ -88,6 +88,13 @@ extension HybridStorage: StorageAware { notifyStorageObservers(about: .removeExpired) } + + public func removeExpiredObjects(expiryPeriod: TimeInterval? = nil) throws { + memoryStorage.removeExpiredObjects() + try diskStorage.removeExpiredObjects(expiryPeriod: expiryPeriod) + + notifyStorageObservers(about: .removeExpired) + } } public extension HybridStorage { diff --git a/Source/Shared/Storage/Storage.swift b/Source/Shared/Storage/Storage.swift index 4f94c86..233536f 100644 --- a/Source/Shared/Storage/Storage.swift +++ b/Source/Shared/Storage/Storage.swift @@ -74,6 +74,10 @@ extension Storage: StorageAware { public func removeExpiredObjects() throws { try self.syncStorage.removeExpiredObjects() } + + public func removeExpiredObjects(expiryPeriod: TimeInterval? = nil) throws { + try self.syncStorage.removeExpiredObjects(expiryPeriod: expiryPeriod) + } } public extension Storage { diff --git a/Source/Shared/Storage/SyncStorage.swift b/Source/Shared/Storage/SyncStorage.swift index b7bab94..ac58c17 100644 --- a/Source/Shared/Storage/SyncStorage.swift +++ b/Source/Shared/Storage/SyncStorage.swift @@ -62,6 +62,12 @@ extension SyncStorage: StorageAware { } } + public func removeExpiredObjects(expiryPeriod: TimeInterval? = nil) throws { + try serialQueue.sync { + try innerStorage.removeExpiredObjects(expiryPeriod: expiryPeriod) + } + } + public func removeInMemoryObject(forKey key: Key) throws { try serialQueue.sync { try self.innerStorage.removeInMemoryObject(forKey: key)