Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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 = url?.absoluteString ?? EventForDispatch.getEndpoint(for: region)
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
19 changes: 15 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,14 @@ 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)

let regionValue = base.region == Region.EU.rawValue ? Region.EU : Region.US
return EventForDispatch(url: url, body: data, region: regionValue)
}
}
18 changes: 13 additions & 5 deletions Sources/Implementation/Events/BatchEventBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ class BatchEventBuilder {
userId: userId,
attributes: attributes,
decisions: [decision],
dispatchEvents: [dispatchEvent])
dispatchEvents: [dispatchEvent],
region: config.region)
}

// MARK: - Converison Event
Expand Down Expand Up @@ -77,7 +78,8 @@ class BatchEventBuilder {
userId: userId,
attributes: attributes,
decisions: nil,
dispatchEvents: [dispatchEvent])
dispatchEvents: [dispatchEvent],
region: config.region)
}

// MARK: - Create Event
Expand All @@ -86,7 +88,9 @@ class BatchEventBuilder {
userId: String,
attributes: OptimizelyAttributes?,
decisions: [Decision]?,
dispatchEvents: [DispatchEvent]) -> Data? {
dispatchEvents: [DispatchEvent],
region: Region? = nil) -> Data? {
let eventRegion = region ?? config.region
let snapShot = Snapshot(decisions: decisions, events: dispatchEvents)

let eventAttributes = getEventAttributes(config: config, attributes: attributes)
Expand All @@ -100,9 +104,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
15 changes: 11 additions & 4 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, region: region)
return ObjcOptimizelyUserContext(user: user, region: region)
}

@available(swift, obsoleted: 1.0)
Expand Down
4 changes: 3 additions & 1 deletion Sources/Optimizely+Decide/OptimizelyUserContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,11 @@ 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) {
attributes: [String: Any?]? = nil,
region: String? = nil) {
self.init(optimizely: optimizely, userId: userId, attributes: attributes ?? [:], identify: true)
}

Expand Down
Loading
Loading