Skip to content
Closed
53 changes: 37 additions & 16 deletions Split/Api/DefaultSplitClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Foundation
typealias DestroyHandler = () -> Void

public final class DefaultSplitClient: NSObject, SplitClient, TelemetrySplitClient {

private var storageContainer: SplitStorageContainer
private var key: Key
private let config: SplitClientConfig
Expand Down Expand Up @@ -57,26 +57,43 @@ public final class DefaultSplitClient: NSObject, SplitClient, TelemetrySplitClie

// MARK: Events
extension DefaultSplitClient {

public func on(event: SplitEvent, execute action: @escaping SplitAction) {

public func on(event: SplitEvent, perform: SplitAction?) {
guard let perform = perform else { return }
on(event: SplitEventWithMetadata(type: event, metadata: nil), execute: perform)
}

public func on(event: SplitEventWithMetadata, execute action: @escaping SplitAction) {
on(event: event, runInBackground: false, queue: nil, execute: action)
}

public func on(event: SplitEvent, runInBackground: Bool,
execute action: @escaping SplitAction) {
public func on(event: SplitEventWithMetadata, runInBackground: Bool, execute action: @escaping SplitAction) {
on(event: event, runInBackground: runInBackground, queue: nil, execute: action)
}

public func on(event: SplitEvent,
queue: DispatchQueue, execute action: @escaping SplitAction) {
public func on(event: SplitEventWithMetadata, queue: DispatchQueue, execute action: @escaping SplitAction) {
on(event: event, runInBackground: true, queue: queue, execute: action)
}

private func on(event: SplitEventWithMetadata, runInBackground: Bool, queue: DispatchQueue?, execute action: @escaping SplitAction) {
guard let factory = clientManager?.splitFactory else {
return
}

private func on(event: SplitEvent,
runInBackground: Bool,
queue: DispatchQueue?,
execute action: @escaping SplitAction) {

let task = SplitEventActionTask(action: action, event: event,
runInBackground: runInBackground,
factory: factory,
queue: queue)
task.event = event
on(event: event, executeTask: task)
}

public func on(event: SplitEvent, performWithMetadata action: SplitActionWithMetadata?) {
guard let action = action else { return }
onWithMetadata(event:SplitEventWithMetadata(type: event, metadata: nil), runInBackground: true, queue: nil, execute: action)
}

private func onWithMetadata(event: SplitEventWithMetadata, runInBackground: Bool, queue: DispatchQueue?, execute action: @escaping SplitActionWithMetadata) {
guard let factory = clientManager?.splitFactory else {
return
}
Expand All @@ -88,16 +105,20 @@ extension DefaultSplitClient {
task.event = event
on(event: event, executeTask: task)
}


private func on(event: SplitEvent, executeTask task: SplitEventTask) {
if event != .sdkReadyFromCache,
eventsManager.eventAlreadyTriggered(event: event) {
Logger.w("A handler was added for \(event.toString()) on the SDK, " +
private func on(event: SplitEventWithMetadata, executeTask task: SplitEventActionTask) {
if event.type != .sdkReadyFromCache,
eventsManager.eventAlreadyTriggered(event: event.type) {
Logger.w("A handler was added for \(event.type.toString()) on the SDK, " +
"which has already fired and won’t be emitted again. The callback won’t be executed.")
return
}
eventsManager.register(event: event, task: task)
}



}

// MARK: Treatment / Evaluation
Expand Down
15 changes: 12 additions & 3 deletions Split/Api/FailHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import Foundation
///

class FailedClient: SplitClient {
func on(event: SplitEvent, performWithMetadata: SplitActionWithMetadata?) {

}

func getTreatment(_ split: String) -> String {
return SplitConstants.control
Expand Down Expand Up @@ -53,15 +56,21 @@ class FailedClient: SplitClient {
func getTreatmentsWithConfig(splits: [String], attributes: [String: Any]?, evaluationOptions: EvaluationOptions?) -> [String: SplitResult] {
return [:]
}

public func on(event: SplitEvent, perform: SplitAction?) {
}

func on(event: SplitEvent, perform: @escaping ([String : Any]?) -> Void) {
}

func on(event: SplitEvent, execute action: @escaping SplitAction) {
func on(event: SplitEventWithMetadata, execute action: @escaping SplitAction) {
}

func on(event: SplitEvent, runInBackground: Bool,
func on(event: SplitEventWithMetadata, runInBackground: Bool,
execute action: @escaping SplitAction) {
}

func on(event: SplitEvent,
func on(event: SplitEventWithMetadata,
queue: DispatchQueue, execute action: @escaping SplitAction) {
}

Expand Down
40 changes: 32 additions & 8 deletions Split/Api/LocalhostSplitClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,7 @@ public final class LocalhostSplitClient: NSObject, SplitClient {
private let key: Key
weak var clientManger: SplitClientManager?

init(key: Key, splitsStorage: SplitsStorage,
clientManager: SplitClientManager?,
eventsManager: SplitEventsManager? = nil,
evaluator: Evaluator) {
init(key: Key, splitsStorage: SplitsStorage, clientManager: SplitClientManager?, eventsManager: SplitEventsManager? = nil, evaluator: Evaluator) {
self.eventsManager = eventsManager
self.key = key
self.splitsStorage = splitsStorage
Expand Down Expand Up @@ -120,21 +117,35 @@ public final class LocalhostSplitClient: NSObject, SplitClient {
}
return results
}

public func on(event: SplitEvent, perform: SplitAction?) {
guard let perform = perform else { return }
on(event: SplitEventWithMetadata(type: event, metadata: nil), execute: perform)
}

public func on(event: SplitEvent, performWithMetadata: SplitActionWithMetadata?) {
guard let performWithMetadata = performWithMetadata else { return }
on(eventWithMetadata: SplitEventWithMetadata(type: event, metadata: nil), runInBackground: false, queue: nil, execute: performWithMetadata)
}

public func on(event: SplitEvent, runInBackground: Bool,
public func on(event: SplitEventWithMetadata, runInBackground: Bool,
execute action: @escaping SplitAction) {
on(event: event, runInBackground: runInBackground, queue: nil, execute: action)
}

public func on(event: SplitEvent, queue: DispatchQueue, execute action: @escaping SplitAction) {
public func on(event: SplitEventWithMetadata, queue: DispatchQueue, execute action: @escaping SplitAction) {
on(event: event, runInBackground: true, queue: queue, execute: action)
}

public func on(event: SplitEvent, execute action: @escaping SplitAction) {
public func on(event: SplitEventWithMetadata, execute action: @escaping SplitAction) {
on(event: event, runInBackground: false, queue: nil, execute: action)
}

private func on(event: SplitEvent, runInBackground: Bool,
private func on(event: SplitEventWithMetadata, runInBackground: Bool, queue: DispatchQueue?, execute action: @escaping SplitAction) {
on(eventWithMetadata: event, runInBackground: runInBackground, queue: queue, execute: action)
}

private func on(eventWithMetadata event: SplitEventWithMetadata, runInBackground: Bool,
queue: DispatchQueue?, execute action: @escaping SplitAction) {

guard let factory = clientManger?.splitFactory else { return }
Expand All @@ -146,6 +157,19 @@ public final class LocalhostSplitClient: NSObject, SplitClient {
eventsManager.register(event: event, task: task)
}
}

private func on(eventWithMetadata event: SplitEventWithMetadata, runInBackground: Bool,
queue: DispatchQueue?, execute action: @escaping SplitActionWithMetadata) {

guard let factory = clientManger?.splitFactory else { return }
if let eventsManager = self.eventsManager {
let task = SplitEventActionTask(action: action, event: event,
runInBackground: runInBackground,
factory: factory,
queue: queue)
eventsManager.register(event: event, task: task)
}
}

public func track(trafficType: String, eventType: String) -> Bool {
return true
Expand Down
13 changes: 8 additions & 5 deletions Split/Api/SplitClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import Foundation

public typealias SplitAction = () -> Void
public typealias SplitActionWithMetadata = (_ data: Any?) -> Void

@objc public protocol SplitClient {

Expand All @@ -32,11 +33,13 @@ public typealias SplitAction = () -> Void
func getTreatmentWithConfig(_ split: String, attributes: [String: Any]?, evaluationOptions: EvaluationOptions?) -> SplitResult
@objc(getTreatmentsWithConfigForSplits:attributes:evaluationOptions:)
func getTreatmentsWithConfig(splits: [String], attributes: [String: Any]?, evaluationOptions: EvaluationOptions?) -> [String: SplitResult]

func on(event: SplitEvent, execute action: @escaping SplitAction)
func on(event: SplitEvent, runInBackground: Bool, execute action: @escaping SplitAction)
func on(event: SplitEvent, queue: DispatchQueue, execute action: @escaping SplitAction)


func on(event: SplitEvent, perform: SplitAction?) -> Void
func on(event: SplitEvent, performWithMetadata: SplitActionWithMetadata?) -> Void
func on(event: SplitEventWithMetadata, execute action: @escaping SplitAction)
func on(event: SplitEventWithMetadata, runInBackground: Bool, execute action: @escaping SplitAction)
func on(event: SplitEventWithMetadata, queue: DispatchQueue, execute action: @escaping SplitAction)

// MARK: Track feature
func track(trafficType: String, eventType: String) -> Bool
func track(trafficType: String, eventType: String, value: Double) -> Bool
Expand Down
4 changes: 2 additions & 2 deletions Split/Api/SplitClientManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,15 @@ class DefaultClientManager: SplitClientManager {
eventsManagerCoordinator.start()

if let producer = telemetryProducer {
defaultClient?.on(event: .sdkReadyFromCache) {
defaultClient?.on(event: SplitEventWithMetadata(type: .sdkReadyFromCache, metadata: nil)) {
DispatchQueue.general.async { [weak self] in
if let self = self {
producer.recordTimeUntilReadyFromCache(self.telemetryStopwatch?.interval() ?? 0)
}
}
}

defaultClient?.on(event: .sdkReady) {
defaultClient?.on(event: SplitEventWithMetadata(type: .sdkReadyFromCache, metadata: nil)) {
DispatchQueue.general.async { [weak self] in
if let self = self {
producer.recordTimeUntilReady(self.telemetryStopwatch?.interval() ?? 0)
Expand Down
15 changes: 10 additions & 5 deletions Split/Events/EventsManagerCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,18 @@ protocol SplitEventsManagerCoordinator: SplitEventsManager {
}

class MainSplitEventsManager: SplitEventsManagerCoordinator {

private var defaultManager: SplitEventsManager?
private var managers = [Key: SplitEventsManager]()
private var triggered = Set<SplitInternalEvent>()
private var triggered = Set<SplitEventCase>()
private let queue = DispatchQueue(label: "split-event-manager-coordinator")
private let eventsToHandle: Set<SplitInternalEvent> = Set(
private let eventsToHandle: Set<SplitEventCase> = Set(
[.splitsLoadedFromCache,
.splitsUpdated,
.splitKilledNotification]
)

func notifyInternalEvent(_ event: SplitInternalEvent) {
func notifyInternalEvent(_ event: SplitEventCase, _ metadata: [String : Any]? = nil) {
if !eventsToHandle.contains(event) {
return
}
Expand All @@ -33,10 +34,14 @@ class MainSplitEventsManager: SplitEventsManagerCoordinator {

self.triggered.insert(event)
self.managers.forEach { _, manager in
manager.notifyInternalEvent(event)
manager.notifyInternalEvent(event, metadata)
}
}
}

func notifyInternalEventWithMetadata(_ event: SplitInternalEvent) {
notifyInternalEvent(event.type, event.metadata)
}

func start() {}

Expand Down Expand Up @@ -76,5 +81,5 @@ class MainSplitEventsManager: SplitEventsManagerCoordinator {
}
}

func register(event: SplitEvent, task: SplitEventTask) {}
func register(event: SplitEventWithMetadata, task: SplitEventActionTask) {}
}
21 changes: 21 additions & 0 deletions Split/Events/SplitEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,24 @@ import Foundation
}
}
}

@objcMembers
public class SplitEventWithMetadata: NSObject {
let type: SplitEvent
let metadata: [String: Any]?

@objc public init(type: SplitEvent, metadata: [String : Any]? = nil) {
self.type = type
self.metadata = metadata
}

public override func isEqual(_ object: Any?) -> Bool {
guard let other = object as? SplitEventWithMetadata else { return false }
return self.type == other.type
}

public override var hash: Int {
return type.hashValue
}
}

23 changes: 14 additions & 9 deletions Split/Events/SplitEventActionTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,23 @@
import Foundation

class SplitEventActionTask: SplitEventTask {

private var eventHandler: SplitAction?
private var eventHandlerWithMetadata: SplitActionWithMetadata?
private var queue: DispatchQueue?
var event: SplitEvent
var event: SplitEventWithMetadata
var runInBackground: Bool = false
var factory: SplitFactory

init(action: @escaping SplitAction,
event: SplitEvent,
runInBackground: Bool = false,
factory: SplitFactory,
queue: DispatchQueue? = nil) {

init(action: @escaping SplitActionWithMetadata, event: SplitEventWithMetadata, runInBackground: Bool = false, factory: SplitFactory, queue: DispatchQueue? = nil) {
self.eventHandlerWithMetadata = action
self.event = event
self.runInBackground = runInBackground
self.queue = queue
self.factory = factory
}

init(action: @escaping SplitAction, event: SplitEventWithMetadata, runInBackground: Bool = false, factory: SplitFactory, queue: DispatchQueue? = nil) {
self.eventHandler = action
self.event = event
self.runInBackground = runInBackground
Expand All @@ -33,7 +37,8 @@ class SplitEventActionTask: SplitEventTask {
return queue
}

func run() {
func run(_ data: Any?) {
eventHandler?()
eventHandlerWithMetadata?(data)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import Foundation

enum SplitInternalEvent {
enum SplitEventCase {
case mySegmentsUpdated
case myLargeSegmentsUpdated
case splitsUpdated
Expand All @@ -18,3 +18,17 @@ enum SplitInternalEvent {
case sdkReadyTimeoutReached
case splitKilledNotification
}

struct SplitInternalEvent: Equatable {
let type: SplitEventCase
let metadata: [String: Any]?

init(type: SplitEventCase, metadata: [String : Any]? = nil) {
self.type = type
self.metadata = metadata
}

static func == (lhs: SplitInternalEvent, rhs: SplitInternalEvent) -> Bool {
return lhs.type == rhs.type
}
}
4 changes: 2 additions & 2 deletions Split/Events/SplitEventTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import Foundation

protocol SplitEventTask {
var event: SplitEvent { get }
var event: SplitEventWithMetadata { get }
var runInBackground: Bool { get }
func takeQueue() -> DispatchQueue?
func run()
func run(_ data: Any?)
}
Loading
Loading