Skip to content

Commit 9f7ea59

Browse files
committed
fix to support android-sdk
1 parent ad474c8 commit 9f7ea59

File tree

5 files changed

+83
-34
lines changed

5 files changed

+83
-34
lines changed

core-api/src/main/java/com/optimizely/ab/Optimizely.java

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,6 +1518,7 @@ Map<String, OptimizelyDecision> decideAll(@Nonnull OptimizelyUserContext user,
15181518
* @param options A list of options for decision-making.
15191519
* @return A decision result using traditional A/B testing logic only.
15201520
*/
1521+
@VisibleForTesting()
15211522
OptimizelyDecision decideSync(@Nonnull OptimizelyUserContext user,
15221523
@Nonnull String key,
15231524
@Nonnull List<OptimizelyDecideOption> options) {
@@ -1547,6 +1548,13 @@ Map<String, OptimizelyDecision> decideForKeysSync(@Nonnull OptimizelyUserContext
15471548
return decideForKeysSync(user, keys, options, false);
15481549
}
15491550

1551+
private Map<String, OptimizelyDecision> decideForKeysSync(@Nonnull OptimizelyUserContext user,
1552+
@Nonnull List<String> keys,
1553+
@Nonnull List<OptimizelyDecideOption> options,
1554+
boolean ignoreDefaultOptions) {
1555+
return decideForKeys(user, keys, options, ignoreDefaultOptions, DecisionPath.WITHOUT_CMAB);
1556+
}
1557+
15501558
/**
15511559
* Returns decision results for all active flag keys, skipping CMAB logic and using only traditional A/B testing.
15521560
* This will be called by mobile apps which will make synchronous decisions only (for backward compatibility with android-sdk)
@@ -1572,13 +1580,6 @@ Map<String, OptimizelyDecision> decideAllSync(@Nonnull OptimizelyUserContext use
15721580
return decideForKeysSync(user, allFlagKeys, options);
15731581
}
15741582

1575-
private Map<String, OptimizelyDecision> decideForKeysSync(@Nonnull OptimizelyUserContext user,
1576-
@Nonnull List<String> keys,
1577-
@Nonnull List<OptimizelyDecideOption> options,
1578-
boolean ignoreDefaultOptions) {
1579-
return decideForKeys(user, keys, options, ignoreDefaultOptions, DecisionPath.WITHOUT_CMAB);
1580-
}
1581-
15821583
//============ decide async ============//
15831584

15841585
/**
@@ -1589,10 +1590,10 @@ private Map<String, OptimizelyDecision> decideForKeysSync(@Nonnull OptimizelyUse
15891590
* @param callback A callback to invoke when the decision is available
15901591
* @param options A list of options for decision-making
15911592
*/
1592-
public void decideAsync(@Nonnull OptimizelyUserContext userContext,
1593-
@Nonnull String key,
1594-
@Nonnull OptimizelyDecisionCallback callback,
1595-
@Nonnull List<OptimizelyDecideOption> options) {
1593+
void decideAsync(@Nonnull OptimizelyUserContext userContext,
1594+
@Nonnull String key,
1595+
@Nonnull List<OptimizelyDecideOption> options,
1596+
@Nonnull OptimizelyDecisionCallback callback) {
15961597
AsyncDecisionFetcher fetcher = new AsyncDecisionFetcher(userContext, key, options, callback);
15971598
fetcher.start();
15981599
}
@@ -1605,10 +1606,10 @@ public void decideAsync(@Nonnull OptimizelyUserContext userContext,
16051606
* @param callback A callback to invoke when decisions are available
16061607
* @param options A list of options for decision-making
16071608
*/
1608-
public void decideForKeysAsync(@Nonnull OptimizelyUserContext userContext,
1609-
@Nonnull List<String> keys,
1610-
@Nonnull OptimizelyDecisionsCallback callback,
1611-
@Nonnull List<OptimizelyDecideOption> options) {
1609+
void decideForKeysAsync(@Nonnull OptimizelyUserContext userContext,
1610+
@Nonnull List<String> keys,
1611+
@Nonnull List<OptimizelyDecideOption> options,
1612+
@Nonnull OptimizelyDecisionsCallback callback) {
16121613
AsyncDecisionFetcher fetcher = new AsyncDecisionFetcher(userContext, keys, options, callback);
16131614
fetcher.start();
16141615
}
@@ -1620,9 +1621,9 @@ public void decideForKeysAsync(@Nonnull OptimizelyUserContext userContext,
16201621
* @param callback A callback to invoke when decisions are available
16211622
* @param options A list of options for decision-making
16221623
*/
1623-
public void decideAllAsync(@Nonnull OptimizelyUserContext userContext,
1624-
@Nonnull OptimizelyDecisionsCallback callback,
1625-
@Nonnull List<OptimizelyDecideOption> options) {
1624+
void decideAllAsync(@Nonnull OptimizelyUserContext userContext,
1625+
@Nonnull List<OptimizelyDecideOption> options,
1626+
@Nonnull OptimizelyDecisionsCallback callback) {
16261627
AsyncDecisionFetcher fetcher = new AsyncDecisionFetcher(userContext, options, callback);
16271628
fetcher.start();
16281629
}

core-api/src/main/java/com/optimizely/ab/OptimizelyUserContext.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
import javax.annotation.Nonnull;
2727
import javax.annotation.Nullable;
2828

29+
import com.optimizely.ab.annotations.VisibleForTesting;
30+
import com.optimizely.ab.optimizelydecision.OptimizelyDecisionCallback;
31+
import com.optimizely.ab.optimizelydecision.OptimizelyDecisionsCallback;
2932
import org.slf4j.Logger;
3033
import org.slf4j.LoggerFactory;
3134

@@ -395,4 +398,44 @@ public String toString() {
395398
", attributes='" + attributes + '\'' +
396399
'}';
397400
}
401+
402+
// sync decision support for android-sdk backward compatibility only
403+
404+
@VisibleForTesting // protected, open for testing only
405+
public OptimizelyDecision decideSync(@Nonnull String key,
406+
@Nonnull List<OptimizelyDecideOption> options) {
407+
return optimizely.decideSync(copy(), key, options);
408+
}
409+
410+
@VisibleForTesting // protected, open for testing only
411+
public Map<String, OptimizelyDecision> decideForKeysSync(@Nonnull List<String> keys,
412+
@Nonnull List<OptimizelyDecideOption> options) {
413+
return optimizely.decideForKeysSync(copy(), keys, options);
414+
}
415+
416+
@VisibleForTesting // protected, open for testing only
417+
public Map<String, OptimizelyDecision> decideAllSync(@Nonnull List<OptimizelyDecideOption> options) {
418+
return optimizely.decideAllSync(copy(), options);
419+
}
420+
421+
@VisibleForTesting // protected, open for testing only
422+
public void decideAsync(@Nonnull String key,
423+
@Nonnull List<OptimizelyDecideOption> options,
424+
@Nonnull OptimizelyDecisionCallback callback) {
425+
optimizely.decideAsync(copy(), key, options, callback);
426+
}
427+
428+
@VisibleForTesting // protected, open for testing only
429+
public void decideForKeysAsync(@Nonnull List<String> keys,
430+
@Nonnull List<OptimizelyDecideOption> options,
431+
@Nonnull OptimizelyDecisionsCallback callback) {
432+
optimizely.decideForKeysAsync(copy(), keys, options, callback);
433+
}
434+
435+
@VisibleForTesting // protected, open for testing only
436+
public void decideAllAsync(@Nonnull List<OptimizelyDecideOption> options,
437+
@Nonnull OptimizelyDecisionsCallback callback) {
438+
optimizely.decideAllAsync(copy(), options, callback);
439+
}
440+
398441
}

core-api/src/main/java/com/optimizely/ab/cmab/client/CmabClientHelper.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.regex.Pattern;
2121

2222
public class CmabClientHelper {
23+
public static final String CMAB_PREDICTION_ENDPOINT = "https://prediction.cmab.optimizely.com/predict/%s";
2324
public static final String CMAB_FETCH_FAILED = "CMAB decision fetch failed with status: %s";
2425
public static final String INVALID_CMAB_FETCH_RESPONSE = "Invalid CMAB fetch response";
2526
private static final Pattern VARIATION_ID_PATTERN = Pattern.compile("\"variation_id\"\\s*:\\s*\"?([^\"\\s,}]+)\"?");

core-api/src/test/java/com/optimizely/ab/OptimizelyTest.java

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5152,17 +5152,19 @@ public void decideAsyncReturnsDecision() throws Exception {
51525152
final AtomicReference<OptimizelyDecision> decisionRef = new AtomicReference<>();
51535153
final AtomicReference<Throwable> errorRef = new AtomicReference<>();
51545154

5155-
optimizely.decideAsync(userContext,
5156-
FEATURE_MULTI_VARIATE_FEATURE_KEY, (OptimizelyDecision decision) -> {
5155+
optimizely.decideAsync(
5156+
userContext,
5157+
FEATURE_MULTI_VARIATE_FEATURE_KEY,
5158+
Collections.emptyList(),
5159+
(OptimizelyDecision decision) -> {
51575160
try {
51585161
decisionRef.set(decision);
51595162
} catch (Throwable t) {
51605163
errorRef.set(t);
51615164
} finally {
51625165
latch.countDown();
51635166
}
5164-
},
5165-
Collections.emptyList()
5167+
}
51665168
);
51675169

51685170
boolean completed = latch.await(5, TimeUnit.SECONDS);
@@ -5196,12 +5198,14 @@ public void decideForKeysAsyncReturnsDecisions() throws Exception {
51965198
final CountDownLatch latch = new CountDownLatch(1);
51975199
final AtomicReference<Map<String, OptimizelyDecision>> decisionsRef = new AtomicReference<>();
51985200

5199-
optimizely.decideForKeysAsync(userContext,
5200-
flagKeys, (Map<String, OptimizelyDecision> decisions) -> {
5201+
optimizely.decideForKeysAsync(
5202+
userContext,
5203+
flagKeys,
5204+
Collections.emptyList(),
5205+
(Map<String, OptimizelyDecision> decisions) -> {
52015206
decisionsRef.set(decisions);
52025207
latch.countDown();
5203-
},
5204-
Collections.emptyList()
5208+
}
52055209
);
52065210

52075211
assertTrue("Callback should be called within timeout", latch.await(5, TimeUnit.SECONDS));
@@ -5224,11 +5228,13 @@ public void decideAllAsyncReturnsAllDecisions() throws Exception {
52245228
final CountDownLatch latch = new CountDownLatch(1);
52255229
final AtomicReference<Map<String, OptimizelyDecision>> decisionsRef = new AtomicReference<>();
52265230

5227-
optimizely.decideAllAsync(userContext, (Map<String, OptimizelyDecision> decisions) -> {
5228-
decisionsRef.set(decisions);
5229-
latch.countDown();
5230-
},
5231-
Collections.emptyList()
5231+
optimizely.decideAllAsync(
5232+
userContext,
5233+
Collections.emptyList(),
5234+
(Map<String, OptimizelyDecision> decisions) -> {
5235+
decisionsRef.set(decisions);
5236+
latch.countDown();
5237+
}
52325238
);
52335239

52345240
assertTrue("Callback should be called within timeout", latch.await(5, TimeUnit.SECONDS));

core-httpclient-impl/src/main/java/com/optimizely/ab/cmab/DefaultCmabClient.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ public class DefaultCmabClient implements CmabClient {
4343
private static final Logger logger = LoggerFactory.getLogger(DefaultCmabClient.class);
4444
private static final int DEFAULT_TIMEOUT_MS = 10000;
4545

46-
private static final String CMAB_PREDICTION_ENDPOINT = "https://prediction.cmab.optimizely.com/predict/%s";
47-
4846
private final OptimizelyHttpClient httpClient;
4947
private final RetryConfig retryConfig;
5048

@@ -78,7 +76,7 @@ private OptimizelyHttpClient createDefaultHttpClient() {
7876
@Override
7977
public String fetchDecision(String ruleId, String userId, Map<String, Object> attributes, String cmabUuid) {
8078
// Implementation will use this.httpClient and this.retryConfig
81-
String url = String.format(CMAB_PREDICTION_ENDPOINT, ruleId);
79+
String url = String.format(CmabClientHelper.CMAB_PREDICTION_ENDPOINT, ruleId);
8280
String requestBody = CmabClientHelper.buildRequestJson(userId, ruleId, attributes, cmabUuid);
8381

8482
// Use retry logic if configured, otherwise single request

0 commit comments

Comments
 (0)