Skip to content

Commit 1cd02a1

Browse files
feat: implement all EventEmitter handler types
1 parent cee34dd commit 1cd02a1

File tree

3 files changed

+166
-57
lines changed

3 files changed

+166
-57
lines changed

DevCycle/DevCycleClient.swift

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public class DevCycleClient {
148148
Log.error("Error getting config: \(error)", tags: ["setup"])
149149
self.cache = self.cacheService.load()
150150

151-
self.eventEmitter.emitError(error)
151+
self.eventEmitter.emit(EventEmitValues.error(error))
152152
requestErrored = true
153153
} else {
154154
if let config = config {
@@ -177,7 +177,7 @@ public class DevCycleClient {
177177

178178
self.initialized = true
179179
callback?(error)
180-
self.eventEmitter.emitInitialized(!requestErrored)
180+
self.eventEmitter.emit(EventEmitValues.initialized(!requestErrored))
181181

182182
self.setupSSEConnection()
183183
})
@@ -391,12 +391,18 @@ public class DevCycleClient {
391391
return self.config?.userConfig?.variables ?? [:]
392392
}
393393

394-
public func subscribe(_ handler: DevCycleEventHandlers) {
395-
self.eventEmitter.subscribe(handler)
394+
public func subscribe(_ handler: InitializedEventHandler) {
395+
self.eventEmitter.subscribe(EventHandlers.initialized(handler))
396+
}
397+
public func subscribe(_ handler: ErrorEventHandler) {
398+
self.eventEmitter.subscribe(EventHandlers.error(handler))
396399
}
397400

398-
public func unsubscribe(_ handler: DevCycleEventHandlers) {
399-
self.eventEmitter.unsubscribe(handler)
401+
public func unsubscribe(_ handler: InitializedEventHandler) {
402+
self.eventEmitter.unsubscribe(EventHandlers.initialized(handler))
403+
}
404+
public func unsubscribe(_ handler: ErrorEventHandler) {
405+
self.eventEmitter.unsubscribe(EventHandlers.error(handler))
400406
}
401407

402408
public func track(_ event: DevCycleEvent) {

DevCycle/Utils/EventEmitter.swift

Lines changed: 140 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,75 +3,169 @@
33
// DevCycle
44
//
55

6-
public typealias EventHandler = (Any?) -> Void
6+
public typealias VariableSet = [String: Variable]
77

8-
public typealias SubscribeErrorHandler = (Error) -> Void
9-
public typealias SubscribeInitializedHandler = (Bool) -> Void
8+
public typealias ErrorHandlerCallback = (Error) -> Void
9+
public typealias InitializedHandlerCallback = (Bool) -> Void
10+
public typealias ConfigUpdatedHandlerCallback = (VariableSet) -> Void
11+
public typealias VariableUpdatedHandlerCallback = (String, Variable) -> Void
12+
public typealias VariableEvaluatedHandlerCallback = (String, DVCVariable<Any>) -> Void
13+
public typealias FeatureUpdatedHandlerCallback = (String, Feature) -> Void
1014

11-
public struct ErrorHandler {
12-
// Had to add this index field, because I can't make this struct Equitable to do a equality comparison
13-
// because you can't compare anon function pointers... so it was either this or generate a UUID to compare.
14-
fileprivate var index: Int?
15-
var handler: SubscribeErrorHandler
15+
public class BaseHandler<T>: Equatable {
16+
public static func == (lhs: BaseHandler, rhs: BaseHandler) -> Bool {
17+
return lhs === rhs
18+
}
19+
20+
let callback: T
1621

17-
public init(_ handler: @escaping SubscribeErrorHandler) {
18-
self.handler = handler
22+
public init(_ handler: T) {
23+
self.callback = handler
1924
}
2025
}
2126

22-
public struct InitializedHandler {
23-
fileprivate var index: Int?
24-
var handler: SubscribeInitializedHandler
25-
26-
public init(_ handler: @escaping SubscribeInitializedHandler) {
27-
self.handler = handler
28-
}
27+
public typealias ErrorEventHandler = BaseHandler<ErrorHandlerCallback>
28+
public typealias InitializedEventHandler = BaseHandler<InitializedHandlerCallback>
29+
public typealias ConfigUpdatedEventHandler = BaseHandler<ConfigUpdatedHandlerCallback>
30+
public typealias VariableUpdatedHandler = BaseHandler<VariableUpdatedHandlerCallback>
31+
public typealias VariableEvaluatedHandler = BaseHandler<VariableEvaluatedHandlerCallback>
32+
public typealias FeatureUpdatedHandler = BaseHandler<FeatureUpdatedHandlerCallback>
33+
34+
enum EventHandlers {
35+
case error(ErrorEventHandler)
36+
case initialized(InitializedEventHandler)
37+
case configUpdated(ConfigUpdatedEventHandler)
38+
case variableUpdated(String?, VariableUpdatedHandler)
39+
case variableEvaluated(String?, VariableEvaluatedHandler)
40+
case featureUpdated(String?, FeatureUpdatedHandler)
2941
}
3042

31-
public enum DevCycleEventHandlers {
32-
case error(ErrorHandler)
33-
case initialized(InitializedHandler)
43+
enum EventEmitValues {
44+
case error(Error)
45+
case initialized(Bool)
46+
case configUpdated(VariableSet)
47+
case variableUpdated(String, Variable)
48+
case variableEvaluated(String, DVCVariable<Any>)
49+
case featureUpdated(String, Feature)
3450
}
3551

3652
class EventEmitter {
37-
var errorHandlers: [ErrorHandler] = []
38-
var initHandlers: [InitializedHandler] = []
39-
40-
func subscribe(_ handler: DevCycleEventHandlers) {
53+
var errorHandlers: [ErrorEventHandler] = []
54+
var initHandlers: [InitializedEventHandler] = []
55+
var configUpdatedHandlers: [ConfigUpdatedEventHandler] = []
56+
var variableUpdatedHandlers: [String : [VariableUpdatedHandler]] = [:]
57+
var allVariableUpdatedHandlers: [VariableUpdatedHandler] = []
58+
var variableEvaluatedHandlers: [String : [VariableEvaluatedHandler]] = [:]
59+
var allVariableEvaluatedHandlers: [VariableEvaluatedHandler] = []
60+
var featureUpdatedHandlers: [String : [FeatureUpdatedHandler]] = [:]
61+
var allFeatureUpdatedHandlers: [FeatureUpdatedHandler] = []
62+
63+
func subscribe(_ handler: EventHandlers) {
4164
switch handler {
42-
case .error(var errorHandler):
43-
self.errorHandlers.append(errorHandler)
44-
errorHandler.index = self.errorHandlers.count-1
45-
break
46-
case .initialized(var initHandler):
47-
self.initHandlers.append(initHandler)
48-
initHandler.index = self.initHandlers.count-1
49-
break
65+
case .error(let handler):
66+
self.errorHandlers.append(handler)
67+
case .initialized(let handler):
68+
self.initHandlers.append(handler)
69+
case .configUpdated(let handler):
70+
self.configUpdatedHandlers.append(handler)
71+
case .variableUpdated(let key, let handler):
72+
if let key = key {
73+
subscribeByKey(key, handler: handler, handlersByKey: &self.variableUpdatedHandlers)
74+
} else {
75+
self.allVariableUpdatedHandlers.append(handler)
76+
}
77+
case .variableEvaluated(let key, let handler):
78+
if let key = key {
79+
subscribeByKey(key, handler: handler, handlersByKey: &self.variableEvaluatedHandlers)
80+
} else {
81+
self.allVariableEvaluatedHandlers.append(handler)
82+
}
83+
case .featureUpdated(let key, let handler):
84+
if let key = key {
85+
subscribeByKey(key, handler: handler, handlersByKey: &self.featureUpdatedHandlers)
86+
} else {
87+
self.allFeatureUpdatedHandlers.append(handler)
88+
}
89+
}
90+
}
91+
92+
private func subscribeByKey<T>(_ key: String, handler: T, handlersByKey: inout [String: [T]]) {
93+
if var handlers = handlersByKey[key] {
94+
handlers.append(handler)
95+
} else {
96+
handlersByKey[key] = [handler]
5097
}
5198
}
5299

53-
func unsubscribe(_ handler: DevCycleEventHandlers) {
100+
func unsubscribe(_ handler: EventHandlers) {
54101
switch handler {
55-
case .error(let errorHandler):
56-
if let index = errorHandler.index {
57-
self.errorHandlers.remove(at: index)
102+
case .error(let handler):
103+
unsubscribeHandler(handler, handlers: &self.errorHandlers)
104+
case .initialized(let handler):
105+
unsubscribeHandler(handler, handlers: &self.initHandlers)
106+
case .configUpdated(let handler):
107+
unsubscribeHandler(handler, handlers: &self.configUpdatedHandlers)
108+
case .variableUpdated(let key, let handler):
109+
if let key = key {
110+
unsubscribeHandlerByKey(key, handler: handler, handlersByKey: &self.variableUpdatedHandlers)
111+
} else {
112+
unsubscribeHandler(handler, handlers: &self.allVariableUpdatedHandlers)
113+
}
114+
case .variableEvaluated(let key, let handler):
115+
if let key = key {
116+
unsubscribeHandlerByKey(key, handler: handler, handlersByKey: &self.variableEvaluatedHandlers)
117+
} else {
118+
unsubscribeHandler(handler, handlers: &self.allVariableEvaluatedHandlers)
58119
}
59-
break
60-
case .initialized(let initHandler):
61-
if let index = initHandler.index {
62-
self.initHandlers.remove(at: index)
120+
case .featureUpdated(let key, let handler):
121+
if let key = key {
122+
unsubscribeHandlerByKey(key, handler: handler, handlersByKey: &self.featureUpdatedHandlers)
123+
} else {
124+
unsubscribeHandler(handler, handlers: &self.allVariableEvaluatedHandlers)
63125
}
64-
break
65126
}
66127
}
67128

68-
func emitError(_ err: Error) {
69-
self.errorHandlers.forEach { errHandler in errHandler.handler(err) }
129+
private func unsubscribeHandlerByKey<T: Equatable>(_ key: String, handler: T, handlersByKey: inout [String: [T]]) {
130+
if var handlers = handlersByKey[key] {
131+
unsubscribeHandler(handler, handlers: &handlers)
132+
}
70133
}
71134

72-
func emitInitialized(_ success: Bool) {
73-
self.initHandlers.forEach { initSub in
74-
initSub.handler(success)
135+
private func unsubscribeHandler<T: Equatable>(_ handler: T, handlers: inout [T]) {
136+
if let index = handlers.firstIndex(where: { $0 == handler }) {
137+
handlers.remove(at: index)
75138
}
76139
}
140+
141+
func emit(_ emitValues: EventEmitValues) {
142+
switch emitValues {
143+
case .error(let err):
144+
self.errorHandlers.forEach { handler in handler.callback(err) }
145+
case .initialized(let initialized):
146+
self.initHandlers.forEach { handler in handler.callback(initialized) }
147+
case .configUpdated(let variableSet):
148+
self.configUpdatedHandlers.forEach { handler in handler.callback(variableSet) }
149+
case .variableUpdated(let key, let variable):
150+
if let handlers = self.variableUpdatedHandlers[key] {
151+
handlers.forEach { handler in handler.callback(key, variable) }
152+
}
153+
case .variableEvaluated(let key, let variable):
154+
if let handlers = self.variableEvaluatedHandlers[key] {
155+
handlers.forEach { handler in handler.callback(key, variable) }
156+
}
157+
allVariableEvaluatedHandlers.forEach { handler in handler.callback(key, variable) }
158+
case .featureUpdated(let key, let feature):
159+
if let handlers = self.featureUpdatedHandlers[key] {
160+
handlers.forEach { handler in handler.callback(key, feature) }
161+
}
162+
allFeatureUpdatedHandlers.forEach { handler in handler.callback(key, feature) }
163+
}
164+
}
165+
166+
// private func emitValuesByKey<T: BaseHandler<Any>, V>(_ key: String, variable: V, handlersByKey: [String : [T]]) {
167+
// if let handlers = handlersByKey[key] {
168+
// handlers.forEach { handler in handler.callback(key, variable) }
169+
// }
170+
// }
77171
}

Examples/DevCycle-iOS-Example-App-Swift/DevCycle-iOS-Example-App-Swift/DevCycleManager.swift

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,21 @@ class DevCycleManager {
3131
}
3232
self.client = client
3333

34-
35-
client.subscribe(DevCycleEventHandlers.error(ErrorHandler { error in
34+
let errHandler = ErrorEventHandler { error in
3635
print("DevCycle Error: \(error.localizedDescription)")
37-
}))
38-
client.subscribe(DevCycleEventHandlers.initialized(InitializedHandler { success in
36+
}
37+
client.subscribe(errHandler)
38+
39+
let initHandler = InitializedEventHandler { success in
3940
print("DevCycle Initialized: \(success) from subscription")
40-
}))
41+
}
42+
client.subscribe(initHandler)
43+
44+
45+
Timer.scheduledTimer(withTimeInterval: TimeInterval(15), repeats: false) { timer in
46+
print("Cleanup handlers")
47+
client.unsubscribe(errHandler)
48+
client.unsubscribe(initHandler)
49+
}
4150
}
4251
}

0 commit comments

Comments
 (0)