Skip to content

Commit 962ca8f

Browse files
[FSSDK-11455] Java - Add SDK Multi-Region Support for Data Hosting (#573)
* [FSSDK-11455] Java - Add SDK Multi-Region Support for Data Hosting * Update test comment * Fix failures * Update Nebula version * Fix tests * Implement changes * Implement comments
1 parent 05f922d commit 962ca8f

File tree

13 files changed

+168
-9
lines changed

13 files changed

+168
-9
lines changed

core-api/src/main/java/com/optimizely/ab/config/DatafileProjectConfig.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public class DatafileProjectConfig implements ProjectConfig {
6363
private final boolean anonymizeIP;
6464
private final boolean sendFlagDecisions;
6565
private final Boolean botFiltering;
66+
private final String region;
6667
private final String hostForODP;
6768
private final String publicKeyForODP;
6869
private final List<Attribute> attributes;
@@ -115,6 +116,7 @@ public DatafileProjectConfig(String accountId, String projectId, String version,
115116
anonymizeIP,
116117
false,
117118
null,
119+
null,
118120
projectId,
119121
revision,
120122
null,
@@ -138,6 +140,7 @@ public DatafileProjectConfig(String accountId,
138140
boolean anonymizeIP,
139141
boolean sendFlagDecisions,
140142
Boolean botFiltering,
143+
String region,
141144
String projectId,
142145
String revision,
143146
String sdkKey,
@@ -162,6 +165,7 @@ public DatafileProjectConfig(String accountId,
162165
this.anonymizeIP = anonymizeIP;
163166
this.sendFlagDecisions = sendFlagDecisions;
164167
this.botFiltering = botFiltering;
168+
this.region = region != null ? region : "US";
165169

166170
this.attributes = Collections.unmodifiableList(attributes);
167171
this.audiences = Collections.unmodifiableList(audiences);
@@ -434,6 +438,11 @@ public Boolean getBotFiltering() {
434438
return botFiltering;
435439
}
436440

441+
@Override
442+
public String getRegion() {
443+
return region;
444+
}
445+
437446
@Override
438447
public List<Group> getGroups() {
439448
return groups;
@@ -612,6 +621,7 @@ public String toString() {
612621
", version='" + version + '\'' +
613622
", anonymizeIP=" + anonymizeIP +
614623
", botFiltering=" + botFiltering +
624+
", region=" + region +
615625
", attributes=" + attributes +
616626
", audiences=" + audiences +
617627
", typedAudiences=" + typedAudiences +

core-api/src/main/java/com/optimizely/ab/config/ProjectConfig.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,6 @@ public String toString() {
142142
return version;
143143
}
144144
}
145+
146+
String getRegion();
145147
}

core-api/src/main/java/com/optimizely/ab/config/parser/DatafileGsonDeserializer.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,18 @@ public ProjectConfig deserialize(JsonElement json, Type typeOfT, JsonDeserializa
121121
sendFlagDecisions = jsonObject.get("sendFlagDecisions").getAsBoolean();
122122
}
123123

124+
String region = "US";
125+
126+
if (jsonObject.has("region")) {
127+
region = jsonObject.get("region").getAsString();
128+
}
129+
124130
return new DatafileProjectConfig(
125131
accountId,
126132
anonymizeIP,
127133
sendFlagDecisions,
128134
botFiltering,
135+
region,
129136
projectId,
130137
revision,
131138
sdkKey,

core-api/src/main/java/com/optimizely/ab/config/parser/DatafileJacksonDeserializer.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,18 @@ public DatafileProjectConfig deserialize(JsonParser parser, DeserializationConte
9595
}
9696
}
9797

98+
String region = "US";
99+
100+
if (node.hasNonNull("region")) {
101+
region = node.get("region").textValue();
102+
}
103+
98104
return new DatafileProjectConfig(
99105
accountId,
100106
anonymizeIP,
101107
sendFlagDecisions,
102108
botFiltering,
109+
region,
103110
projectId,
104111
revision,
105112
sdkKey,

core-api/src/main/java/com/optimizely/ab/config/parser/JsonConfigParser.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,17 @@ public ProjectConfig parseProjectConfig(@Nonnull String json) throws ConfigParse
100100
sendFlagDecisions = rootObject.getBoolean("sendFlagDecisions");
101101
}
102102

103+
String region = "US"; // Default to US
104+
if (rootObject.has("region")) {
105+
String regionString = rootObject.getString("region");
106+
}
107+
103108
return new DatafileProjectConfig(
104109
accountId,
105110
anonymizeIP,
106111
sendFlagDecisions,
107112
botFiltering,
113+
region,
108114
projectId,
109115
revision,
110116
sdkKey,

core-api/src/main/java/com/optimizely/ab/config/parser/JsonSimpleConfigParser.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,17 @@ public ProjectConfig parseProjectConfig(@Nonnull String json) throws ConfigParse
103103
sendFlagDecisions = (Boolean) rootObject.get("sendFlagDecisions");
104104
}
105105

106+
String region = "US"; // Default to US
107+
if (rootObject.containsKey("region")) {
108+
String regionString = (String) rootObject.get("region");
109+
}
110+
106111
return new DatafileProjectConfig(
107112
accountId,
108113
anonymizeIP,
109114
sendFlagDecisions,
110115
botFiltering,
116+
region,
111117
projectId,
112118
revision,
113119
sdkKey,
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
*
3+
* Copyright 2016-2020, 2022, Optimizely and contributors
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package com.optimizely.ab.event.internal;
18+
import java.util.HashMap;
19+
import java.util.Map;
20+
21+
/**
22+
* EventEndpoints provides region-specific endpoint URLs for Optimizely events.
23+
* Similar to the TypeScript logxEndpoint configuration.
24+
*/
25+
public class EventEndpoints {
26+
27+
private static final Map<String, String> LOGX_ENDPOINTS = new HashMap<>();
28+
29+
static {
30+
LOGX_ENDPOINTS.put("US", "https://logx.optimizely.com/v1/events");
31+
LOGX_ENDPOINTS.put("EU", "https://eu.logx.optimizely.com/v1/events");
32+
}
33+
34+
/**
35+
* Get the event endpoint URL for the specified region.
36+
* Defaults to US region endpoint if region is null.
37+
*
38+
* @param region the region for which to get the endpoint
39+
* @return the endpoint URL for the specified region, or US endpoint if region is null
40+
*/
41+
public static String getEndpointForRegion(String region) {
42+
if (region != null && region.equals("EU")) {
43+
return LOGX_ENDPOINTS.get("EU");
44+
}
45+
return LOGX_ENDPOINTS.get("US");
46+
}
47+
}

core-api/src/main/java/com/optimizely/ab/event/internal/EventFactory.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
*/
4343
public class EventFactory {
4444
private static final Logger logger = LoggerFactory.getLogger(EventFactory.class);
45-
public static final String EVENT_ENDPOINT = "https://logx.optimizely.com/v1/events"; // Should be part of the datafile
4645
private static final String ACTIVATE_EVENT_KEY = "campaign_activated";
4746

4847
public static LogEvent createLogEvent(UserEvent userEvent) {
@@ -52,6 +51,7 @@ public static LogEvent createLogEvent(UserEvent userEvent) {
5251
public static LogEvent createLogEvent(List<UserEvent> userEvents) {
5352
EventBatch.Builder builder = new EventBatch.Builder();
5453
List<Visitor> visitors = new ArrayList<>(userEvents.size());
54+
String eventEndpoint = "https://logx.optimizely.com/v1/events";
5555

5656
for (UserEvent userEvent: userEvents) {
5757

@@ -71,6 +71,8 @@ public static LogEvent createLogEvent(List<UserEvent> userEvents) {
7171
UserContext userContext = userEvent.getUserContext();
7272
ProjectConfig projectConfig = userContext.getProjectConfig();
7373

74+
eventEndpoint = EventEndpoints.getEndpointForRegion(projectConfig.getRegion());
75+
7476
builder
7577
.setClientName(ClientEngineInfo.getClientEngineName())
7678
.setClientVersion(BuildVersionInfo.getClientVersion())
@@ -85,7 +87,7 @@ public static LogEvent createLogEvent(List<UserEvent> userEvents) {
8587
}
8688

8789
builder.setVisitors(visitors);
88-
return new LogEvent(LogEvent.RequestMethod.POST, EVENT_ENDPOINT, Collections.emptyMap(), builder.build());
90+
return new LogEvent(LogEvent.RequestMethod.POST, eventEndpoint, Collections.emptyMap(), builder.build());
8991
}
9092

9193
private static Visitor createVisitor(ImpressionEvent impressionEvent) {

core-api/src/test/java/com/optimizely/ab/config/ValidProjectConfigV4.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public class ValidProjectConfigV4 {
4141
private static final String ENVIRONMENT_KEY = "production";
4242
private static final String VERSION = "4";
4343
private static final Boolean SEND_FLAG_DECISIONS = true;
44+
private static final String REGION = "US";
4445

4546
// attributes
4647
private static final String ATTRIBUTE_HOUSE_ID = "553339214";
@@ -1564,6 +1565,7 @@ public static ProjectConfig generateValidProjectConfigV4() {
15641565
ANONYMIZE_IP,
15651566
SEND_FLAG_DECISIONS,
15661567
BOT_FILTERING,
1568+
REGION,
15671569
PROJECT_ID,
15681570
REVISION,
15691571
SDK_KEY,
@@ -1666,6 +1668,7 @@ public static ProjectConfig generateValidProjectConfigV4_holdout() {
16661668
ANONYMIZE_IP,
16671669
SEND_FLAG_DECISIONS,
16681670
BOT_FILTERING,
1671+
REGION,
16691672
PROJECT_ID,
16701673
REVISION,
16711674
SDK_KEY,

core-api/src/test/java/com/optimizely/ab/event/ForwardingEventProcessorTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public void setUp() throws Exception {
5050
eventProcessor = new ForwardingEventProcessor(logEvent -> {
5151
assertNotNull(logEvent.getEventBatch());
5252
assertEquals(logEvent.getRequestMethod(), LogEvent.RequestMethod.POST);
53-
assertEquals(logEvent.getEndpointUrl(), EventFactory.EVENT_ENDPOINT);
53+
assertEquals(logEvent.getEndpointUrl(), EventEndpoints.getEndpointForRegion("US"));
5454
atomicBoolean.set(true);
5555
}, notificationCenter);
5656
}

0 commit comments

Comments
 (0)