Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Sources/Data Model/DispatchEvents/BatchEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ struct BatchEvent: Codable, Equatable {
let clientName: String
let anonymizeIP: Bool
let enrichDecisions: Bool
let region: String

enum CodingKeys: String, CodingKey {
case revision
Expand All @@ -35,6 +36,7 @@ struct BatchEvent: Codable, Equatable {
case clientName = "client_name"
case anonymizeIP = "anonymize_ip"
case enrichDecisions = "enrich_decisions"
case region
}

func getEventAttribute(key: String) -> EventAttribute? {
Expand Down
15 changes: 13 additions & 2 deletions Sources/Data Model/DispatchEvents/EventForDispatch.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,23 @@ import Foundation

@objcMembers public class EventForDispatch: NSObject, Codable {
public static var eventEndpoint = "https://logx.optimizely.com/v1/events"
public static var euEventEndpoint = "https://eu.logx.optimizely.com/v1/events"

public static func getEndpoint(for region: Region) -> String {
switch region {
case .EU:
return euEventEndpoint
case .US:
return eventEndpoint
}
}

public let url: URL
public let body: Data

public init(url: URL? = nil, body: Data) {
self.url = url ?? URL(string: EventForDispatch.eventEndpoint)!
public init(url: URL? = nil, body: Data, region: Region = .US) {
let endpoint = region == .US ? Self.eventEndpoint : Self.euEventEndpoint
self.url = URL(string: endpoint)!
self.body = body
}

Expand Down
16 changes: 14 additions & 2 deletions Sources/Data Model/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@

import Foundation

/// Optimizely region identifiers
public enum Region: String, Codable, Equatable {
case US
case EU
}

protocol ProjectProtocol {
func evaluateAudience(audienceId: String, user: OptimizelyUserContext) throws -> Bool
}
Expand Down Expand Up @@ -48,6 +54,8 @@ struct Project: Codable, Equatable {
var environmentKey: String?
// Holdouts
var holdouts: [Holdout]
// Region
var region: Region?
let logger = OPTLoggerFactory.getLogger()

// Required since logger is not decodable
Expand All @@ -57,7 +65,7 @@ struct Project: Codable, Equatable {
// V3
case anonymizeIP
// V4
case rollouts, integrations, typedAudiences, featureFlags, botFiltering, sendFlagDecisions, sdkKey, environmentKey, holdouts
case rollouts, integrations, typedAudiences, featureFlags, botFiltering, sendFlagDecisions, sdkKey, environmentKey, holdouts, region
}

init(from decoder: Decoder) throws {
Expand Down Expand Up @@ -88,6 +96,8 @@ struct Project: Codable, Equatable {
environmentKey = try container.decodeIfPresent(String.self, forKey: .environmentKey)
// Holdouts - defaults to empty array if key is not present
holdouts = try container.decodeIfPresent([Holdout].self, forKey: .holdouts) ?? []
// Region - defaults to US if not present
region = try container.decodeIfPresent(Region.self, forKey: .region)
}

// Required since logger is not equatable
Expand All @@ -97,7 +107,9 @@ struct Project: Codable, Equatable {
lhs.accountId == rhs.accountId && lhs.events == rhs.events && lhs.revision == rhs.revision &&
lhs.anonymizeIP == rhs.anonymizeIP && lhs.rollouts == rhs.rollouts &&
lhs.integrations == rhs.integrations && lhs.typedAudiences == rhs.typedAudiences &&
lhs.featureFlags == rhs.featureFlags && lhs.botFiltering == rhs.botFiltering && lhs.sendFlagDecisions == rhs.sendFlagDecisions && lhs.sdkKey == rhs.sdkKey && lhs.environmentKey == rhs.environmentKey
lhs.featureFlags == rhs.featureFlags && lhs.botFiltering == rhs.botFiltering &&
lhs.sendFlagDecisions == rhs.sendFlagDecisions && lhs.sdkKey == rhs.sdkKey &&
lhs.environmentKey == rhs.environmentKey && lhs.region == rhs.region
}
}

Expand Down
7 changes: 7 additions & 0 deletions Sources/Data Model/ProjectConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,13 @@ extension ProjectConfig {

extension ProjectConfig {

/**
* Get the region value. Defaults to US if not specified in the project.
*/
public var region: Region {
return project.region ?? .US
}

/**
* Get sendFlagDecisions value.
*/
Expand Down
18 changes: 14 additions & 4 deletions Sources/Extensions/ArrayEventForDispatch+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ extension Array where Element == EventForDispatch {
var url: URL?
var projectId: String?
var revision: String?
var region: String?

let checkUrl = { (event: EventForDispatch) -> Bool in
if url == nil {
Expand All @@ -69,10 +70,18 @@ extension Array where Element == EventForDispatch {
}
return revision == batchEvent.revision
}

let checkRegion = { (batchEvent: BatchEvent) -> Bool in
if region == nil {
region = batchEvent.region
return region != nil
}
return region == batchEvent.region
}

for event in self {
if let batchEvent = try? JSONDecoder().decode(BatchEvent.self, from: event.body) {
if !checkUrl(event) || !checkProjectId(batchEvent) || !checkRevision(batchEvent) {
if !checkUrl(event) || !checkProjectId(batchEvent) || !checkRevision(batchEvent) || !checkRegion(batchEvent) {
break
}

Expand Down Expand Up @@ -101,12 +110,13 @@ extension Array where Element == EventForDispatch {
projectID: base.projectID,
clientName: base.clientName,
anonymizeIP: base.anonymizeIP,
enrichDecisions: true)
enrichDecisions: true,
region: base.region)

guard let data = try? JSONEncoder().encode(batchEvent) else {
return nil
}
return EventForDispatch(url: url, body: data)

return EventForDispatch(url: url, body: data, region: Region(rawValue: base.region) ?? .US)
}
}
9 changes: 7 additions & 2 deletions Sources/Implementation/Events/BatchEventBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class BatchEventBuilder {
attributes: OptimizelyAttributes?,
decisions: [Decision]?,
dispatchEvents: [DispatchEvent]) -> Data? {
let eventRegion = config.region
let snapShot = Snapshot(decisions: decisions, events: dispatchEvents)

let eventAttributes = getEventAttributes(config: config, attributes: attributes)
Expand All @@ -100,9 +101,13 @@ class BatchEventBuilder {
projectID: config.project.projectId,
clientName: Utils.swiftSdkClientName,
anonymizeIP: config.project.anonymizeIP,
enrichDecisions: true)
enrichDecisions: true,
region: eventRegion.rawValue)

let data = try? JSONEncoder().encode(batchEvent)
let eventForDispatch = EventForDispatch(url: nil, body: data ?? Data(), region: eventRegion)

return try? JSONEncoder().encode(batchEvent)
return eventForDispatch.body
}

// MARK: - Event Tags
Expand Down
17 changes: 12 additions & 5 deletions Sources/Optimizely+Decide/OptimizelyUserContext+ObjC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ import Foundation
return userContext.optimizely
}

public init(optimizely: OptimizelyClient, userId: String, attributes: [String: Any]? = nil) {
public init(optimizely: OptimizelyClient, userId: String, attributes: [String: Any]? = nil, region: String = "US") {
userContext = OptimizelyUserContext(optimizely: optimizely, userId: userId, attributes: attributes)
}
public init(user: OptimizelyUserContext) {

public init(user: OptimizelyUserContext, region: String = "US") {
self.userContext = user
}

Expand Down Expand Up @@ -83,7 +83,7 @@ import Foundation
ruleKey = decision.ruleKey

flagKey = decision.flagKey
userContext = ObjcOptimizelyUserContext(user: decision.userContext)
userContext = ObjcOptimizelyUserContext(user: decision.userContext, region: "US")
reasons = decision.reasons
}
}
Expand All @@ -94,7 +94,14 @@ extension OptimizelyClient {
@objc(createUserContextWithUserId:attributes:)
public func objcCreateUserContext(userId: String, attributes: [String: Any]? = nil) -> ObjcOptimizelyUserContext {
let user = createUserContext(userId: userId, attributes: attributes)
return ObjcOptimizelyUserContext(user: user)
return ObjcOptimizelyUserContext(user: user, region: "US")
}

@available(swift, obsoleted: 1.0)
@objc(createUserContextWithUserId:attributes:region:)
public func objcCreateUserContext(userId: String, attributes: [String: Any]? = nil, region: String) -> ObjcOptimizelyUserContext {
let user = OptimizelyUserContext(optimizely: self, userId: userId, attributes: attributes)
return ObjcOptimizelyUserContext(user: user, region: region)
}

@available(swift, obsoleted: 1.0)
Expand Down
1 change: 1 addition & 0 deletions Sources/Optimizely+Decide/OptimizelyUserContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public class OptimizelyUserContext {
/// - optimizely: An instance of OptimizelyClient to be used for decisions.
/// - userId: The user ID to be used for bucketing.
/// - attributes: A map of attribute names to current user attribute values.
/// - region: The region for the user context (optional). Defaults to the region from the project config.
public convenience init(optimizely: OptimizelyClient,
userId: String,
attributes: [String: Any?]? = nil) {
Expand Down
7 changes: 7 additions & 0 deletions Sources/Optimizely/OptimizelyClient+ObjC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -546,3 +546,10 @@ extension OptimizelyClient {
}

}

// MARK: - EventForDispatch Objective-C initializer
extension EventForDispatch {
@objc public convenience init(url: URL? = nil, body: Data) {
self.init(url: url, body: body, region: .US)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,8 @@ extension EventDispatcherTests_Batch {
projectID: testProjectId,
clientName: kClientName,
anonymizeIP: kAnonymizeIP,
enrichDecisions: kEnrichDecision)
enrichDecisions: kEnrichDecision,
region: "US")
}

func dispatchMultipleEvents(_ events: [(url: String, event: BatchEvent)]) {
Expand Down
Loading
Loading