Files
Cable/Pods/PostHog/PostHog/PostHogFileBackedQueue.swift
Stefan Lange-Hegermann ced06f9eb6 ads tracking
2025-11-05 11:13:54 +01:00

115 lines
2.9 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// PostHogFileBackedQueue.swift
// PostHog
//
// Created by Manoel Aranda Neto on 13.10.23.
//
import Foundation
class PostHogFileBackedQueue {
let queue: URL
@ReadWriteLock
private var items = [String]()
var depth: Int {
items.count
}
init(queue: URL, oldQueue: URL? = nil) {
self.queue = queue
setup(oldQueue: oldQueue)
}
private func setup(oldQueue: URL?) {
do {
try FileManager.default.createDirectory(atPath: queue.path, withIntermediateDirectories: true)
} catch {
hedgeLog("Error trying to create caching folder \(error)")
}
if oldQueue != nil {
migrateOldQueue(queue: queue, oldQueue: oldQueue!)
}
do {
items = try FileManager.default.contentsOfDirectory(atPath: queue.path)
items.sort { Double($0)! < Double($1)! }
} catch {
hedgeLog("Failed to load files for queue \(error)")
// failed to read directory bad permissions, perhaps?
}
}
func peek(_ count: Int) -> [Data] {
loadFiles(count)
}
func delete(index: Int) {
if items.isEmpty { return }
let removed = items.remove(at: index)
deleteSafely(queue.appendingPathComponent(removed))
}
func pop(_ count: Int) {
deleteFiles(count)
}
func add(_ contents: Data) {
do {
let filename = "\(Date().timeIntervalSince1970)"
try contents.write(to: queue.appendingPathComponent(filename))
items.append(filename)
} catch {
hedgeLog("Could not write file \(error)")
}
}
/// Internal, used for testing
func clear() {
deleteSafely(queue)
setup(oldQueue: nil)
}
private func loadFiles(_ count: Int) -> [Data] {
var results = [Data]()
for item in items {
let itemURL = queue.appendingPathComponent(item)
do {
if !FileManager.default.fileExists(atPath: itemURL.path) {
hedgeLog("File \(itemURL) does not exist")
continue
}
let contents = try Data(contentsOf: itemURL)
results.append(contents)
} catch {
hedgeLog("File \(itemURL) is corrupted \(error)")
deleteSafely(itemURL)
}
if results.count == count {
return results
}
}
return results
}
private func deleteFiles(_ count: Int) {
for _ in 0 ..< count {
if let removed: String = _items.mutate({ items in
if items.isEmpty {
return nil
}
return items.remove(at: 0) // We always remove from the top of the queue
}) {
deleteSafely(queue.appendingPathComponent(removed))
}
}
}
}