Skip to content

Commit 6a13830

Browse files
(chore): Update injection service to support global registered services (event processor) and (#249)
* make the binder an atomic property thus making sure that even if we did do a reinit that it would work * fix coveralls tag * add 'global' elements which don't have a sdk key * event handler is still per sdk key for now * fix tests
1 parent ddc14d0 commit 6a13830

File tree

8 files changed

+38
-24
lines changed

8 files changed

+38
-24
lines changed

OptimizelySDK/Extensions/OptimizelyClient+Extension.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ extension OptimizelyClient {
3535
// the decision service is also a singleton that will reCreate on re-initalize
3636
HandlerRegistryService.shared.registerBinding(binder: Binder<OPTDecisionService>(service: OPTDecisionService.self).singetlon().using(instance: decisionService).reInitializeStrategy(strategy: .reUse).sdkKey(key: sdkKey))
3737

38-
// An event dispatcher. We rely on the factory to create and mantain. Again, recreate on re-initalize.
38+
// An event dispatcher. We use a singleton and use the same Event dispatcher for all
39+
// projects. If you change the event dispatcher, you can potentially lose data if you
40+
// don't use the same backingstore.
3941
HandlerRegistryService.shared.registerBinding(binder: Binder<OPTEventDispatcher>(service: OPTEventDispatcher.self).singetlon().reInitializeStrategy(strategy: .reUse).using(instance: eventDispatcher).sdkKey(key: sdkKey))
4042

4143
// This is a singleton and might be a good candidate for reuse. The handler supports mulitple

OptimizelySDK/Optimizely/OptimizelyClient.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ open class OptimizelyClient: NSObject {
167167

168168
// call reinit on the services we know we are reinitializing.
169169

170-
for component in HandlerRegistryService.shared.lookupComponents(sdkKey: self.sdkKey) {
170+
for component in HandlerRegistryService.shared.lookupComponents(sdkKey: self.sdkKey) ?? [] {
171171
HandlerRegistryService.shared.reInitializeComponent(service: component, sdkKey: self.sdkKey)
172172
}
173173

OptimizelySDK/OptimizelyTests/OptimizelyTests-APIs/OptimizelyClientTests_DatafileHandler.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class OptimizelyClientTests_DatafileHandler: XCTestCase {
7676

7777
client.datafileHandler.stopAllUpdates()
7878

79-
HandlerRegistryService.shared.binders.removeAll()
79+
HandlerRegistryService.shared.binders.property?.removeAll()
8080

8181
// This is an example of a functional test case.
8282
// Use XCTAssert and related functions to verify your tests produce the correct results.

OptimizelySDK/OptimizelyTests/OptimizelyTests-APIs/OptimizelyClientTests_Others.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -265,24 +265,24 @@ class OptimizelyClientTests_Others: XCTestCase {
265265

266266
// all handlers before transfer
267267

268-
var handlersForCurrentSdkKey = HandlerRegistryService.shared.binders.keys.filter { $0.sdkKey == kNotRealSdkKey }
269-
let oldHandlersCount = handlersForCurrentSdkKey.count
268+
var handlersForCurrentSdkKey = HandlerRegistryService.shared.binders.property?.keys.filter { $0.sdkKey == kNotRealSdkKey }
269+
let oldHandlersCount = handlersForCurrentSdkKey?.count
270270

271271
// remove one of the handler to test nil-handlers
272272

273-
let testKey = handlersForCurrentSdkKey.filter { $0.service.contains("EventDispatcher") }.first!
274-
HandlerRegistryService.shared.binders[testKey] = nil
275-
273+
let testKey = handlersForCurrentSdkKey!.filter { $0.service.contains("EventDispatcher")}.first!
274+
HandlerRegistryService.shared.binders.property?[testKey] = nil
275+
276276
// this will replace config, which will transfer all handlers
277277

278278
try? optimizely.configSDK(datafile: OTUtils.loadJSONDatafile("api_datafile")!)
279279

280280
// nil handlers must be cleaned up when re-init
281281

282-
handlersForCurrentSdkKey = HandlerRegistryService.shared.binders.keys.filter { $0.sdkKey == kNotRealSdkKey }
283-
let newHandlersCount = handlersForCurrentSdkKey.count
282+
handlersForCurrentSdkKey = HandlerRegistryService.shared.binders.property?.keys.filter { $0.sdkKey == kNotRealSdkKey }
283+
let newHandlersCount = handlersForCurrentSdkKey?.count
284284

285-
XCTAssertEqual(newHandlersCount, oldHandlersCount - 1, "nil handlers should be filtered out")
285+
XCTAssertEqual(newHandlersCount, oldHandlersCount! - 1, "nil handlers should be filtered out")
286286
}
287287

288288

OptimizelySDK/OptimizelyTests/OptimizelyTests-Common/DatafileHandlerTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class DatafileHandlerTests: XCTestCase {
2020

2121
override func setUp() {
2222

23-
HandlerRegistryService.shared.binders.removeAll()
23+
HandlerRegistryService.shared.binders.property?.removeAll()
2424
// Put setup code here. This method is called before the invocation of each test method in the class.
2525
if let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
2626
if (!FileManager.default.fileExists(atPath: url.path)) {
@@ -37,7 +37,7 @@ class DatafileHandlerTests: XCTestCase {
3737

3838
override func tearDown() {
3939
// Put teardown code here. This method is called after the invocation of each test method in the class.
40-
HandlerRegistryService.shared.binders.removeAll()
40+
HandlerRegistryService.shared.binders.property?.removeAll()
4141
}
4242

4343
func testDatafileHandler() {

OptimizelySDK/OptimizelyTests/OptimizelyTests-Common/DecisionListenerTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,6 @@ class FakeDecisionService: DefaultDecisionService {
605605

606606
fileprivate extension HandlerRegistryService {
607607
func removeAll() {
608-
self.binders.removeAll()
608+
self.binders.property?.removeAll()
609609
}
610610
}

OptimizelySDK/Utils/HandlerRegistryService.swift

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,34 @@ class HandlerRegistryService {
2525
var sdkKey: String?
2626
}
2727

28-
var binders: [ServiceKey: BinderProtocol] = [ServiceKey: BinderProtocol]()
28+
var binders: AtomicProperty<[ServiceKey: BinderProtocol]> = {
29+
30+
var binders = AtomicProperty<[ServiceKey: BinderProtocol]>()
31+
binders.property = [ServiceKey: BinderProtocol]()
32+
return binders
33+
}()
2934

3035
private init() {
3136

3237
}
3338

3439
func registerBinding(binder: BinderProtocol) {
3540
let sk = ServiceKey(service: "\(type(of: binder.service))", sdkKey: binder.sdkKey)
36-
if binders[sk] != nil {
41+
if binders.property?[sk] != nil {
3742
} else {
38-
binders[sk] = binder
43+
binders.property?[sk] = binder
3944
}
4045
}
4146

4247
func injectComponent(service: Any, sdkKey: String? = nil, isReintialize: Bool=false) -> Any? {
4348
var result: Any?
44-
let sk = ServiceKey(service: "\(type(of: service))", sdkKey: sdkKey)
45-
if var binder = binders[sk] {
49+
// first look up global. Then look up if there is a local.
50+
let skLocal = ServiceKey(service: "\(type(of: service))", sdkKey: sdkKey)
51+
let skGlobal = ServiceKey(service: "\(type(of: service))", sdkKey: nil)
52+
53+
let binderToUse = binders.property?[skLocal] ?? binders.property?[skGlobal]
54+
55+
if var binder = binderToUse {
4656
if isReintialize && binder.strategy == .reCreate {
4757
binder.instance = binder.factory()
4858
result = binder.instance
@@ -61,12 +71,14 @@ class HandlerRegistryService {
6171
_ = injectComponent(service: service, sdkKey: sdkKey, isReintialize: true)
6272
}
6373

64-
func lookupComponents(sdkKey: String)->[Any] {
65-
let value = self.binders.keys
74+
func lookupComponents(sdkKey: String)->[Any]? {
75+
if let value = self.binders.property?.keys
6676
.filter({$0.sdkKey == sdkKey})
67-
.compactMap({ self.injectComponent(service: self.binders[$0]!.service, sdkKey: sdkKey) })
77+
.compactMap({ self.injectComponent(service: self.binders.property![$0]!.service, sdkKey: sdkKey) }) {
78+
return value
79+
}
6880

69-
return value
81+
return nil
7082
}
7183
}
7284

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
[![Apache 2.0](https://img.shields.io/github/license/nebula-plugins/gradle-extra-configurations-plugin.svg)](http://www.apache.org/licenses/LICENSE-2.0)
33
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/carthage/carthage)
44
[![Build Status](https://travis-ci.com/optimizely/swift-sdk.svg?branch=master)](https://travis-ci.com/optimizely/swift-sdk)
5-
[![Coverage Status](https://coveralls.io/repos/github/optimizely/swift-sdk/badge.svg)](https://coveralls.io/github/optimizely/swift-sdk)
5+
[![Coverage Status](https://coveralls.io/repos/github/optimizely/swift-sdk/badge.svg?branch=master)](https://coveralls.io/github/optimizely/swift-sdk?branch=master)
66

77
This repository houses the Swift SDK for use with Optimizely Full Stack and Optimizely Rollouts for Mobile and OTT.
88

0 commit comments

Comments
 (0)