Skip to content
This repository has been archived by the owner on Sep 13, 2023. It is now read-only.

Commit

Permalink
Merge pull request #16 from spotify/client-things
Browse files Browse the repository at this point in the history
Use generic types extensions, use a lock instead of queue
  • Loading branch information
Calibretto authored Jun 29, 2023
2 parents acaca2d + 8e3d442 commit d89152f
Showing 1 changed file with 19 additions and 29 deletions.
48 changes: 19 additions & 29 deletions Sources/OpenFeature/OpenFeatureClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,14 @@ import Foundation
import os

public class OpenFeatureClient: Client {
// TODO: We use DispatchQueue here instead of being an actor to not lock into new versions of Swift
private let hookQueue = DispatchQueue(label: "dev.openfeature.client.hook")
private let contextQueue = DispatchQueue(label: "dev.openfeature.client.context")
private let hookLock = NSLock()

private var openFeatureApi: OpenFeatureAPI
private(set) var name: String?
private(set) var version: String?

private var _metadata: Metadata
public var metadata: Metadata {
return _metadata
}

private var _hooks: [any Hook] = []
public var hooks: [any Hook] {
return _hooks
}
private(set) public var metadata: Metadata
private(set) public var hooks: [any Hook] = []

private var hookSupport = HookSupport()
private var logger = Logger()
Expand All @@ -27,13 +18,13 @@ public class OpenFeatureClient: Client {
self.openFeatureApi = openFeatureApi
self.name = name
self.version = version
self._metadata = ClientMetadata(name: name)
self.metadata = ClientMetadata(name: name)
}

public func addHooks(_ hooks: any Hook...) {
self.hookQueue.sync {
self._hooks.append(contentsOf: hooks)
}
hookLock.lock()
self.hooks.append(contentsOf: hooks)
hookLock.unlock()
}
}

Expand All @@ -58,7 +49,6 @@ extension OpenFeatureClient {
-> FlagEvaluationDetails<T> where T: AllowedFlagValueType, T: Equatable
{
evaluateFlag(
flagValueType: T.flagValueType,
key: key,
defaultValue: defaultValue,
options: options
Expand All @@ -73,8 +63,7 @@ extension OpenFeatureClient {
}

extension OpenFeatureClient {
private func evaluateFlag<T>(
flagValueType: FlagValueType,
private func evaluateFlag<T: AllowedFlagValueType>(
key: String,
defaultValue: T,
options: FlagEvaluationOptions?
Expand All @@ -85,20 +74,22 @@ extension OpenFeatureClient {

var details = FlagEvaluationDetails(flagKey: key, value: defaultValue)
let provider = openFeatureApi.getProvider() ?? NoOpProvider()
let mergedHooks = provider.hooks + options.hooks + hooks + openFeatureApi.hooks
let hookCtx = HookContext(
flagKey: key,
type: flagValueType,
type: T.flagValueType,
defaultValue: defaultValue,
ctx: context,
clientMetadata: self.metadata,
providerMetadata: provider.metadata)

hookLock.lock()
let mergedHooks = provider.hooks + options.hooks + hooks + openFeatureApi.hooks
hookLock.unlock()

do {
hookSupport.beforeHooks(flagValueType: flagValueType, hookCtx: hookCtx, hooks: mergedHooks, hints: hints)
hookSupport.beforeHooks(flagValueType: T.flagValueType, hookCtx: hookCtx, hooks: mergedHooks, hints: hints)

let providerEval = try createProviderEvaluation(
flagValueType: flagValueType,
key: key,
context: context,
defaultValue: defaultValue,
Expand All @@ -108,7 +99,7 @@ extension OpenFeatureClient {
details = evalDetails

try hookSupport.afterHooks(
flagValueType: flagValueType, hookCtx: hookCtx, details: evalDetails, hooks: mergedHooks, hints: hints)
flagValueType: T.flagValueType, hookCtx: hookCtx, details: evalDetails, hooks: mergedHooks, hints: hints)
} catch {
logger.error("Unable to correctly evaluate flag with key \(key) due to exception \(error)")

Expand All @@ -122,24 +113,23 @@ extension OpenFeatureClient {
details.reason = Reason.error.rawValue

hookSupport.errorHooks(
flagValueType: flagValueType, hookCtx: hookCtx, error: error, hooks: mergedHooks, hints: hints)
flagValueType: T.flagValueType, hookCtx: hookCtx, error: error, hooks: mergedHooks, hints: hints)
}

hookSupport.afterAllHooks(
flagValueType: flagValueType, hookCtx: hookCtx, hooks: mergedHooks, hints: hints)
flagValueType: T.flagValueType, hookCtx: hookCtx, hooks: mergedHooks, hints: hints)

return details
}

// swiftlint:disable:next cyclomatic_complexity
private func createProviderEvaluation<V>(
flagValueType: FlagValueType,
private func createProviderEvaluation<V: AllowedFlagValueType>(
key: String,
context: EvaluationContext?,
defaultValue: V,
provider: FeatureProvider
) throws -> ProviderEvaluation<V> {
switch flagValueType {
switch V.flagValueType {
case .boolean:
guard let defaultValue = defaultValue as? Bool else {
break
Expand Down

0 comments on commit d89152f

Please sign in to comment.