Skip to content

Commit a457ff3

Browse files
authored
refactor: Change eventDispatch and notification to non-blocking (#265)
* refactor notification logic * fix for async notification + event dispatch
1 parent 266b556 commit a457ff3

21 files changed

+818
-424
lines changed

DemoSwiftApp/AppDelegate.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,15 +122,17 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
122122
func addListeners() {
123123
// notification listeners
124124

125-
_ = optimizely.notificationCenter.addDecisionNotificationListener(decisionListener: { (type, userId, attributes, decisionInfo) in
125+
let notificationCenter = optimizely.notificationCenter!
126+
127+
_ = notificationCenter.addDecisionNotificationListener(decisionListener: { (type, userId, attributes, decisionInfo) in
126128
print("Received decision notification: \(type) \(userId) \(String(describing: attributes)) \(decisionInfo)")
127129
})
128130

129-
_ = optimizely.notificationCenter.addTrackNotificationListener(trackListener: { (eventKey, userId, attributes, eventTags, event) in
131+
_ = notificationCenter.addTrackNotificationListener(trackListener: { (eventKey, userId, attributes, eventTags, event) in
130132
print("Received track notification: \(eventKey) \(userId) \(String(describing: attributes)) \(String(describing: eventTags)) \(event)")
131133
})
132134

133-
_ = optimizely.notificationCenter.addDatafileChangeNotificationListener(datafileListener: { (_) in
135+
_ = notificationCenter.addDatafileChangeNotificationListener(datafileListener: { (_) in
134136
DispatchQueue.main.async {
135137
#if os(iOS)
136138
if let controller = self.window?.rootViewController {

OptimizelySwiftSDK.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,8 @@
10151015
6E75195D22C520D500B2B157 /* OPTBucketer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E7516A522C520D400B2B157 /* OPTBucketer.swift */; };
10161016
6E75195E22C520D500B2B157 /* OPTBucketer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E7516A522C520D400B2B157 /* OPTBucketer.swift */; };
10171017
6E75195F22C520D500B2B157 /* OPTBucketer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E7516A522C520D400B2B157 /* OPTBucketer.swift */; };
1018+
6E981FC2232C363300FADDD6 /* DecisionListenerTests_Datafile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E981FC1232C363300FADDD6 /* DecisionListenerTests_Datafile.swift */; };
1019+
6E981FC3232C363300FADDD6 /* DecisionListenerTests_Datafile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E981FC1232C363300FADDD6 /* DecisionListenerTests_Datafile.swift */; };
10181020
6E9B114522C5486E00C22D81 /* MurmurTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E75197F22C5211100B2B157 /* MurmurTests.swift */; };
10191021
6E9B114622C5486E00C22D81 /* DecisionServiceTests_Experiments.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E75198022C5211100B2B157 /* DecisionServiceTests_Experiments.swift */; };
10201022
6E9B114722C5486E00C22D81 /* OptimizelyErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E75198122C5211100B2B157 /* OptimizelyErrorTests.swift */; };
@@ -1395,6 +1397,7 @@
13951397
6E7519C622C5211100B2B157 /* OptimizelyClientTests_ObjcOthers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OptimizelyClientTests_ObjcOthers.m; sourceTree = "<group>"; };
13961398
6E7519C822C5211100B2B157 /* OtherTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OtherTests.swift; sourceTree = "<group>"; };
13971399
6E7519C922C5211100B2B157 /* ThrowableConditionListTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThrowableConditionListTest.swift; sourceTree = "<group>"; };
1400+
6E981FC1232C363300FADDD6 /* DecisionListenerTests_Datafile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DecisionListenerTests_Datafile.swift; sourceTree = "<group>"; };
13981401
6EA425082218E41500B074B5 /* OptimizelyTests-Common-tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "OptimizelyTests-Common-tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
13991402
6EA4255B2218E58400B074B5 /* OptimizelyTests-DataModel-tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "OptimizelyTests-DataModel-tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
14001403
6EA4256A2218E60A00B074B5 /* OptimizelyTests-Common-iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "OptimizelyTests-Common-iOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1785,6 +1788,7 @@
17851788
6E75198E22C5211100B2B157 /* LoggerTests.swift */,
17861789
6E75198F22C5211100B2B157 /* BucketTests_BucketVariation.swift */,
17871790
6E75199022C5211100B2B157 /* DecisionListenerTests.swift */,
1791+
6E981FC1232C363300FADDD6 /* DecisionListenerTests_Datafile.swift */,
17881792
6E75199122C5211100B2B157 /* DecisionServiceTests_Features.swift */,
17891793
6E75199222C5211100B2B157 /* EventDispatcherTests.swift */,
17901794
6E75199322C5211100B2B157 /* BatchEventBuilderTests_Attributes.swift */,
@@ -2926,6 +2930,7 @@
29262930
6E9B116922C5487100C22D81 /* DefaultUserProfileServiceTests.swift in Sources */,
29272931
6E75192122C520D500B2B157 /* OPTNotificationCenter.swift in Sources */,
29282932
6E75170322C520D400B2B157 /* OptimizelyLogLevel.swift in Sources */,
2933+
6E981FC3232C363300FADDD6 /* DecisionListenerTests_Datafile.swift in Sources */,
29292934
6E9B116422C5487100C22D81 /* BucketTests_Others.swift in Sources */,
29302935
6E7518CD22C520D400B2B157 /* Audience.swift in Sources */,
29312936
6E9B117322C5487100C22D81 /* BatchEventBuilderTests_Attributes.swift in Sources */,
@@ -3109,6 +3114,7 @@
31093114
6E9B114F22C5486E00C22D81 /* DefaultUserProfileServiceTests.swift in Sources */,
31103115
6E7518F722C520D500B2B157 /* UserAttribute.swift in Sources */,
31113116
6E75174522C520D400B2B157 /* HandlerRegistryService.swift in Sources */,
3117+
6E981FC2232C363300FADDD6 /* DecisionListenerTests_Datafile.swift in Sources */,
31123118
6E9B114A22C5486E00C22D81 /* BucketTests_Others.swift in Sources */,
31133119
6E7517BF22C520D400B2B157 /* DefaultDatafileHandler.swift in Sources */,
31143120
6E9B115922C5486E00C22D81 /* BatchEventBuilderTests_Attributes.swift in Sources */,

OptimizelySwiftSDK.xcodeproj/xcshareddata/xcschemes/OptimizelySwiftSDK-tvOS.xcscheme

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
buildConfiguration = "Debug"
2727
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
2828
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29+
codeCoverageEnabled = "YES"
2930
shouldUseLaunchSchemeArgsEnv = "YES">
3031
<Testables>
3132
<TestableReference

Sources/Customization/DefaultEventDispatcher.swift

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,22 @@ open class DefaultEventDispatcher: BackgroundingCallbacks, OPTEventDispatcher {
2424

2525
static let sharedInstance = DefaultEventDispatcher()
2626

27-
// the max failure count. there is no backoff timer.
28-
static let MAX_FAILURE_COUNT = 3
29-
3027
// default timerInterval
3128
var timerInterval: TimeInterval
3229
// default batchSize.
3330
// attempt to send events in batches with batchSize number of events combined
3431
var batchSize: Int
3532
var maxQueueSize: Int
3633

34+
public struct DefaultValues {
35+
static public let batchSize = 10
36+
static public let timeInterval: TimeInterval = 60 // secs
37+
static public let maxQueueSize = 10000
38+
static let maxFailureCount = 3
39+
}
40+
41+
// the max failure count. there is no backoff timer.
42+
3743
lazy var logger = OPTLoggerFactory.getLogger()
3844
var backingStore: DataStoreType
3945
var backingStoreName: String
@@ -45,12 +51,10 @@ open class DefaultEventDispatcher: BackgroundingCallbacks, OPTEventDispatcher {
4551
// timer as a atomic property.
4652
var timer: AtomicProperty<Timer> = AtomicProperty<Timer>()
4753

48-
public struct DefaultValues {
49-
static public let batchSize = 10
50-
static public let timeInterval: TimeInterval = 60 // secs
51-
static public let maxQueueSize = 10000
52-
}
54+
var observerProjectId: NSObjectProtocol?
55+
var observerRevision: NSObjectProtocol?
5356

57+
5458
public init(batchSize: Int = DefaultValues.batchSize,
5559
backingStore: DataStoreType = .file,
5660
dataStoreName: String = "OPTEventQueue",
@@ -88,21 +92,11 @@ open class DefaultEventDispatcher: BackgroundingCallbacks, OPTEventDispatcher {
8892
deinit {
8993
stopTimer()
9094

95+
removeProjectChangeNotificationObservers()
96+
9197
unsubscribe()
9298
}
9399

94-
func addProjectChangeNotificationObservers() {
95-
NotificationCenter.default.addObserver(forName: .didReceiveOptimizelyProjectIdChange, object: nil, queue: nil) { (notif) in
96-
self.logger.d("Event flush triggered by datafile projectId change")
97-
self.flushEvents()
98-
}
99-
100-
NotificationCenter.default.addObserver(forName: .didReceiveOptimizelyRevisionChange, object: nil, queue: nil) { (notif) in
101-
self.logger.d("Event flush triggered by datafile revision change")
102-
self.flushEvents()
103-
}
104-
}
105-
106100
open func dispatchEvent(event: EventForDispatch, completionHandler: DispatchCompletionHandler?) {
107101
guard dataStore.count < maxQueueSize else {
108102
let error = OptimizelyError.eventDispatchFailed("EventQueue is full")
@@ -156,7 +150,7 @@ open class DefaultEventDispatcher: BackgroundingCallbacks, OPTEventDispatcher {
156150

157151
// we've exhuasted our failure count. Give up and try the next time a event
158152
// is queued or someone calls flush.
159-
if failureCount > DefaultEventDispatcher.MAX_FAILURE_COUNT {
153+
if failureCount > DefaultValues.maxFailureCount {
160154
self.logger.e(.eventSendRetyFailed(failureCount))
161155
break
162156
}
@@ -252,3 +246,30 @@ open class DefaultEventDispatcher: BackgroundingCallbacks, OPTEventDispatcher {
252246
timer.property = nil
253247
}
254248
}
249+
250+
// MARK: - Notification Observers
251+
252+
extension DefaultEventDispatcher {
253+
254+
func addProjectChangeNotificationObservers() {
255+
observerProjectId = NotificationCenter.default.addObserver(forName: .didReceiveOptimizelyProjectIdChange, object: nil, queue: nil) { [weak self] (notif) in
256+
self?.logger.d("Event flush triggered by datafile projectId change")
257+
self?.flushEvents()
258+
}
259+
260+
observerRevision = NotificationCenter.default.addObserver(forName: .didReceiveOptimizelyRevisionChange, object: nil, queue: nil) { [weak self] (notif) in
261+
self?.logger.d("Event flush triggered by datafile revision change")
262+
self?.flushEvents()
263+
}
264+
}
265+
266+
func removeProjectChangeNotificationObservers() {
267+
if let observer = observerProjectId {
268+
NotificationCenter.default.removeObserver(observer, name: .didReceiveOptimizelyProjectIdChange, object: nil)
269+
}
270+
if let observer = observerRevision {
271+
NotificationCenter.default.removeObserver(observer, name: .didReceiveOptimizelyRevisionChange, object: nil)
272+
}
273+
}
274+
275+
}

Sources/Implementation/DefaultNotificationCenter.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,4 @@ public class DefaultNotificationCenter: OPTNotificationCenter {
134134
}
135135
}
136136

137-
public func getArgumentsForDecisionListener(notificationType: String, userId: String, attributes: OptimizelyAttributes?) -> [Any?] {
138-
var args = [Any?]()
139-
args.append(notificationType)
140-
args.append(userId)
141-
args.append(attributes ?? OptimizelyAttributes())
142-
return args
143-
}
144-
145137
}

Sources/Optimizely/OptimizelyClient+ObjC.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ extension OptimizelyClient {
424424

425425
}
426426

427-
return ObjcCenter(notificationCenter: self.notificationCenter)
427+
return ObjcCenter(notificationCenter: self.notificationCenter!)
428428
}
429429
}
430430

0 commit comments

Comments
 (0)