Skip to content

Commit 8cbdedb

Browse files
feat: [WIP] Add setProviderAndWait
Signed-off-by: Fabrizio Demaria <[email protected]>
1 parent 2ba03fe commit 8cbdedb

File tree

3 files changed

+116
-0
lines changed

3 files changed

+116
-0
lines changed

Sources/OpenFeature/OpenFeatureAPI.swift

+19
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,22 @@ public class OpenFeatureAPI {
8585
.eraseToAnyPublisher()
8686
}
8787
}
88+
89+
extension OpenFeatureAPI {
90+
public func setProviderAndWait(provider: FeatureProvider) async {
91+
await setProviderAndWait(provider: provider, initialContext: nil)
92+
}
93+
94+
public func setProviderAndWait(provider: FeatureProvider, initialContext: EvaluationContext?) async {
95+
var holder: [AnyCancellable] = []
96+
await withCheckedContinuation { continuation in
97+
let stateObserver = provider.observe().sink {
98+
if $0 == .ready {
99+
continuation.resume()
100+
}
101+
}
102+
stateObserver.store(in: &holder)
103+
setProvider(provider: provider, initialContext: initialContext)
104+
}
105+
}
106+
}

Tests/OpenFeatureTests/DeveloperExperienceTests.swift

+23
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,29 @@ final class DeveloperExperienceTests: XCTestCase {
4949
XCTAssertNotNil(eventState)
5050
}
5151

52+
func testSetProviderAndWait() async {
53+
let readyExpectation = XCTestExpectation(description: "Ready")
54+
let errorExpectation = XCTestExpectation(description: "Error")
55+
let staleExpectation = XCTestExpectation(description: "Stale")
56+
let eventState = OpenFeatureAPI.shared.observe().sink { event in
57+
switch event {
58+
case ProviderEvent.ready:
59+
readyExpectation.fulfill()
60+
case ProviderEvent.error:
61+
errorExpectation.fulfill()
62+
case ProviderEvent.stale:
63+
staleExpectation.fulfill()
64+
default:
65+
XCTFail("Unexpected event")
66+
}
67+
}
68+
let provider = SlowProvider()
69+
await OpenFeatureAPI.shared.setProviderAndWait(provider: provider)
70+
wait(for: [readyExpectation], timeout: 0)
71+
72+
XCTAssertNotNil(eventState)
73+
}
74+
5275
func testClientHooks() {
5376
OpenFeatureAPI.shared.setProvider(provider: NoOpProvider())
5477
let client = OpenFeatureAPI.shared.getClient()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import Foundation
2+
import OpenFeature
3+
import Combine
4+
5+
class SlowProvider: FeatureProvider {
6+
public static let name = "Slow"
7+
private let eventHandler = EventHandler(.stale)
8+
private var holdit: AnyCancellable?
9+
10+
func onContextSet(oldContext: OpenFeature.EvaluationContext?, newContext: OpenFeature.EvaluationContext) {
11+
eventHandler.send(.ready)
12+
}
13+
14+
func initialize(initialContext: OpenFeature.EvaluationContext?) {
15+
Task {
16+
// TODO Remove the sleep in the tests
17+
print(">> Sleeping")
18+
try await Task.sleep(nanoseconds: 1_000_000_000)
19+
print(">> Emitting Ready")
20+
eventHandler.send(.ready)
21+
}
22+
}
23+
24+
var hooks: [any OpenFeature.Hook] = []
25+
var metadata: OpenFeature.ProviderMetadata = DoMetadata()
26+
27+
func getBooleanEvaluation(key: String, defaultValue: Bool, context: EvaluationContext?) throws
28+
-> ProviderEvaluation<
29+
Bool
30+
>
31+
{
32+
return ProviderEvaluation(value: !defaultValue)
33+
}
34+
35+
func getStringEvaluation(key: String, defaultValue: String, context: EvaluationContext?) throws
36+
-> ProviderEvaluation<
37+
String
38+
>
39+
{
40+
return ProviderEvaluation(value: String(defaultValue.reversed()))
41+
}
42+
43+
func getIntegerEvaluation(key: String, defaultValue: Int64, context: EvaluationContext?) throws
44+
-> ProviderEvaluation<
45+
Int64
46+
>
47+
{
48+
return ProviderEvaluation(value: defaultValue * 100)
49+
}
50+
51+
func getDoubleEvaluation(key: String, defaultValue: Double, context: EvaluationContext?) throws
52+
-> ProviderEvaluation<
53+
Double
54+
>
55+
{
56+
return ProviderEvaluation(value: defaultValue * 100)
57+
}
58+
59+
func getObjectEvaluation(key: String, defaultValue: Value, context: EvaluationContext?) throws
60+
-> ProviderEvaluation<
61+
Value
62+
>
63+
{
64+
return ProviderEvaluation(value: .null)
65+
}
66+
67+
func observe() -> AnyPublisher<OpenFeature.ProviderEvent, Never> {
68+
eventHandler.observe()
69+
}
70+
71+
public struct DoMetadata: ProviderMetadata {
72+
public var name: String? = DoSomethingProvider.name
73+
}
74+
}

0 commit comments

Comments
 (0)