Skip to content

Commit 8148e32

Browse files
authored
[FSSDK-9062] add more support for sendOdpEvent error handling (#486)
Add more support for sendOdpEvent error handling: - empty string for action: throws odpInvalidAction - nil/empty for type: use default "fullstack" type - replace identifiers alias (fs-user-id/FS-USER-ID/FS_USER_ID) with fs_user_id
1 parent 8b43600 commit 8148e32

File tree

14 files changed

+100
-37
lines changed

14 files changed

+100
-37
lines changed

.github/workflows/swift.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ jobs:
4747
4848
unittests:
4949
if: "${{ github.event.inputs.PREP == '' && github.event.inputs.RELEASE == '' }}"
50-
uses: optimizely/swift-sdk/.github/workflows/unit_tests.yml@master
50+
##uses: optimizely/swift-sdk/.github/workflows/unit_tests.yml@master
51+
uses: optimizely/swift-sdk/.github/workflows/unit_tests.yml@jae/empty-odp-action
5152

5253
prepare_for_release:
5354
runs-on: macos-12

.github/workflows/unit_tests.yml

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ env:
77

88
jobs:
99
unittests:
10-
runs-on: macos-11
10+
runs-on: macos-12
1111
strategy:
1212
fail-fast: false
1313
matrix:
@@ -16,42 +16,43 @@ jobs:
1616
# - each xcode version has own simulator os versions.
1717
# - so to run tests with the target simulator, we have to find a proper xcode version pre-installed and support the target simulator os version.
1818
# also, the xcode version (simulator_xcode_version) and simulator os versions (os) are moving target. We have to change these time to time.
19+
# - see "https://github.com/actions/runner-images/blob/main/images/macos/macos-11-Readme.md" for installed macOS, xcode and simulator versions.
1920
include:
20-
- os: 15.2
21-
device: "iPhone 11"
21+
- os: 16.1
22+
device: "iPhone 12"
2223
scheme: "OptimizelySwiftSDK-iOS"
2324
test_sdk: "iphonesimulator"
2425
platform: "iOS Simulator"
2526
os_type: "iOS"
26-
simulator_xcode_version: 13.2
27-
- os: 14.4
28-
device: "iPhone 8"
27+
simulator_xcode_version: 14.1
28+
- os: 15.5
29+
device: "iPhone 12"
2930
scheme: "OptimizelySwiftSDK-iOS"
3031
test_sdk: "iphonesimulator"
3132
platform: "iOS Simulator"
3233
os_type: "iOS"
33-
simulator_xcode_version: 12.4
34-
- os: 13.7
34+
simulator_xcode_version: 13.4.1
35+
- os: 15.5
3536
# good to have tests with older OS versions, but it looks like this is min OS+xcode versions supported by github actions
36-
device: "iPad Air (3rd generation)"
37+
device: "iPad Air (4th generation)"
3738
scheme: "OptimizelySwiftSDK-iOS"
3839
test_sdk: "iphonesimulator"
3940
platform: "iOS Simulator"
4041
os_type: "iOS"
41-
simulator_xcode_version: 11.7
42-
- os: 13.4
43-
device: "Apple TV 4K"
42+
simulator_xcode_version: 13.4.1
43+
- os: 16.1
44+
device: "Apple TV"
4445
scheme: "OptimizelySwiftSDK-tvOS"
4546
test_sdk: "appletvsimulator"
4647
platform: "tvOS Simulator"
4748
os_type: "tvOS"
48-
simulator_xcode_version: 11.7
49+
simulator_xcode_version: 14.1
4950
steps:
5051
- uses: actions/checkout@v3
5152
- uses: maxim-lobanov/setup-xcode@v1
5253
with:
5354
# macos version and supported simulator_xcode_versions are all related to this xcode_version, so be careful when you upgrade this.
54-
xcode-version: 12.4
55+
xcode-version: 14.1
5556
- name: set SDK Branch if PR
5657
if: ${{ github.event_name == 'pull_request' }}
5758
run: |
@@ -71,16 +72,16 @@ jobs:
7172
NAME: ${{ matrix.device }}
7273
run: |
7374
gem install coveralls-lcov
74-
gem install cocoapods -v '1.9.3'
75+
gem install cocoapods -v '1.11.3'
7576
pod repo update
7677
pod install
7778
HOMEBREW_NO_INSTALL_CLEANUP=true brew update && brew install jq
7879
7980
# github actions are very poor in supporting iOS simulators:
8081
# - to find pre-installed xcode version, run this:
81-
# > ls /Applications/
82+
##ls /Applications/
8283
# - to find supported simulator os versions, run this (and find simulator with non-error "datapath")
83-
# > xcrun simctl list --json devices
84+
##xcrun simctl list --json devices
8485
8586
# switch to the target xcode version
8687
sudo xcode-select -switch /Applications/Xcode_$SIMULATOR_XCODE_VERSION.app

Scripts/test_all.sh

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
1+
12
#!/bin/bash -e
23
# Since github actions only provides limit simulators with each xcode, we need to link simulators from other versions of xcode to be used by current xcode.
34
# We must use old simulators with current xcode since older xcode versions do not support swift 5 which is required by Swift SDK.
45
# More about XCode and its compatible simulators can be found here: https://github.com/actions/virtual-environments/blob/main/images/macos/macos-10.15-Readme.md
56
# https://github.com/actions/virtual-environments/issues/551
67

7-
deviceModels=("iPhone SE" "iPhone 8" "iPhone 11" "Apple TV" "Apple TV" "Apple TV 4K")
8-
osVersions=("12.4" "13.3" "14.4" "12.4" "13.3" "14.3")
9-
xcodeVersions=("10.3" "11.3.1" "12.4" "10.3" "11.3.1" "12.4")
10-
platforms=("iOS" "iOS" "iOS" "tvOS" "tvOS" "tvOS")
11-
testSdks=("iphonesimulator" "iphonesimulator" "iphonesimulator" "appletvsimulator" "appletvsimulator" "appletvsimulator")
8+
deviceModels=("iPhone 12" "iPhone 8" "iPad Air (4th generation)" "Apple TV")
9+
osVersions=("16.0" "14.4" "15.0" "16.0")
10+
xcodeVersions=("14.3" "14.3" "14.3" "14.3")
11+
platforms=("iOS" "iOS" "iOS" "tvOS")
12+
testSdks=("iphonesimulator" "iphonesimulator" "iphonesimulator" "appletvsimulator")
1213

1314
for i in "${!deviceModels[@]}"; do
1415
export PLATFORM="${platforms[$i]} Simulator"
1516
export OS="${osVersions[$i]}"
1617
export NAME="${deviceModels[$i]}"
1718
export OS_TYPE="${platforms[$i]}"
1819
export SIMULATOR_XCODE_VERSION="${xcodeVersions[$i]}"
20+
1921
Scripts/prepare_simulator.sh
2022
echo "Testing OptimizelySwiftSDK-${platforms[$i]} (${deviceModels[$i]},OS=${osVersions[$i]})"
23+
2124
xcrun xcodebuild -workspace OptimizelySwiftSDK.xcworkspace -scheme "OptimizelySwiftSDK-${platforms[$i]}" -sdk "${testSdks[$i]}" -destination "platform=${platforms[$i]} Simulator,name=${deviceModels[$i]},OS=${osVersions[$i]}" test
2225
done

Sources/Extensions/OptimizelyClient+Extension.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ extension OptimizelyClient {
5151
/// - eventDispatcher: custom EventDispatcher (optional)
5252
/// - datafileHandler: custom datafile handler (optional)
5353
/// - userProfileService: custom UserProfileService (optional)
54+
/// - odpManager: custom OdpManager (optional)
5455
/// - periodicDownloadInterval: interval in secs for periodic background datafile download.
5556
/// The recommended value is 10 * 60 secs (you can also set this to nil to use the recommended value).
5657
/// Set this to 0 to disable periodic downloading.

Sources/ODP/OdpEventApiManager.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import Foundation
3030
{"title":"Accepted","status":202,"timestamp":"2022-06-30T20:59:52.046Z"}
3131
*/
3232

33-
public class OdpEventApiManager {
33+
open class OdpEventApiManager {
3434
let resourceTimeoutInSecs: Int?
3535

3636
/// OdpEventApiManager init

Sources/ODP/OdpEventManager.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ open class OdpEventManager {
101101

102102
// MARK: - dispatch
103103

104+
// open for FSC testing support
104105
open func dispatch(_ event: OdpEvent) {
105106
if eventQueue.count < maxQueueSize {
106107
eventQueue.save(item: event)

Sources/ODP/OdpManager.swift

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,17 +116,35 @@ public class OdpManager {
116116
/// - identifiers: a dictionary for identifiers.
117117
/// - data: a dictionary for associated data. The default event data will be added to this data before sending to the ODP server.
118118
/// - Throws: `OptimizelyError` if error is detected
119-
func sendEvent(type: String, action: String, identifiers: [String: String], data: [String: Any?]) throws {
119+
func sendEvent(type: String?, action: String, identifiers: [String: String], data: [String: Any?]) throws {
120120
guard enabled else { throw OptimizelyError.odpNotEnabled }
121121
guard odpConfig.eventQueueingAllowed else { throw OptimizelyError.odpNotIntegrated }
122122
guard eventManager.isDataValidType(data) else { throw OptimizelyError.odpInvalidData }
123+
124+
if action.isEmpty { throw OptimizelyError.odpInvalidAction }
125+
126+
let typeUpdated = (type ?? "").isEmpty ? Constants.ODP.eventType : type!
127+
128+
// add vuid to all events by default
123129

124-
var identifiersWithVuid = identifiers
130+
var identifiersUpdated = identifiers
125131
if identifiers[Constants.ODP.keyForVuid] == nil {
126-
identifiersWithVuid[Constants.ODP.keyForVuid] = vuidManager.vuid
132+
identifiersUpdated[Constants.ODP.keyForVuid] = vuidManager.vuid
133+
}
134+
135+
// replace aliases (fs-user-id, FS_USER_ID, FS-USER-ID) with "fs_user_id".
136+
137+
for (idKey, idValue) in identifiersUpdated {
138+
if idKey == Constants.ODP.keyForUserId { break }
139+
140+
if [Constants.ODP.keyForUserId, Constants.ODP.keyForUserIdAlias].contains(idKey.lowercased()) {
141+
identifiersUpdated.removeValue(forKey: idKey)
142+
identifiersUpdated[Constants.ODP.keyForUserId] = idValue
143+
break
144+
}
127145
}
128146

129-
eventManager.sendEvent(type: type, action: action, identifiers: identifiersWithVuid, data: data)
147+
eventManager.sendEvent(type: typeUpdated, action: action, identifiers: identifiersUpdated, data: data)
130148
}
131149

132150
func updateOdpConfig(apiKey: String?, apiHost: String?, segmentsToCheck: [String]) {

Sources/ODP/OdpSegmentManager.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import Foundation
1818

19-
public class OdpSegmentManager {
19+
open class OdpSegmentManager {
2020
var odpConfig = OdpConfig()
2121
var segmentsCache: LruCache<String, [String]>
2222
var apiMgr: OdpSegmentApiManager
@@ -33,7 +33,6 @@ public class OdpSegmentManager {
3333
cacheTimeoutInSecs: Int,
3434
apiManager: OdpSegmentApiManager? = nil,
3535
resourceTimeoutInSecs: Int? = nil) {
36-
self.odpConfig = odpConfig ?? OdpConfig()
3736
self.apiMgr = apiManager ?? OdpSegmentApiManager(timeout: resourceTimeoutInSecs)
3837

3938
self.segmentsCache = LruCache<String, [String]>(size: cacheSize,

Sources/Optimizely+Decide/OptimizelyClient+Decide.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,7 @@ extension OptimizelyClient {
4444
return createUserContext(userId: userId,
4545
attributes: (attributes ?? [:]) as [String: Any])
4646
}
47-
48-
47+
4948
/// Create a user context to be used internally without sending an ODP identify event.
5049
///
5150
/// - Parameters:

Sources/Optimizely/OptimizelyClient.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ open class OptimizelyClient: NSObject {
5959

6060
var decisionService: OPTDecisionService!
6161
public var notificationCenter: OPTNotificationCenter?
62-
var odpManager: OdpManager!
62+
public var odpManager: OdpManager!
6363
let sdkSettings: OptimizelySdkSettings
6464

6565
// MARK: - Public interfaces
@@ -72,6 +72,7 @@ open class OptimizelyClient: NSObject {
7272
/// - eventDispatcher: custom EventDispatcher (optional)
7373
/// - datafileHandler: custom datafile handler (optional)
7474
/// - userProfileService: custom UserProfileService (optional)
75+
/// - odpManager: custom OdpManager (optional)
7576
/// - defaultLogLevel: default log level (optional. default = .info)
7677
/// - defaultDecisionOptions: default decision options (optional)
7778
/// - settings: SDK configuration (optional)
@@ -941,7 +942,7 @@ extension OptimizelyClient {
941942
action: String,
942943
identifiers: [String: String] = [:],
943944
data: [String: Any?] = [:]) throws {
944-
try odpManager.sendEvent(type: type ?? Constants.ODP.eventType,
945+
try odpManager.sendEvent(type: type,
945946
action: action,
946947
identifiers: identifiers,
947948
data: data)

0 commit comments

Comments
 (0)