@@ -3,12 +3,26 @@ import SwiftEventBus
33
44@available ( macOS 10 . 15 , * )
55public class UnleashClientBase {
6- public var context : Context
7- var timer : Timer ?
6+ private var _context : Context
7+
8+ public var context : Context {
9+ get {
10+ lock. lock ( )
11+ let value = self . _context
12+ lock. unlock ( )
13+ return value
14+ }
15+ set {
16+ lock. lock ( )
17+ self . _context = newValue
18+ lock. unlock ( )
19+ }
20+ }
21+ var timer : DispatchSourceTimer ?
822 var poller : Poller
923 var metrics : Metrics
1024 var connectionId : UUID
11- private let queue = DispatchQueue ( label : " com.unleash.clientbase " , attributes : . concurrent )
25+ private let lock = NSLock ( )
1226
1327 public init (
1428 unleashUrl: String ,
@@ -63,9 +77,9 @@ public class UnleashClientBase {
6377 self . metrics = Metrics ( appName: appName, metricsInterval: Double ( metricsInterval) , clock: { return Date ( ) } , disableMetrics: disableMetrics, poster: urlSessionPoster, url: url, clientKey: clientKey, customHeaders: customHeaders, connectionId: connectionId)
6478 }
6579
66- self . context = Context ( appName: appName, environment: environment, sessionId: String ( Int . random ( in: 0 ..< 1_000_000_000 ) ) )
80+ self . _context = Context ( appName: appName, environment: environment, sessionId: String ( Int . random ( in: 0 ..< 1_000_000_000 ) ) )
6781 if let providedContext = context {
68- self . context = self . calculateContext ( context: providedContext)
82+ self . _context = self . calculateContext ( context: providedContext)
6983 }
7084 }
7185
@@ -75,13 +89,13 @@ public class UnleashClientBase {
7589 completionHandler: ( ( PollerError ? ) -> Void ) ? = nil
7690 ) -> Void {
7791 Printer . showPrintStatements = printToConsole
78- self . stopPolling ( )
79- poller. start (
80- bootstrapping: bootstrap. toggles,
81- context: context,
82- completionHandler: completionHandler
83- )
84- metrics. start ( )
92+ self . stopPolling ( )
93+ poller. start (
94+ bootstrapping: bootstrap. toggles,
95+ context: context,
96+ completionHandler: completionHandler
97+ )
98+ metrics. start ( )
8599 }
86100
87101 private func stopPolling( ) -> Void {
@@ -90,55 +104,55 @@ public class UnleashClientBase {
90104 }
91105
92106 public func stop( ) -> Void {
93- self . stopPolling ( ) ;
107+ self . stopPolling ( )
108+ lock. lock ( )
109+ timer? . cancel ( )
110+ timer = nil
111+ lock. unlock ( )
94112 UnleashEvent . allCases. forEach { self . unsubscribe ( $0) }
95113 }
96114
97115 public func isEnabled( name: String ) -> Bool {
98- return queue. sync {
99- let toggle = poller. getFeature ( name: name)
100- let enabled = toggle? . enabled ?? false
101-
102- metrics. count ( name: name, enabled: enabled)
103-
104- if let toggle = toggle, toggle. impressionData {
105- // Dispatch impression event to background queue
106- DispatchQueue . global ( ) . async {
107- SwiftEventBus . post ( " impression " , sender: ImpressionEvent (
108- toggleName: name,
109- enabled: enabled,
110- context: self . context
111- ) )
112- }
113- }
116+ let toggle = poller. getFeature ( name: name)
117+ let enabled = toggle? . enabled ?? false
118+ let contextSnapshot = self . context
114119
115- return enabled
120+ metrics. count ( name: name, enabled: enabled)
121+
122+ if let toggle = toggle, toggle. impressionData {
123+ DispatchQueue . global ( qos: . background) . async {
124+ SwiftEventBus . post ( " impression " , sender: ImpressionEvent (
125+ toggleName: name,
126+ enabled: enabled,
127+ context: contextSnapshot
128+ ) )
129+ }
116130 }
131+
132+ return enabled
117133 }
118134
119135 public func getVariant( name: String ) -> Variant {
120- return queue. sync {
121- let toggle = poller. getFeature ( name: name)
122- let variant = toggle? . variant ?? . defaultDisabled
123- let enabled = toggle? . enabled ?? false
124-
125- metrics. count ( name: name, enabled: enabled)
126- metrics. countVariant ( name: name, variant: variant. name)
127-
128- if let toggle = toggle, toggle. impressionData {
129- // Dispatch impression event to background queue
130- DispatchQueue . global ( ) . async {
131- SwiftEventBus . post ( " impression " , sender: ImpressionEvent (
132- toggleName: name,
133- enabled: enabled,
134- variant: variant,
135- context: self . context
136- ) )
137- }
138- }
136+ let toggle = poller. getFeature ( name: name)
137+ let variant = toggle? . variant ?? . defaultDisabled
138+ let enabled = toggle? . enabled ?? false
139+ let contextSnapshot = self . context
140+
141+ metrics. count ( name: name, enabled: enabled)
142+ metrics. countVariant ( name: name, variant: variant. name)
139143
140- return variant
144+ if let toggle = toggle, toggle. impressionData {
145+ DispatchQueue . global ( qos: . background) . async {
146+ SwiftEventBus . post ( " impression " , sender: ImpressionEvent (
147+ toggleName: name,
148+ enabled: enabled,
149+ variant: variant,
150+ context: contextSnapshot
151+ ) )
152+ }
141153 }
154+
155+ return variant
142156 }
143157
144158 public func subscribe( name: String , callback: @escaping ( ) -> Void ) {
@@ -185,15 +199,16 @@ public class UnleashClientBase {
185199 unsubscribe ( name: event. rawValue)
186200 }
187201
188- public func updateContext( context: [ String : String ] , properties: [ String : String ] ? = nil , completionHandler: ( ( PollerError ? ) -> Void ) ? = nil ) {
189- if Thread . isMainThread {
190- self . context = self . calculateContext ( context: context, properties: properties)
202+ public func updateContext(
203+ context: [ String : String ] ,
204+ properties: [ String : String ] ? = nil ,
205+ completionHandler: ( ( PollerError ? ) -> Void ) ? = nil
206+ ) {
207+ let newContext = self . calculateContext ( context: context, properties: properties)
208+ self . context = newContext
209+
210+ DispatchQueue . global ( qos: . background) . async {
191211 self . start ( Printer . showPrintStatements, completionHandler: completionHandler)
192- } else {
193- DispatchQueue . main. async {
194- self . context = self . calculateContext ( context: context, properties: properties)
195- self . start ( Printer . showPrintStatements, completionHandler: completionHandler)
196- }
197212 }
198213 }
199214
@@ -211,11 +226,13 @@ public class UnleashClientBase {
211226 newProperties [ key] = value
212227 }
213228
214- let sessionId = context [ " sessionId " ] ?? self . context. sessionId;
215-
229+ let currentContext = self . context
230+
231+ let sessionId = context [ " sessionId " ] ?? currentContext. sessionId;
232+
216233 let newContext = Context (
217- appName: self . context . appName,
218- environment: self . context . environment,
234+ appName: currentContext . appName,
235+ environment: currentContext . environment,
219236 userId: context [ " userId " ] ,
220237 sessionId: sessionId,
221238 remoteAddress: context [ " remoteAddress " ] ,
@@ -243,7 +260,7 @@ public class UnleashClient: UnleashClientBase, ObservableObject {
243260 }
244261 }
245262 }
246-
263+
247264 @MainActor
248265 public func updateContext(
249266 context: [ String : String ] ,
0 commit comments