Skip to content

Commit c7b98f4

Browse files
committed
Updates returning an error vs throwing an error pattern in multiprovider strategies
1 parent 4863f2f commit c7b98f4

File tree

3 files changed

+49
-12
lines changed

3 files changed

+49
-12
lines changed

Sources/OpenFeature/Provider/MultiProvider/FirstMatchStrategy.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ final public class FirstMatchStrategy: Strategy {
1919
}
2020
} catch OpenFeatureError.flagNotFoundError {
2121
continue
22+
} catch let error as OpenFeatureError {
23+
return ProviderEvaluation(
24+
value: defaultValue,
25+
reason: Reason.error.rawValue,
26+
errorCode: error.errorCode(),
27+
errorMessage: error.description
28+
)
2229
} catch {
2330
throw error
2431
}

Sources/OpenFeature/Provider/MultiProvider/FirstSuccessfulStrategy.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/// FirstSuccessfulStrategy is a strategy that evaluates a feature flag across multiple providers
22
/// and returns the first result. Similar to `FirstMatchStrategy` but does not bubble up individual provider errors.
3-
/// If no provider successfully responds, it will throw an error.
3+
/// If no provider successfully responds, it will return an error.
44
final public class FirstSuccessfulStrategy: Strategy {
55
public func evaluate<T>(
66
providers: [FeatureProvider],
@@ -20,6 +20,10 @@ final public class FirstSuccessfulStrategy: Strategy {
2020
}
2121
}
2222

23-
throw OpenFeatureError.flagNotFoundError(key: key)
23+
return ProviderEvaluation(
24+
value: defaultValue,
25+
reason: Reason.defaultReason.rawValue,
26+
errorCode: ErrorCode.flagNotFound
27+
)
2428
}
2529
}

Tests/OpenFeatureTests/MultiProviderTests.swift

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ final class MultiProviderTests: XCTestCase {
120120
XCTAssertTrue(result.errorCode == .flagNotFound)
121121
}
122122

123-
func testEvaluationWithMultipleProvidersAndFirstMatchStrategy_Throws() throws {
123+
func testEvaluationWithMultipleProvidersAndFirstMatchStrategy_HandlesOpenFeatureError() throws {
124124
let mockKey = "test-key"
125125
let mockProvider1 = MockProvider(
126126
initialize: { _ in },
@@ -138,12 +138,39 @@ final class MultiProviderTests: XCTestCase {
138138
providers: [mockProvider1, mockProvider2],
139139
strategy: FirstMatchStrategy()
140140
)
141+
let defaultValue = false
142+
let result = try multiProvider.getBooleanEvaluation(
143+
key: mockKey, defaultValue: defaultValue, context: MutableContext())
144+
XCTAssertEqual(result.value, false)
145+
XCTAssertNotNil(result.errorCode)
146+
}
141147

148+
func testEvaluationWithMultipleProvidersAndFirstMatchStrategy_Throws() throws {
149+
let mockKey = "test-key"
150+
let mockError = MockProvider.MockProviderError.message("test non-open feature error")
151+
let mockProvider1 = MockProvider(
152+
initialize: { _ in },
153+
getBooleanEvaluation: { _, defaultValue, _ in
154+
return ProviderEvaluation(value: defaultValue, errorCode: .flagNotFound)
155+
}
156+
)
157+
let mockProvider2 = MockProvider(
158+
initialize: { _ in },
159+
getBooleanEvaluation: { _, _, _ in
160+
throw mockError
161+
}
162+
)
163+
let multiProvider = MultiProvider(
164+
providers: [mockProvider1, mockProvider2],
165+
strategy: FirstMatchStrategy()
166+
)
167+
let defaultValue = false
142168
do {
143-
_ = try multiProvider.getBooleanEvaluation(key: mockKey, defaultValue: false, context: MutableContext())
144-
XCTFail("Expected error to be thrown")
169+
_ = try multiProvider.getBooleanEvaluation(
170+
key: mockKey, defaultValue: defaultValue, context: MutableContext())
171+
XCTFail("Expected to throw")
145172
} catch {
146-
XCTAssertEqual(error as? OpenFeatureError, OpenFeatureError.generalError(message: "test error"))
173+
XCTAssertTrue(error is MockProvider.MockProviderError)
147174
}
148175
}
149176

@@ -192,12 +219,11 @@ final class MultiProviderTests: XCTestCase {
192219
strategy: FirstSuccessfulStrategy()
193220
)
194221

195-
do {
196-
_ = try multiProvider.getBooleanEvaluation(key: mockKey, defaultValue: false, context: MutableContext())
197-
XCTFail("Expected error to be thrown")
198-
} catch {
199-
XCTAssertTrue(error as? OpenFeatureError == OpenFeatureError.flagNotFoundError(key: mockKey))
200-
}
222+
let defaultValue = false
223+
let result = try multiProvider.getBooleanEvaluation(
224+
key: mockKey, defaultValue: defaultValue, context: MutableContext())
225+
XCTAssertEqual(result.errorCode, .flagNotFound)
226+
XCTAssertEqual(result.value, defaultValue)
201227
}
202228

203229
func testObserveWithMultipleProviders() {

0 commit comments

Comments
 (0)