Skip to content

Commit 3190808

Browse files
authored
feat(flag-decisions): Add support for sending flag decisions along with decision metadata. (#370)
1 parent b1d0962 commit 3190808

File tree

14 files changed

+583
-337
lines changed

14 files changed

+583
-337
lines changed

Sources/Data Model/DispatchEvents/BatchEvent.swift

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
/****************************************************************************
2-
* Copyright 2019, Optimizely, Inc. and contributors *
3-
* *
4-
* Licensed under the Apache License, Version 2.0 (the "License"); *
5-
* you may not use this file except in compliance with the License. *
6-
* You may obtain a copy of the License at *
7-
* *
8-
* http://www.apache.org/licenses/LICENSE-2.0 *
9-
* *
10-
* Unless required by applicable law or agreed to in writing, software *
11-
* distributed under the License is distributed on an "AS IS" BASIS, *
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13-
* See the License for the specific language governing permissions and *
14-
* limitations under the License. *
15-
***************************************************************************/
2+
* Copyright 2019-2020, Optimizely, Inc. and contributors *
3+
* *
4+
* Licensed under the Apache License, Version 2.0 (the "License"); *
5+
* you may not use this file except in compliance with the License. *
6+
* You may obtain a copy of the License at *
7+
* *
8+
* http://www.apache.org/licenses/LICENSE-2.0 *
9+
* *
10+
* Unless required by applicable law or agreed to in writing, software *
11+
* distributed under the License is distributed on an "AS IS" BASIS, *
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13+
* See the License for the specific language governing permissions and *
14+
* limitations under the License. *
15+
***************************************************************************/
1616

1717
import Foundation
1818

@@ -79,15 +79,31 @@ struct Snapshot: Codable, Equatable {
7979
let events: [DispatchEvent]
8080
}
8181

82+
struct DecisionMetadata: Codable, Equatable {
83+
let ruleType: String
84+
let ruleKey: String
85+
let flagKey: String
86+
let variationKey: String
87+
88+
enum CodingKeys: String, CodingKey {
89+
case ruleType = "rule_type"
90+
case ruleKey = "rule_key"
91+
case flagKey = "flag_key"
92+
case variationKey = "variation_key"
93+
}
94+
}
95+
8296
struct Decision: Codable, Equatable {
8397
let variationID: String
8498
let campaignID: String
8599
let experimentID: String
100+
let metaData: DecisionMetadata
86101

87102
enum CodingKeys: String, CodingKey {
88103
case variationID = "variation_id"
89104
case campaignID = "campaign_id"
90105
case experimentID = "experiment_id"
106+
case metaData = "metadata"
91107
}
92108
}
93109

@@ -104,7 +120,7 @@ struct DispatchEvent: Codable, Equatable {
104120
var tags: [String: AttributeValue]?
105121
var revenue: AttributeValue?
106122
var value: AttributeValue?
107-
123+
108124
enum CodingKeys: String, CodingKey {
109125
case entityID = "entity_id"
110126
case key
@@ -124,7 +140,7 @@ struct DispatchEvent: Codable, Equatable {
124140
revenue: AttributeValue? = nil) {
125141

126142
// TODO: add validation and throw here for invalid value (int, double) and revenue (int) types
127-
143+
128144
self.timestamp = timestamp
129145
self.key = key
130146
self.entityID = entityID

Sources/Data Model/Project.swift

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
/****************************************************************************
2-
* Copyright 2019-2020, Optimizely, Inc. and contributors *
3-
* *
4-
* Licensed under the Apache License, Version 2.0 (the "License"); *
5-
* you may not use this file except in compliance with the License. *
6-
* You may obtain a copy of the License at *
7-
* *
8-
* http://www.apache.org/licenses/LICENSE-2.0 *
9-
* *
10-
* Unless required by applicable law or agreed to in writing, software *
11-
* distributed under the License is distributed on an "AS IS" BASIS, *
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13-
* See the License for the specific language governing permissions and *
14-
* limitations under the License. *
15-
***************************************************************************/
2+
* Copyright 2019-2020, Optimizely, Inc. and contributors *
3+
* *
4+
* Licensed under the Apache License, Version 2.0 (the "License"); *
5+
* you may not use this file except in compliance with the License. *
6+
* You may obtain a copy of the License at *
7+
* *
8+
* http://www.apache.org/licenses/LICENSE-2.0 *
9+
* *
10+
* Unless required by applicable law or agreed to in writing, software *
11+
* distributed under the License is distributed on an "AS IS" BASIS, *
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13+
* See the License for the specific language governing permissions and *
14+
* limitations under the License. *
15+
***************************************************************************/
1616

1717
import Foundation
1818

@@ -42,23 +42,24 @@ struct Project: Codable, Equatable {
4242
var typedAudiences: [Audience]?
4343
var featureFlags: [FeatureFlag]
4444
var botFiltering: Bool?
45+
var sendFlagDecisions: Bool?
4546

4647
let logger = OPTLoggerFactory.getLogger()
4748

48-
// Required since logger in not decodable
49+
// Required since logger is not decodable
4950
enum CodingKeys: String, CodingKey {
5051
// V2
5152
case version, projectId, experiments, audiences, groups, attributes, accountId, events, revision
5253
// V3
5354
case anonymizeIP
5455
// V4
55-
case rollouts, typedAudiences, featureFlags, botFiltering
56+
case rollouts, typedAudiences, featureFlags, botFiltering, sendFlagDecisions
5657
}
5758

58-
// Required since logger in not equatable
59+
// Required since logger is not equatable
5960
static func ==(lhs: Project, rhs: Project) -> Bool {
6061
return lhs.version == rhs.version && lhs.projectId == rhs.projectId && lhs.experiments == rhs.experiments &&
61-
lhs.audiences == rhs.audiences && lhs.groups == rhs.groups && lhs.attributes == rhs.attributes && lhs.accountId == rhs.accountId && lhs.events == rhs.events && lhs.revision == rhs.revision && lhs.anonymizeIP == rhs.anonymizeIP && lhs.rollouts == rhs.rollouts && lhs.typedAudiences == rhs.typedAudiences && lhs.featureFlags == rhs.featureFlags && lhs.botFiltering == rhs.botFiltering
62+
lhs.audiences == rhs.audiences && lhs.groups == rhs.groups && lhs.attributes == rhs.attributes && lhs.accountId == rhs.accountId && lhs.events == rhs.events && lhs.revision == rhs.revision && lhs.anonymizeIP == rhs.anonymizeIP && lhs.rollouts == rhs.rollouts && lhs.typedAudiences == rhs.typedAudiences && lhs.featureFlags == rhs.featureFlags && lhs.botFiltering == rhs.botFiltering && lhs.sendFlagDecisions == rhs.sendFlagDecisions
6263
}
6364
}
6465

Sources/Data Model/ProjectConfig.swift

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
/****************************************************************************
2-
* Copyright 2019, Optimizely, Inc. and contributors *
3-
* *
4-
* Licensed under the Apache License, Version 2.0 (the "License"); *
5-
* you may not use this file except in compliance with the License. *
6-
* You may obtain a copy of the License at *
7-
* *
8-
* http://www.apache.org/licenses/LICENSE-2.0 *
9-
* *
10-
* Unless required by applicable law or agreed to in writing, software *
11-
* distributed under the License is distributed on an "AS IS" BASIS, *
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13-
* See the License for the specific language governing permissions and *
14-
* limitations under the License. *
15-
***************************************************************************/
2+
* Copyright 2019-2020, Optimizely, Inc. and contributors *
3+
* *
4+
* Licensed under the Apache License, Version 2.0 (the "License"); *
5+
* you may not use this file except in compliance with the License. *
6+
* You may obtain a copy of the License at *
7+
* *
8+
* http://www.apache.org/licenses/LICENSE-2.0 *
9+
* *
10+
* Unless required by applicable law or agreed to in writing, software *
11+
* distributed under the License is distributed on an "AS IS" BASIS, *
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13+
* See the License for the specific language governing permissions and *
14+
* limitations under the License. *
15+
***************************************************************************/
1616

1717
import Foundation
1818

@@ -34,13 +34,13 @@ class ProjectConfig {
3434
}
3535
return map
3636
}()
37-
37+
3838
lazy var experimentIdMap: [String: Experiment] = {
3939
var map = [String: Experiment]()
4040
allExperiments.forEach { map[$0.id] = $0 }
4141
return map
4242
}()
43-
43+
4444
lazy var experimentFeatureMap: [String: [String]] = {
4545
var experimentFeatureMap = [String: [String]]()
4646
project.featureFlags.forEach { (ff) in
@@ -67,25 +67,25 @@ class ProjectConfig {
6767
project.attributes.forEach { map[$0.key] = $0 }
6868
return map
6969
}()
70-
70+
7171
lazy var featureFlagKeyMap: [String: FeatureFlag] = {
7272
var map = [String: FeatureFlag]()
7373
project.featureFlags.forEach { map[$0.key] = $0 }
7474
return map
7575
}()
76-
76+
7777
lazy var rolloutIdMap: [String: Rollout] = {
7878
var map = [String: Rollout]()
7979
project.rollouts.forEach { map[$0.id] = $0 }
8080
return map
8181
}()
82-
82+
8383
lazy var allExperiments: [Experiment] = {
8484
return project.experiments + project.groups.map { $0.experiments }.flatMap({$0})
8585
}()
8686

8787
// MARK: - Init
88-
88+
8989
init(datafile: Data) throws {
9090
do {
9191
self.project = try JSONDecoder().decode(Project.self, from: datafile)
@@ -142,7 +142,7 @@ extension ProjectConfig {
142142
}
143143

144144
static var observer = ProjectObserver()
145-
145+
146146
}
147147

148148
// MARK: - Persistent Data
@@ -177,6 +177,13 @@ extension ProjectConfig {
177177

178178
extension ProjectConfig {
179179

180+
/**
181+
* Get sendFlagDecisions value.
182+
*/
183+
var sendFlagDecisions: Bool {
184+
return project.sendFlagDecisions ?? false
185+
}
186+
180187
/**
181188
* Get an Experiment object for a key.
182189
*/
@@ -306,12 +313,12 @@ extension ProjectConfig {
306313

307314
// TODO: common function to trim all keys
308315
variationKey = variationKey.trimmingCharacters(in: NSCharacterSet.whitespaces)
309-
316+
310317
guard !variationKey.isEmpty else {
311318
logger.e(.variationKeyInvalid(experimentKey, variationKey))
312319
return false
313320
}
314-
321+
315322
guard let variation = experiment.getVariation(key: variationKey) else {
316323
logger.e(.variationKeyInvalid(experimentKey, variationKey))
317324
return false

0 commit comments

Comments
 (0)