Skip to content

Commit

Permalink
feat: First Confidence Scaffolding
Browse files Browse the repository at this point in the history
  • Loading branch information
fabriziodemaria committed Mar 27, 2024
1 parent e529cc8 commit a5ec0d5
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 50 deletions.
10 changes: 7 additions & 3 deletions ConfidenceDemoApp/ConfidenceDemoApp/ConfidenceDemoApp.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import ConfidenceProvider
import OpenFeature
import SwiftUI
import Confidence

@main
struct ConfidenceDemoApp: App {
Expand All @@ -26,10 +27,13 @@ extension ConfidenceDemoApp {
initializationStratgey = .fetchAndActivate
}

let provider = ConfidenceFeatureProvider
.Builder(credentials: .clientSecret(secret: secret))
.with(initializationStrategy: initializationStratgey)
// TODO: Remove Builder pattern
let confidence = Confidence.Builder(clientSecret: secret)
.withOptions(options: ConfidenceClientOptions(initializationStrategy: initializationStratgey))
.build()
// TODO: Remove Builder pattern
let provider = ConfidenceFeatureProvider.Builder(confidence: confidence).build()

// 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())
OpenFeatureAPI.shared.setProvider(provider: provider, initialContext: ctx)
Expand Down
13 changes: 11 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@
import PackageDescription

let package = Package(
name: "ConfidenceProvider",
name: "Confidence",
platforms: [
.iOS(.v14),
.macOS(.v12)
],
products: [
.library(
name: "ConfidenceProvider",
targets: ["ConfidenceProvider"])
targets: ["ConfidenceProvider"]),
.library(
name: "Confidence",
targets: ["Confidence"])
],
dependencies: [
.package(url: "[email protected]:open-feature/swift-sdk.git", from: "0.1.0"),
Expand All @@ -22,9 +25,15 @@ let package = Package(
name: "ConfidenceProvider",
dependencies: [
.product(name: "OpenFeature", package: "swift-sdk"),
"Confidence"
],
plugins: []
),
.target(
name: "Confidence",
dependencies: [],
plugins: []
),
.testTarget(
name: "ConfidenceProviderTests",
dependencies: [
Expand Down
63 changes: 63 additions & 0 deletions Sources/Confidence/Confidence.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import Foundation

public class Confidence: ConfidenceEventSender {
public var context: [String: String]
public let clientSecret: String
public let options: ConfidenceClientOptions

init(clientSecret: String, options: ConfidenceClientOptions) {
self.clientSecret = clientSecret
self.options = options
self.context = [:]
}

public func send(eventName: String) {
print("Sending \(eventName)")
}

public func updateContextEntry(key: String, value: String) {
context[key] = value
}

public func removeContextEntry(key: String) {
context.removeValue(forKey: key)
}

public func clearContext() {
context = [:]
}

public func withContext(_ context: [String: String]) -> Self {
// TODO
return self
}
}

extension Confidence {
public struct Builder {
let clientSecret: String
var options: ConfidenceClientOptions

public init(clientSecret: String) {
self.clientSecret = clientSecret
self.options = ConfidenceClientOptions(
credentials: ConfidenceClientCredentials.clientSecret(secret: (clientSecret)))
}

init(clientSecret: String, options: ConfidenceClientOptions) {
self.clientSecret = clientSecret
self.options = options
}

public func withOptions(options: ConfidenceClientOptions) -> Builder {
return Builder(
clientSecret: clientSecret,
options: options
)
}

public func build() -> Confidence {
return Confidence(clientSecret: clientSecret, options: ConfidenceClientOptions())
}
}
}
41 changes: 41 additions & 0 deletions Sources/Confidence/ConfidenceClientOptions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import Foundation

public struct ConfidenceClientOptions {
public var credentials: ConfidenceClientCredentials // DEPRECATED
public var timeout: TimeInterval
public var region: ConfidenceRegion
public var initializationStrategy: InitializationStrategy

public init(
credentials: ConfidenceClientCredentials? = nil,
timeout: TimeInterval? = nil,
region: ConfidenceRegion? = nil,
initializationStrategy: InitializationStrategy = .fetchAndActivate
) {
self.credentials = credentials ?? ConfidenceClientCredentials.clientSecret(secret: "")
self.timeout = timeout ?? 10.0
self.region = region ?? .global
self.initializationStrategy = initializationStrategy
}
}

public enum ConfidenceClientCredentials {
case clientSecret(secret: String)

public func getSecret() -> String {
switch self {
case .clientSecret(let secret):
return secret
}
}
}

public enum ConfidenceRegion {
case global
case europe
case usa
}

public enum InitializationStrategy {
case fetchAndActivate, activateAndFetchAsync
}
5 changes: 5 additions & 0 deletions Sources/Confidence/ConfidenceEventSender.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Foundation

public protocol ConfidenceEventSender: Contextual {
func send(eventName: String)
}
11 changes: 11 additions & 0 deletions Sources/Confidence/Contextual.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Foundation

public protocol Contextual {
var context: [String: String] { get set } // TODO Introdue complex types

func updateContextEntry(key: String, value: String)
func removeContextEntry(key: String)
func clearContext()

func withContext(_ context: [String: String]) -> Self
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Foundation
import OpenFeature
import Confidence
import os

typealias ApplyFlagHTTPResponse = HttpClientResponse<ApplyFlagsResponse>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import Foundation
import OpenFeature
import Confidence


public class RemoteConfidenceClient: ConfidenceClient {
private let targetingKey = "targeting_key"
Expand Down Expand Up @@ -161,37 +163,6 @@ struct ApplyFlagsRequest: Codable {
struct ApplyFlagsResponse: Codable {
}

public struct ConfidenceClientOptions {
public var credentials: ConfidenceClientCredentials
public var timeout: TimeInterval
public var region: ConfidenceRegion

public init(
credentials: ConfidenceClientCredentials, timeout: TimeInterval? = nil, region: ConfidenceRegion? = nil
) {
self.credentials = credentials
self.timeout = timeout ?? 10.0
self.region = region ?? .global
}
}

public enum ConfidenceClientCredentials {
case clientSecret(secret: String)

public func getSecret() -> String {
switch self {
case .clientSecret(let secret):
return secret
}
}
}

public enum ConfidenceRegion {
case global
case europe
case usa
}

struct Sdk: Codable {
init(id: String?, version: String?) {
self.id = id ?? "SDK_ID_SWIFT_PROVIDER"
Expand Down
32 changes: 23 additions & 9 deletions Sources/ConfidenceProvider/ConfidenceFeatureProvider.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Foundation
import OpenFeature
import Combine
import Confidence
import os

/// The implementation of the Confidence Feature Provider. This implementation allows to pre-cache evaluations.
Expand All @@ -21,6 +22,7 @@ public class ConfidenceFeatureProvider: FeatureProvider {
private let initializationStrategy: InitializationStrategy
private let storage: Storage
private let eventHandler = EventHandler(ProviderEvent.notReady)
private let confidence: Confidence?

/// Should not be called externally, use `ConfidenceFeatureProvider.Builder` instead.
init(
Expand All @@ -31,7 +33,8 @@ public class ConfidenceFeatureProvider: FeatureProvider {
overrides: [String: LocalOverride] = [:],
flagApplier: FlagApplier,
applyStorage: Storage,
initializationStrategy: InitializationStrategy
initializationStrategy: InitializationStrategy,
confidence: Confidence?
) {
self.client = client
self.metadata = metadata
Expand All @@ -40,6 +43,7 @@ public class ConfidenceFeatureProvider: FeatureProvider {
self.flagApplier = flagApplier
self.initializationStrategy = initializationStrategy
self.storage = storage
self.confidence = confidence

resolver = LocalStorageResolver(cache: cache)
}
Expand Down Expand Up @@ -251,12 +255,12 @@ public class ConfidenceFeatureProvider: FeatureProvider {
)
return evaluationResult
} catch ConfidenceError.cachedValueExpired {
return ProviderEvaluation(value: defaultValue,
variant: nil,
reason: Reason.error.rawValue,
errorCode: ErrorCode.providerNotReady
)}
catch {
return ProviderEvaluation(
value: defaultValue,
variant: nil,
reason: Reason.error.rawValue,
errorCode: ErrorCode.providerNotReady)
} catch {
throw error
}
}
Expand Down Expand Up @@ -410,8 +414,9 @@ extension ConfidenceFeatureProvider {
var flagApplier: (any FlagApplier)?
var initializationStrategy: InitializationStrategy = .fetchAndActivate
var applyStorage: Storage = DefaultStorage.resolverApplyCache()
var confidence: Confidence?

/// Initializes the builder with the given credentails.
/// Initializes the builder with the given credentails. DEPRECATED
///
/// OpenFeatureAPI.shared.setProvider(provider:
/// ConfidenceFeatureProvider.Builder(credentials: .clientSecret(secret: "mysecret"))
Expand All @@ -420,6 +425,14 @@ extension ConfidenceFeatureProvider {
self.options = ConfidenceClientOptions(credentials: credentials)
}

/// TODO
public init(confidence: Confidence) {
self.options = ConfidenceClientOptions(credentials: ConfidenceClientCredentials
.clientSecret(secret: confidence.clientSecret))
self.initializationStrategy = confidence.options.initializationStrategy
self.confidence = confidence
}

init(
options: ConfidenceClientOptions,
session: URLSession? = nil,
Expand Down Expand Up @@ -606,7 +619,8 @@ extension ConfidenceFeatureProvider {
overrides: localOverrides,
flagApplier: flagApplier,
applyStorage: applyStorage,
initializationStrategy: initializationStrategy
initializationStrategy: initializationStrategy,
confidence: confidence
)
}
}
Expand Down
1 change: 1 addition & 0 deletions Sources/ConfidenceProvider/Http/NetworkClient.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Foundation
import Confidence

final class NetworkClient: HttpClient {
private let headers: [String: String]
Expand Down
5 changes: 0 additions & 5 deletions Sources/ConfidenceProvider/InitializationStrategy.swift

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// swiftlint:disable file_length
import Foundation
import OpenFeature
import Confidence
import XCTest

@testable import ConfidenceProvider
Expand Down

0 comments on commit a5ec0d5

Please sign in to comment.