Memory + disk cache with deduplication: find the bugs
Task
Code review. The cache must: serve from memory, then disk, then download; never download the same URL twice concurrently. Find the bugs.
actor ImageCache {
private var memory: [String: UIImage] = [:]
private var inFlight: [String: Task<UIImage, Error>] = [:]
private let diskURL = FileManager.default.temporaryDirectory
func image(for url: String) async throws -> UIImage {
if let img = memory[url] { return img }
let fileURL = diskURL.appendingPathComponent(url.hash.description)
if let data = try? Data(contentsOf: fileURL), let img = UIImage(data: data) {
memory[url] = img
return img
}
if let existing = inFlight[url] { return try await existing.value }
let task = Task<UIImage, Error> {
let (data, _) = try await URLSession.shared.data(from: URL(string: url)!)
let img = UIImage(data: data)!
memory[url] = img
try? data.write(to: fileURL)
return img
}
inFlight[url] = task
defer { inFlight[url] = nil }
return try await task.value
}
}
The rest of this answer, with code and interview follow-ups, is in the DevPrep app.
Read the full answer in DevPrep