Skip to content

Commit

Permalink
feat: Append EvalContext to Events (#85)
Browse files Browse the repository at this point in the history
* Append EvalContext to Events

* Test context updates to Confidence
  • Loading branch information
fabriziodemaria authored Apr 9, 2024
1 parent 8de4b78 commit 56f8130
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 5 deletions.
8 changes: 6 additions & 2 deletions ConfidenceDemoApp/ConfidenceDemoApp/ConfidenceDemoApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,14 @@ extension ConfidenceDemoApp {
let provider = ConfidenceFeatureProvider(confidence: confidence)

// NOTE: Using a random UUID for each app start is not advised and can result in getting stale values.
let ctx = MutableContext(targetingKey: UUID.init().uuidString, structure: MutableStructure())
let ctx = MutableContext(
targetingKey: UUID.init().uuidString,
structure: MutableStructure.init(attributes: ["country": .string("SE")]))
Task {
await OpenFeatureAPI.shared.setProviderAndWait(provider: provider, initialContext: ctx)
confidence.send(definition: "my_event", payload: ConfidenceStruct())
confidence.send(
definition: "my_event",
payload: ["my_string_field": ConfidenceValue(string: "hello_from_world")])
}
}
}
2 changes: 1 addition & 1 deletion Sources/Confidence/Confidence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class Confidence: ConfidenceEventSender {

// TODO: Implement actual event uploading to the backend
public func send(definition: String, payload: ConfidenceStruct) {
print("Sending \(definition) - Targeting key: \(payload)")
print("Sending: \"\(definition)\".\nMessage: \(payload)\nContext: \(context)")
}

public func updateContextEntry(key: String, value: ConfidenceValue) {
Expand Down
5 changes: 4 additions & 1 deletion Sources/Confidence/ConfidenceValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ import Foundation

public typealias ConfidenceStruct = [String: ConfidenceValue]

public class ConfidenceValue: Equatable, Encodable {
public class ConfidenceValue: Equatable, Encodable, CustomStringConvertible {
private let value: ConfidenceValueInternal
public var description: String {
return value.description
}

public init(boolean: Bool) {
self.value = .boolean(boolean)
Expand Down
9 changes: 9 additions & 0 deletions Sources/ConfidenceProvider/ConfidenceFeatureProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public class ConfidenceFeatureProvider: FeatureProvider {
return
}

self.updateConfidenceContext(context: initialContext)
if self.initializationStrategy == .activateAndFetchAsync {
eventHandler.send(.ready)
}
Expand Down Expand Up @@ -128,12 +129,14 @@ public class ConfidenceFeatureProvider: FeatureProvider {
return
}

self.updateConfidenceContext(context: newContext)
Task {
do {
let resolveResult = try await resolve(context: newContext)

// update the storage
try await store(with: newContext, resolveResult: resolveResult, refreshCache: true)

eventHandler.send(ProviderEvent.ready)
} catch {
eventHandler.send(ProviderEvent.ready)
Expand All @@ -142,6 +145,12 @@ public class ConfidenceFeatureProvider: FeatureProvider {
}
}

private func updateConfidenceContext(context: EvaluationContext) {
confidence?.updateContextEntry(
key: "open_feature",
value: ConfidenceValue(structure: ConfidenceTypeMapper.from(ctx: context)))
}

public func getBooleanEvaluation(key: String, defaultValue: Bool, context: EvaluationContext?) throws
-> OpenFeature.ProviderEvaluation<Bool>
{
Expand Down
52 changes: 52 additions & 0 deletions Tests/ConfidenceProviderTests/ConfidenceFeatureProviderTest.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// swiftlint:disable type_body_length

Check warning on line 1 in Tests/ConfidenceProviderTests/ConfidenceFeatureProviderTest.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Blanket Disable Command Violation: The disabled 'type_body_length' rule should be re-enabled before the end of the file (blanket_disable_command)
// swiftlint:disable file_length
import Foundation
import Confidence
import OpenFeature
import XCTest

Expand Down Expand Up @@ -898,6 +899,57 @@ class ConfidenceFeatureProviderTest: XCTestCase {
XCTAssertEqual(evaluation.value, 5)
}
}

func testConfidenceContextOnInitialize() throws {
let confidence = Confidence.Builder.init(clientSecret: "").build()
let provider = ConfidenceFeatureProvider(confidence: confidence)

withExtendedLifetime(
provider.observe().sink { event in
if event == .ready {
self.readyExpectation.fulfill()
}
})
{
provider.initialize(initialContext: MutableContext(targetingKey: "user1"))
wait(for: [readyExpectation], timeout: 5)
let context = confidence.context
let expected = [
"open_feature": ConfidenceValue(structure: ["targeting_key": ConfidenceValue(string: "user1")])
]
XCTAssertEqual(context, expected)
}
}

func testConfidenceContextOnContextChange() throws {
let confidence = Confidence.Builder.init(clientSecret: "").build()
let provider = ConfidenceFeatureProvider(confidence: confidence)

let readyExpectation = self.expectation(description: "Waiting for init and ctx change to complete")
readyExpectation.expectedFulfillmentCount = 2

withExtendedLifetime(
provider.observe().sink { event in
if event == .ready {
readyExpectation.fulfill()
}
})
{
let ctx1 = MutableContext(targetingKey: "user1")
let ctx2 = MutableContext(targetingKey: "user1", structure: MutableStructure(attributes: ["active": Value.boolean(true)]))

Check warning on line 939 in Tests/ConfidenceProviderTests/ConfidenceFeatureProviderTest.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Line Length Violation: Line should be 120 characters or less; currently it has 134 characters (line_length)
provider.initialize(initialContext: ctx1)
provider.onContextSet(oldContext: ctx1, newContext: ctx2)
wait(for: [readyExpectation], timeout: 5)
let context = confidence.context
let expected = [
"open_feature": ConfidenceValue(structure: [
"targeting_key": ConfidenceValue(string: "user1"),
"active": ConfidenceValue(boolean: true)
])
]
XCTAssertEqual(context, expected)
}
}
}

final class DispatchQueueFake: DispatchQueueType {
Expand Down
5 changes: 4 additions & 1 deletion Tests/ConfidenceProviderTests/ConfidenceTypeMapperTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ class ValueConverterTest: XCTestCase {
"dateList": .list([.date(date1), .date(date2)]),
"nullList": .list([.null, .null]),
"listList": .list([.list([.string("nested_value1")]), .list([.string("nested_value2")])]),
"structList": .list([.structure(["test": .string("nested_test1")]), .structure(["test": .string("nested_test2")])])
"structList": .list([
.structure(["test": .string("nested_test1")]),
.structure(["test": .string("nested_test2")])
])
])))
let confidenceStruct = ConfidenceTypeMapper.from(ctx: openFeatureCtx)
let expected = [
Expand Down

0 comments on commit 56f8130

Please sign in to comment.