Skip to content

Commit 58f6b23

Browse files
authored
Merge pull request #137 from unsignedapps/remove-direct-source-setter
Make updating FlagPole's source list thread-safe.
2 parents 7ef7b5f + 69c9c3c commit 58f6b23

File tree

3 files changed

+40
-18
lines changed

3 files changed

+40
-18
lines changed

Sources/Vexil/Observability/Observing.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
import AsyncAlgorithms
1515

16-
public enum FlagChange: Sendable {
16+
public enum FlagChange: Sendable, Equatable {
1717

1818
/// All flags _may_ have changed. This change type often occurs when flags could be changed
1919
/// outside the bounds of the app using Vexil and we are unable to tell if any flags have changed,
@@ -109,3 +109,12 @@ public struct EmptyFlagChangeStream: AsyncSequence, Sendable {
109109
}
110110

111111
}
112+
113+
extension FlagChange: CustomDebugStringConvertible {
114+
public var debugDescription: String {
115+
switch self {
116+
case .all: "FlagChange.all"
117+
case let .some(keys): "FlagChange.some(\(keys.map(\.key).joined(separator: ", ")))"
118+
}
119+
}
120+
}

Sources/Vexil/Pole.swift

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,30 @@ public final class FlagPole<RootGroup>: Sendable where RootGroup: FlagContainer
5959
// MARK: - Sources
6060

6161
/// An Array of `FlagValueSource`s that are used during flag value lookup.
62-
///
63-
/// This array is mutable so you can manipulate it directly whenever your
64-
/// need to change the hierarchy of your flag sources.
65-
///
6662
/// The order of this Array is the order used when looking up flag values.
6763
///
64+
/// To update the list of sources use ``
65+
///
6866
public var _sources: [any FlagValueSource] {
69-
get {
70-
manager.withLockUnchecked {
71-
$0.sources
72-
}
67+
manager.withLockUnchecked {
68+
$0.sources
7369
}
74-
set {
75-
manager.withLockUnchecked { manager in
76-
let oldValue = manager.sources
77-
manager.sources = newValue
78-
subscribeChannel(oldSources: oldValue, newSources: newValue, on: &manager)
70+
}
71+
72+
/// Updates the list of `FlagValueSource`s using the supplied closure.
73+
///
74+
/// - Parameters:
75+
/// - closure: A closure that is passed a mutable copy of the sources array.
76+
///
77+
public func updateSources(_ closure: (inout [any FlagValueSource]) throws -> Void) rethrows {
78+
try manager.withLockUnchecked { manager in
79+
let oldValue = manager.sources
80+
var copy = manager.sources
81+
try closure(&copy)
82+
manager.sources = copy
83+
84+
if oldValue.map(\.flagValueSourceID) != copy.map(\.flagValueSourceID) {
85+
subscribeChannel(oldSources: oldValue, newSources: copy, on: &manager)
7986
}
8087
}
8188
}
@@ -312,7 +319,9 @@ public final class FlagPole<RootGroup>: Sendable where RootGroup: FlagContainer
312319
/// - at: The index at which to insert the `Snapshot`.
313320
///
314321
public func insert(snapshot: Snapshot<RootGroup>, at index: Array<any FlagValueSource>.Index) {
315-
_sources.insert(snapshot, at: index)
322+
updateSources {
323+
$0.insert(snapshot, at: index)
324+
}
316325
}
317326

318327
/// Appends a `Snapshot` to the end of the `FlagPole`s source hierarchy.
@@ -323,7 +332,9 @@ public final class FlagPole<RootGroup>: Sendable where RootGroup: FlagContainer
323332
/// - snapshot: The `Snapshot` to be added to the source hierarchy.
324333
///
325334
public func append(snapshot: Snapshot<RootGroup>) {
326-
_sources.append(snapshot)
335+
updateSources {
336+
$0.append(snapshot)
337+
}
327338
}
328339

329340
/// Removes a `Snapshot` from the `FlagPole`s source hierarchy.
@@ -334,7 +345,9 @@ public final class FlagPole<RootGroup>: Sendable where RootGroup: FlagContainer
334345
/// - snapshot: The `Snapshot` to be removed from the source hierarchy.
335346
///
336347
public func remove(snapshot: Snapshot<RootGroup>) {
337-
_sources.removeAll(where: { ($0 as? Snapshot<RootGroup>)?.id == snapshot.id })
348+
updateSources {
349+
$0.removeAll(where: { ($0 as? Snapshot<RootGroup>)?.id == snapshot.id })
350+
}
338351
}
339352

340353

Sources/Vexil/Sources/FlagValueDictionary.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public final class FlagValueDictionary: Identifiable, ExpressibleByDictionaryLit
7878
// MARK: - Dictionary Access
7979

8080
/// Returns a copy of the current values in this source
81-
var allValues: DictionaryType {
81+
public var allValues: DictionaryType {
8282
storage.withLock { $0 }
8383
}
8484

0 commit comments

Comments
 (0)