@@ -28,6 +28,8 @@ public typealias IdentifyCompletedHandler = (Error?, [String: Variable]?) -> Voi
2828public typealias FlushCompletedHandler = ( Error ? ) -> Void
2929public typealias CloseCompletedHandler = ( ) -> Void
3030
31+ internal typealias VariableInstanceDic = [ String : NSMapTable < AnyObject , AnyObject > ]
32+
3133
3234public class DevCycleClient {
3335 var sdkKey : String ?
@@ -51,7 +53,7 @@ public class DevCycleClient {
5153 private var flushTimer : Timer ?
5254 private var closed : Bool = false
5355 private var inactivityWorkItem : DispatchWorkItem ?
54- private var variableInstanceDictonary = [ String : NSMapTable < AnyObject , AnyObject > ] ( )
56+ private var variableInstanceDictonary = VariableInstanceDic ( )
5557 private var isConfigCached : Bool = false
5658 private var disableAutomaticEventLogging : Bool = false
5759 private var disableCustomEventLogging : Bool = false
@@ -154,21 +156,17 @@ public class DevCycleClient {
154156 if let config = config {
155157 Log . debug ( " Config: \( config) " , tags: [ " setup " ] )
156158 }
157- self . config? . userConfig = config
158- self . isConfigCached = false
159-
160- self . cacheUser ( user: user)
159+ self . setUserConfig ( config)
160+ self . cacheUser ( user)
161161
162- if ( self . checkIfEdgeDBEnabled ( config: config!, enableEdgeDB: self . enableEdgeDB) ) {
163- if ( !( user. isAnonymous ?? false ) ) {
164- self . service? . saveEntity ( user: user, completion: { data, response, error in
165- if error != nil {
166- Log . error ( " Error saving user entity for \( user) . Error: \( String ( describing: error) ) " )
167- } else {
168- Log . info ( " Saved user entity " )
169- }
170- } )
171- }
162+ if ( self . checkIfEdgeDBEnabled ( config: config!, enableEdgeDB: self . enableEdgeDB) && !( user. isAnonymous ?? false ) ) {
163+ self . service? . saveEntity ( user: user, completion: { data, response, error in
164+ if error != nil {
165+ Log . error ( " Error saving user entity for \( user) . Error: \( String ( describing: error) ) " )
166+ } else {
167+ Log . info ( " Saved user entity " )
168+ }
169+ } )
172170 }
173171 }
174172
@@ -216,17 +214,40 @@ public class DevCycleClient {
216214 let extraParams = RequestParams ( sse: sse, lastModified: lastModified, etag: etag)
217215 self . service? . getConfig ( user: lastIdentifiedUser, enableEdgeDB: self . enableEdgeDB, extraParams: extraParams, completion: { [ weak self] config, error in
218216 guard let self = self else { return }
217+
219218 if let error = error {
220219 Log . error ( " Error getting config: \( error) " , tags: [ " refetchConfig " ] )
220+ self . eventEmitter. emit ( EventEmitValues . error ( error) )
221221 } else {
222- self . config? . userConfig = config
223- self . isConfigCached = false
222+ self . setUserConfig ( config)
224223 }
225224 } )
226225 }
227226 }
227+
228+ private func setUserConfig( _ config: UserConfig ? ) {
229+ let oldConfig = self . config
230+ self . config? . userConfig = config
231+ self . isConfigCached = false
232+
233+ if let config = config {
234+ self . eventEmitter. emitFeatureUpdates (
235+ oldFeatures: oldConfig? . userConfig? . features,
236+ newFeatures: config. features
237+ )
238+ self . eventEmitter. emitVariableUpdates (
239+ oldVariables: oldConfig? . userConfig? . variables,
240+ newVariables: config. variables,
241+ variableInstanceDic: self . variableInstanceDictonary
242+ )
243+
244+ if oldConfig == nil || config. etag != oldConfig? . userConfig? . etag {
245+ self . eventEmitter. emit ( EventEmitValues . configUpdated ( config. variables) )
246+ }
247+ }
248+ }
228249
229- private func cacheUser( user: DevCycleUser ) {
250+ private func cacheUser( _ user: DevCycleUser ) {
230251 self . cacheService. save ( user: user)
231252 if user. isAnonymous == true , let userId = user. userId {
232253 self . cacheService. setAnonUserId ( anonUserId: userId)
@@ -274,9 +295,10 @@ public class DevCycleClient {
274295 return variable ( key: key, defaultValue: defaultValue) . value
275296 }
276297
298+ private let regex = try ? NSRegularExpression ( pattern: " .*[^a-z0-9( \\ -)(_)].* " )
299+
277300 public func variable< T> ( key: String , defaultValue: T ) -> DVCVariable < T > {
278- let regex = try ? NSRegularExpression ( pattern: " .*[^a-z0-9( \\ -)(_)].* " )
279- if ( regex? . firstMatch ( in: key, range: NSMakeRange ( 0 , key. count) ) != nil ) {
301+ if ( self . regex? . firstMatch ( in: key, range: NSMakeRange ( 0 , key. count) ) != nil ) {
280302 Log . error ( " The variable key \( key) is invalid. It must contain only lowercase letters, numbers, hyphens and underscores. The default value will always be returned for this call. " )
281303 return DVCVariable (
282304 key: key,
@@ -292,6 +314,7 @@ public class DevCycleClient {
292314 if ( self . variableInstanceDictonary [ key] == nil ) {
293315 self . variableInstanceDictonary [ key] = NSMapTable < AnyObject , AnyObject > ( valueOptions: . weakMemory)
294316 }
317+
295318 if let variableFromDictionary = self . variableInstanceDictonary [ key] ? . object ( forKey: defaultValue as AnyObject ) as? DVCVariable < T > {
296319 variable = variableFromDictionary
297320 } else {
@@ -307,15 +330,16 @@ public class DevCycleClient {
307330 evalReason: nil
308331 )
309332 }
310- self . variableInstanceDictonary [ key] ? . setObject ( variable, forKey: defaultValue as AnyObject )
333+
334+ self . variableInstanceDictonary [ key] ? . setObject ( variable, forKey: defaultValue as AnyObject )
311335 }
312336
313- if ( !self . closed) {
314- if ( !self . disableAutomaticEventLogging) {
315- self . eventQueue. updateAggregateEvents ( variableKey: variable. key, variableIsDefaulted: variable. isDefaulted)
316- }
337+ if ( !self . closed && !self . disableAutomaticEventLogging) {
338+ self . eventQueue. updateAggregateEvents ( variableKey: variable. key, variableIsDefaulted: variable. isDefaulted)
317339 }
318340
341+
342+ self . eventEmitter. emit ( EventEmitValues . variableEvaluated ( variable. key, variable) )
319343 return variable
320344 }
321345 }
@@ -336,18 +360,19 @@ public class DevCycleClient {
336360
337361 self . service? . getConfig ( user: updateUser, enableEdgeDB: self . enableEdgeDB, extraParams: nil , completion: { [ weak self] config, error in
338362 guard let self = self else { return }
363+
339364 if let error = error {
340365 Log . error ( " Error getting config: \( error) " , tags: [ " identify " ] )
341366 self . cache = self . cacheService. load ( )
367+ self . eventEmitter. emit ( EventEmitValues . error ( error) )
342368 } else {
343369 if let config = config {
344370 Log . debug ( " Config: \( config) " , tags: [ " identify " ] )
345371 }
346- self . config? . userConfig = config
347- self . isConfigCached = false
372+ self . setUserConfig ( config)
348373 }
349374 self . user = user
350- self . cacheUser ( user: user )
375+ self . cacheUser ( user)
351376 callback ? ( error, config? . variables)
352377 } )
353378 }
@@ -364,21 +389,23 @@ public class DevCycleClient {
364389
365390 self . service? . getConfig ( user: anonUser, enableEdgeDB: self . enableEdgeDB, extraParams: nil , completion: { [ weak self] config, error in
366391 guard let self = self else { return }
367- guard error == nil else {
392+
393+ if let error = error {
368394 if let previousAnonUserId = cachedAnonUserId {
369395 self . cacheService. setAnonUserId ( anonUserId: previousAnonUserId)
370396 }
397+ self . eventEmitter. emit ( EventEmitValues . error ( error) )
371398 callback ? ( error, nil )
372399 return
373400 }
374401
375402 if let config = config {
376403 Log . debug ( " Config: \( config) " , tags: [ " reset " ] )
404+ self . eventEmitter. emit ( EventEmitValues . configUpdated ( config. variables) )
377405 }
378- self . config? . userConfig = config
379- self . isConfigCached = false
406+ self . setUserConfig ( config)
380407 self . user = anonUser
381- self . cacheUser ( user : anonUser)
408+ self . cacheUser ( anonUser)
382409 callback ? ( error, config? . variables)
383410 } )
384411 }
0 commit comments