Skip to content

Commit

Permalink
fix: Make Confidence.cache thread-safe
Browse files Browse the repository at this point in the history
  • Loading branch information
fabriziodemaria committed Nov 5, 2024
1 parent 448fb93 commit bf4e674
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 3 deletions.
18 changes: 15 additions & 3 deletions Sources/Confidence/Confidence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,17 @@ public class Confidence: ConfidenceEventSender {
}
.store(in: &cancellables)
}

/**
Activating the cache means that the flag data on disk is loaded into memory, so consumers can access flag values.
Errors can be thrown if something goes wrong access data on disk.
*/
public func activate() throws {
let savedFlags = try storage.load(defaultValue: FlagResolution.EMPTY)
self.cache = savedFlags
debugLogger?.logFlags(action: "Activate", flag: "")
try withLockThrowing { confidence in
let savedFlags = try confidence.storage.load(defaultValue: FlagResolution.EMPTY)
confidence.cache = savedFlags
confidence.debugLogger?.logFlags(action: "Activate", flag: "")
}
}

/**
Expand Down Expand Up @@ -285,6 +288,15 @@ public class Confidence: ConfidenceEventSender {
callback(self)
}
}

private func withLockThrowing(callback: @escaping (Confidence) throws -> Void) throws {
try confidenceQueue.sync { [weak self] in
guard let self = self else {
return
}
try callback(self)
}
}
}

extension Confidence {
Expand Down
22 changes: 22 additions & 0 deletions Tests/ConfidenceTests/ConfidenceTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,28 @@ class ConfidenceTest: XCTestCase {
XCTAssertEqual(error as? ConfidenceError, ConfidenceError.invalidContextInMessage)
}
}

func testConcurrentActivate() async {
for _ in 1...100 {
Task {
await concurrentActivate()
}
}
}

private func concurrentActivate() async {
let confidence = Confidence.Builder(clientSecret: "test")
.build()

await withTaskGroup(of: Void.self) { group in
for _ in 0..<10000 {
group.addTask {
// Perform the thread-unsafe increment
try! confidence.activate()

Check failure on line 637 in Tests/ConfidenceTests/ConfidenceTest.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Force Try Violation: Force tries should be avoided (force_try)
}
}
}
}
}

final class DispatchQueueFake: DispatchQueueType {
Expand Down

0 comments on commit bf4e674

Please sign in to comment.