Skip to content

Commit c8c4198

Browse files
update: refactor decision methods in Optimizely for improved CMAB handling and backward compatibility
1 parent 528a536 commit c8c4198

File tree

1 file changed

+79
-100
lines changed

1 file changed

+79
-100
lines changed

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

Lines changed: 79 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ private Optimizely(@Nonnull EventHandler eventHandler,
153153
@Nonnull List<OptimizelyDecideOption> defaultDecideOptions,
154154
@Nullable ODPManager odpManager,
155155
@Nonnull CmabService cmabService
156-
) {
156+
) {
157157
this.eventHandler = eventHandler;
158158
this.eventProcessor = eventProcessor;
159159
this.errorHandler = errorHandler;
@@ -349,14 +349,14 @@ private boolean sendImpression(@Nonnull ProjectConfig projectConfig,
349349

350350
// Legacy API methods only apply to the Experiment type and not to Holdout.
351351
boolean isExperimentType = experiment instanceof Experiment;
352-
352+
353353
// Kept For backwards compatibility.
354354
// This notification is deprecated and the new DecisionNotifications
355355
// are sent via their respective method calls.
356356
if (notificationCenter.getNotificationManager(ActivateNotification.class).size() > 0 && isExperimentType) {
357357
LogEvent impressionEvent = EventFactory.createLogEvent(userEvent);
358358
ActivateNotification activateNotification = new ActivateNotification(
359-
(Experiment)experiment, userId, filteredAttributes, variation, impressionEvent);
359+
(Experiment) experiment, userId, filteredAttributes, variation, impressionEvent);
360360
notificationCenter.send(activateNotification);
361361
}
362362
return true;
@@ -1286,20 +1286,6 @@ private OptimizelyUserContext createUserContextCopy(@Nonnull String userId, @Non
12861286
return new OptimizelyUserContext(this, userId, attributes, Collections.EMPTY_MAP, null, false);
12871287
}
12881288

1289-
OptimizelyDecision decide(@Nonnull OptimizelyUserContext user,
1290-
@Nonnull String key,
1291-
@Nonnull List<OptimizelyDecideOption> options) {
1292-
ProjectConfig projectConfig = getProjectConfig();
1293-
if (projectConfig == null) {
1294-
return OptimizelyDecision.newErrorDecision(key, user, DecisionMessage.SDK_NOT_READY.reason());
1295-
}
1296-
1297-
List<OptimizelyDecideOption> allOptions = getAllOptions(options);
1298-
allOptions.remove(OptimizelyDecideOption.ENABLED_FLAGS_ONLY);
1299-
1300-
return decideForKeys(user, Arrays.asList(key), allOptions, true).get(key);
1301-
}
1302-
13031289
private OptimizelyDecision createOptimizelyDecision(
13041290
OptimizelyUserContext user,
13051291
String flagKey,
@@ -1387,17 +1373,72 @@ private OptimizelyDecision createOptimizelyDecision(
13871373
reasonsToReport);
13881374
}
13891375

1376+
OptimizelyDecision decide(@Nonnull OptimizelyUserContext user,
1377+
@Nonnull String key,
1378+
@Nonnull List<OptimizelyDecideOption> options) {
1379+
return decideInternal(user, key, options, DecisionPath.WITH_CMAB);
1380+
}
1381+
13901382
Map<String, OptimizelyDecision> decideForKeys(@Nonnull OptimizelyUserContext user,
13911383
@Nonnull List<String> keys,
13921384
@Nonnull List<OptimizelyDecideOption> options) {
1393-
return decideForKeys(user, keys, options, false);
1385+
return decideForKeysInternal(user, keys, options, false, DecisionPath.WITH_CMAB);
1386+
}
1387+
1388+
Map<String, OptimizelyDecision> decideAll(@Nonnull OptimizelyUserContext user,
1389+
@Nonnull List<OptimizelyDecideOption> options) {
1390+
return decideAllInternal(user, options, DecisionPath.WITH_CMAB);
1391+
}
1392+
1393+
/**
1394+
* Returns a decision result ({@link OptimizelyDecision}) for a given flag key and a user context,
1395+
* skipping CMAB logic and using only traditional A/B testing.
1396+
* This will be called by mobile apps which will make synchronous decisions only (for backward compatibility with android-sdk)
1397+
*
1398+
* @param user An OptimizelyUserContext associated with this OptimizelyClient.
1399+
* @param key A flag key for which a decision will be made.
1400+
* @param options A list of options for decision-making.
1401+
* @return A decision result using traditional A/B testing logic only.
1402+
*/
1403+
OptimizelyDecision decideSync(@Nonnull OptimizelyUserContext user,
1404+
@Nonnull String key,
1405+
@Nonnull List<OptimizelyDecideOption> options) {
1406+
return decideInternal(user, key, options, DecisionPath.WITHOUT_CMAB);
1407+
}
1408+
1409+
/**
1410+
* Returns decision results for multiple flag keys, skipping CMAB logic and using only traditional A/B testing.
1411+
* This will be called by mobile apps which will make synchronous decisions only (for backward compatibility with android-sdk)
1412+
*
1413+
* @param user An OptimizelyUserContext associated with this OptimizelyClient.
1414+
* @param keys A list of flag keys for which decisions will be made.
1415+
* @param options A list of options for decision-making.
1416+
* @return All decision results mapped by flag keys, using traditional A/B testing logic only.
1417+
*/
1418+
Map<String, OptimizelyDecision> decideForKeysSync(@Nonnull OptimizelyUserContext user,
1419+
@Nonnull List<String> keys,
1420+
@Nonnull List<OptimizelyDecideOption> options) {
1421+
return decideForKeysInternal(user, keys, options, false, DecisionPath.WITHOUT_CMAB);
1422+
}
1423+
1424+
/**
1425+
* Returns decision results for all active flag keys, skipping CMAB logic and using only traditional A/B testing.
1426+
* This will be called by mobile apps which will make synchronous decisions only (for backward compatibility with android-sdk)
1427+
*
1428+
* @param user An OptimizelyUserContext associated with this OptimizelyClient.
1429+
* @param options A list of options for decision-making.
1430+
* @return All decision results mapped by flag keys, using traditional A/B testing logic only.
1431+
*/
1432+
Map<String, OptimizelyDecision> decideAllSync(@Nonnull OptimizelyUserContext user,
1433+
@Nonnull List<OptimizelyDecideOption> options) {
1434+
return decideAllInternal(user, options, DecisionPath.WITHOUT_CMAB);
13941435
}
13951436

1396-
private Map<String, OptimizelyDecision> decideForKeys(@Nonnull OptimizelyUserContext user,
1397-
@Nonnull List<String> keys,
1398-
@Nonnull List<OptimizelyDecideOption> options,
1399-
boolean ignoreDefaultOptions,
1400-
DecisionPath decisionPath) {
1437+
private Map<String, OptimizelyDecision> decideForKeysInternal(@Nonnull OptimizelyUserContext user,
1438+
@Nonnull List<String> keys,
1439+
@Nonnull List<OptimizelyDecideOption> options,
1440+
boolean ignoreDefaultOptions,
1441+
DecisionPath decisionPath) {
14011442
Map<String, OptimizelyDecision> decisionMap = new HashMap<>();
14021443

14031444
ProjectConfig projectConfig = getProjectConfig();
@@ -1481,43 +1522,28 @@ private Map<String, OptimizelyDecision> decideForKeys(@Nonnull OptimizelyUserCon
14811522
return decisionMap;
14821523
}
14831524

1484-
private Map<String, OptimizelyDecision> decideForKeys(@Nonnull OptimizelyUserContext user,
1485-
@Nonnull List<String> keys,
1486-
@Nonnull List<OptimizelyDecideOption> options,
1487-
boolean ignoreDefaultOptions) {
1488-
return decideForKeys(user, keys, options, ignoreDefaultOptions, DecisionPath.WITH_CMAB);
1489-
}
1490-
1491-
Map<String, OptimizelyDecision> decideAll(@Nonnull OptimizelyUserContext user,
1492-
@Nonnull List<OptimizelyDecideOption> options) {
1525+
private Map<String, OptimizelyDecision> decideAllInternal(@Nonnull OptimizelyUserContext user,
1526+
@Nonnull List<OptimizelyDecideOption> options,
1527+
@Nonnull DecisionPath decisionPath) {
14931528
Map<String, OptimizelyDecision> decisionMap = new HashMap<>();
14941529

14951530
ProjectConfig projectConfig = getProjectConfig();
14961531
if (projectConfig == null) {
1497-
logger.error("Optimizely instance is not valid, failing isFeatureEnabled call.");
1532+
logger.error("Optimizely instance is not valid, failing decideAllSync call.");
14981533
return decisionMap;
14991534
}
15001535

15011536
List<FeatureFlag> allFlags = projectConfig.getFeatureFlags();
15021537
List<String> allFlagKeys = new ArrayList<>();
15031538
for (int i = 0; i < allFlags.size(); i++) allFlagKeys.add(allFlags.get(i).getKey());
15041539

1505-
return decideForKeys(user, allFlagKeys, options);
1540+
return decideForKeysInternal(user, allFlagKeys, options, false, decisionPath);
15061541
}
15071542

1508-
/**
1509-
* Returns a decision result ({@link OptimizelyDecision}) for a given flag key and a user context,
1510-
* skipping CMAB logic and using only traditional A/B testing.
1511-
* This will be called by mobile apps which will make synchronous decisions only (for backward compatibility with android-sdk)
1512-
*
1513-
* @param user An OptimizelyUserContext associated with this OptimizelyClient.
1514-
* @param key A flag key for which a decision will be made.
1515-
* @param options A list of options for decision-making.
1516-
* @return A decision result using traditional A/B testing logic only.
1517-
*/
1518-
OptimizelyDecision decideSync(@Nonnull OptimizelyUserContext user,
1519-
@Nonnull String key,
1520-
@Nonnull List<OptimizelyDecideOption> options) {
1543+
private OptimizelyDecision decideInternal(@Nonnull OptimizelyUserContext user,
1544+
@Nonnull String key,
1545+
@Nonnull List<OptimizelyDecideOption> options,
1546+
@Nonnull DecisionPath decisionPath) {
15211547
ProjectConfig projectConfig = getProjectConfig();
15221548
if (projectConfig == null) {
15231549
return OptimizelyDecision.newErrorDecision(key, user, DecisionMessage.SDK_NOT_READY.reason());
@@ -1526,54 +1552,7 @@ OptimizelyDecision decideSync(@Nonnull OptimizelyUserContext user,
15261552
List<OptimizelyDecideOption> allOptions = getAllOptions(options);
15271553
allOptions.remove(OptimizelyDecideOption.ENABLED_FLAGS_ONLY);
15281554

1529-
return decideForKeysSync(user, Arrays.asList(key), allOptions, true).get(key);
1530-
}
1531-
1532-
/**
1533-
* Returns decision results for multiple flag keys, skipping CMAB logic and using only traditional A/B testing.
1534-
* This will be called by mobile apps which will make synchronous decisions only (for backward compatibility with android-sdk)
1535-
*
1536-
* @param user An OptimizelyUserContext associated with this OptimizelyClient.
1537-
* @param keys A list of flag keys for which decisions will be made.
1538-
* @param options A list of options for decision-making.
1539-
* @return All decision results mapped by flag keys, using traditional A/B testing logic only.
1540-
*/
1541-
Map<String, OptimizelyDecision> decideForKeysSync(@Nonnull OptimizelyUserContext user,
1542-
@Nonnull List<String> keys,
1543-
@Nonnull List<OptimizelyDecideOption> options) {
1544-
return decideForKeysSync(user, keys, options, false);
1545-
}
1546-
1547-
private Map<String, OptimizelyDecision> decideForKeysSync(@Nonnull OptimizelyUserContext user,
1548-
@Nonnull List<String> keys,
1549-
@Nonnull List<OptimizelyDecideOption> options,
1550-
boolean ignoreDefaultOptions) {
1551-
return decideForKeys(user, keys, options, ignoreDefaultOptions, DecisionPath.WITHOUT_CMAB);
1552-
}
1553-
1554-
/**
1555-
* Returns decision results for all active flag keys, skipping CMAB logic and using only traditional A/B testing.
1556-
* This will be called by mobile apps which will make synchronous decisions only (for backward compatibility with android-sdk)
1557-
*
1558-
* @param user An OptimizelyUserContext associated with this OptimizelyClient.
1559-
* @param options A list of options for decision-making.
1560-
* @return All decision results mapped by flag keys, using traditional A/B testing logic only.
1561-
*/
1562-
Map<String, OptimizelyDecision> decideAllSync(@Nonnull OptimizelyUserContext user,
1563-
@Nonnull List<OptimizelyDecideOption> options) {
1564-
Map<String, OptimizelyDecision> decisionMap = new HashMap<>();
1565-
1566-
ProjectConfig projectConfig = getProjectConfig();
1567-
if (projectConfig == null) {
1568-
logger.error("Optimizely instance is not valid, failing decideAllSync call.");
1569-
return decisionMap;
1570-
}
1571-
1572-
List<FeatureFlag> allFlags = projectConfig.getFeatureFlags();
1573-
List<String> allFlagKeys = new ArrayList<>();
1574-
for (int i = 0; i < allFlags.size(); i++) allFlagKeys.add(allFlags.get(i).getKey());
1575-
1576-
return decideForKeysSync(user, allFlagKeys, options);
1555+
return decideForKeysInternal(user, Arrays.asList(key), allOptions, true, decisionPath).get(key);
15771556
}
15781557

15791558
//============ decide async ============//
@@ -1582,9 +1561,9 @@ Map<String, OptimizelyDecision> decideAllSync(@Nonnull OptimizelyUserContext use
15821561
* Returns a decision result asynchronously for a given flag key and a user context.
15831562
*
15841563
* @param userContext The user context to make decisions for
1585-
* @param key A flag key for which a decision will be made
1586-
* @param callback A callback to invoke when the decision is available
1587-
* @param options A list of options for decision-making
1564+
* @param key A flag key for which a decision will be made
1565+
* @param callback A callback to invoke when the decision is available
1566+
* @param options A list of options for decision-making
15881567
*/
15891568
void decideAsync(@Nonnull OptimizelyUserContext userContext,
15901569
@Nonnull String key,
@@ -1614,8 +1593,8 @@ void decideForKeysAsync(@Nonnull OptimizelyUserContext userContext,
16141593
* Returns decision results asynchronously for all active flag keys.
16151594
*
16161595
* @param userContext The user context to make decisions for
1617-
* @param callback A callback to invoke when decisions are available
1618-
* @param options A list of options for decision-making
1596+
* @param callback A callback to invoke when decisions are available
1597+
* @param options A list of options for decision-making
16191598
*/
16201599
void decideAllAsync(@Nonnull OptimizelyUserContext userContext,
16211600
@Nonnull List<OptimizelyDecideOption> options,

0 commit comments

Comments
 (0)