Skip to content

Commit

Permalink
feat: [WIP] Add setProviderAndWait
Browse files Browse the repository at this point in the history
Signed-off-by: Fabrizio Demaria <[email protected]>
  • Loading branch information
fabriziodemaria committed Jan 22, 2024
1 parent 9ca2cc3 commit 12ad983
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 0 deletions.
17 changes: 17 additions & 0 deletions Sources/OpenFeature/OpenFeatureAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,27 @@ public class OpenFeatureAPI: GlobalEventPublisher {
public init() {
}

public func setProviderAndWait(provider: FeatureProvider) async {
await setProviderAndWait(provider: provider, initialContext: nil)
}

public func setProvider(provider: FeatureProvider) {
self.setProvider(provider: provider, initialContext: nil)
}

public func setProviderAndWait(provider: FeatureProvider, initialContext: EvaluationContext?) async {
var holder: [AnyCancellable] = []
await withCheckedContinuation { continuation in
let stateObserver = provider.observe().sink {
if $0 == .ready {
continuation.resume()
}
}
stateObserver.store(in: &holder)
setProvider(provider: provider, initialContext: initialContext)
}
}

public func setProvider(provider: FeatureProvider, initialContext: EvaluationContext?) {
self._provider = provider
self.providerObserver = provider.observe().sink { event in
Expand Down
23 changes: 23 additions & 0 deletions Tests/OpenFeatureTests/DeveloperExperienceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,29 @@ final class DeveloperExperienceTests: XCTestCase {
XCTAssertNotNil(eventState)
}

func testSetProviderAndWait() async {
let readyExpectation = XCTestExpectation(description: "Ready")
let errorExpectation = XCTestExpectation(description: "Error")
let staleExpectation = XCTestExpectation(description: "Stale")
let eventState = OpenFeatureAPI.shared.observe().sink { event in
switch event {
case ProviderEvent.ready:
readyExpectation.fulfill()
case ProviderEvent.error:
errorExpectation.fulfill()
case ProviderEvent.stale:
staleExpectation.fulfill()
default:
XCTFail("Unexpected event")
}
}
let provider = SlowProvider()
await OpenFeatureAPI.shared.setProviderAndWait(provider: provider)
wait(for: [readyExpectation], timeout: 0)

XCTAssertNotNil(eventState)
}

func testClientHooks() {
OpenFeatureAPI.shared.setProvider(provider: NoOpProvider())
let client = OpenFeatureAPI.shared.getClient()
Expand Down
74 changes: 74 additions & 0 deletions Tests/OpenFeatureTests/Helpers/SlowProvider.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import Foundation
import OpenFeature
import Combine

class SlowProvider: FeatureProvider {
public static let name = "Slow"
private let eventHandler = EventHandler(.stale)
private var holdit: AnyCancellable?

func onContextSet(oldContext: OpenFeature.EvaluationContext?, newContext: OpenFeature.EvaluationContext) {
eventHandler.send(.ready)
}

func initialize(initialContext: OpenFeature.EvaluationContext?) {
Task {
// TODO Remove the sleep in the tests
print(">> Sleeping")
try await Task.sleep(nanoseconds: 1_000_000_000)
print(">> Emitting Ready")
eventHandler.send(.ready)
}
}

var hooks: [any OpenFeature.Hook] = []
var metadata: OpenFeature.ProviderMetadata = DoMetadata()

func getBooleanEvaluation(key: String, defaultValue: Bool, context: EvaluationContext?) throws
-> ProviderEvaluation<
Bool
>
{
return ProviderEvaluation(value: !defaultValue)
}

func getStringEvaluation(key: String, defaultValue: String, context: EvaluationContext?) throws
-> ProviderEvaluation<
String
>
{
return ProviderEvaluation(value: String(defaultValue.reversed()))
}

func getIntegerEvaluation(key: String, defaultValue: Int64, context: EvaluationContext?) throws
-> ProviderEvaluation<
Int64
>
{
return ProviderEvaluation(value: defaultValue * 100)
}

func getDoubleEvaluation(key: String, defaultValue: Double, context: EvaluationContext?) throws
-> ProviderEvaluation<
Double
>
{
return ProviderEvaluation(value: defaultValue * 100)
}

func getObjectEvaluation(key: String, defaultValue: Value, context: EvaluationContext?) throws
-> ProviderEvaluation<
Value
>
{
return ProviderEvaluation(value: .null)
}

func observe() -> CurrentValueSubject<ProviderEvent, Never> {
eventHandler.observe()
}

public struct DoMetadata: ProviderMetadata {
public var name: String? = DoSomethingProvider.name
}
}

0 comments on commit 12ad983

Please sign in to comment.