Skip to content

Commit 9c8dd8f

Browse files
update: modify OptimizelyUserContext to change optimizely field to package-private and add copyright notice to DecisionPath
1 parent 690379c commit 9c8dd8f

File tree

5 files changed

+20
-310
lines changed

5 files changed

+20
-310
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1949,7 +1949,7 @@ public Builder withODPManager(ODPManager odpManager) {
19491949

19501950
public Builder withCmabClient(CmabClient cmabClient) {
19511951
int DEFAULT_MAX_SIZE = 1000;
1952-
int DEFAULT_CMAB_CACHE_TIMEOUT = 30 * 60 * 1000;
1952+
int DEFAULT_CMAB_CACHE_TIMEOUT = 30 * 60;
19531953
DefaultLRUCache<CmabCacheValue> cmabCache = new DefaultLRUCache<>(DEFAULT_MAX_SIZE, DEFAULT_CMAB_CACHE_TIMEOUT);
19541954
CmabServiceOptions cmabServiceOptions = new CmabServiceOptions(logger, cmabCache, cmabClient);
19551955
DefaultCmabService defaultCmabService = new DefaultCmabService(cmabServiceOptions);

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

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public class OptimizelyUserContext {
5050
private List<String> qualifiedSegments;
5151

5252
@Nonnull
53-
private final Optimizely optimizely;
53+
final Optimizely optimizely;
5454

5555
private static final Logger logger = LoggerFactory.getLogger(OptimizelyUserContext.class);
5656

@@ -205,42 +205,6 @@ public Map<String, OptimizelyDecision> decideAll() {
205205
return decideAll(Collections.emptyList());
206206
}
207207

208-
/**
209-
* Returns a decision result ({@link OptimizelyDecision}) for a given flag key and a user context,
210-
* which contains all data required to deliver the flag. This method skips CMAB logic.
211-
* backward compatibility support for android sync decisions
212-
* @param key A flag key for which a decision will be made.
213-
* @param options A list of options for decision-making.
214-
* @return A decision result.
215-
*/
216-
public OptimizelyDecision decideSync(@Nonnull String key,
217-
@Nonnull List<OptimizelyDecideOption> options) {
218-
return optimizely.decideSync(copy(), key, options);
219-
}
220-
221-
/**
222-
* Returns a key-map of decision results ({@link OptimizelyDecision}) for multiple flag keys and a user context.
223-
* This method skips CMAB logic.
224-
* backward compatibility support for android sync decisions
225-
* @param keys A list of flag keys for which decisions will be made.
226-
* @param options A list of options for decision-making.
227-
* @return All decision results mapped by flag keys.
228-
*/
229-
public Map<String, OptimizelyDecision> decideForKeysSync(@Nonnull List<String> keys,
230-
@Nonnull List<OptimizelyDecideOption> options) {
231-
return optimizely.decideForKeysSync(copy(), keys, options);
232-
}
233-
234-
/**
235-
* Returns a key-map of decision results ({@link OptimizelyDecision}) for all active flag keys.
236-
* This method skips CMAB logic.
237-
* backward compatibility support for android sync decisions
238-
* @param options A list of options for decision-making.
239-
* @return All decision results mapped by flag keys.
240-
*/
241-
public Map<String, OptimizelyDecision> decideAllSync(@Nonnull List<OptimizelyDecideOption> options) {
242-
return optimizely.decideAllSync(copy(), options);
243-
}
244208

245209
/**
246210
* Returns a decision result asynchronously for a given flag key and a user context.

core-api/src/main/java/com/optimizely/ab/bucketing/DecisionPath.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
/****************************************************************************
2+
* Copyright 2025 Optimizely, Inc. and contributors *
3+
* *
4+
* Licensed under the Apache License, Version 2.0 (the "License"); *
5+
* you may not use this file except in compliance with the License. *
6+
* You may obtain a copy of the License at *
7+
* *
8+
* http://www.apache.org/licenses/LICENSE-2.0 *
9+
* *
10+
* Unless required by applicable law or agreed to in writing, software *
11+
* distributed under the License is distributed on an "AS IS" BASIS, *
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13+
* See the License for the specific language governing permissions and *
14+
* limitations under the License. *
15+
***************************************************************************/
116
package com.optimizely.ab.bucketing;
217

318
public enum DecisionPath {

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

Lines changed: 0 additions & 269 deletions
Original file line numberDiff line numberDiff line change
@@ -2271,275 +2271,6 @@ public void decide_all_with_holdout() throws Exception {
22712271
logbackVerifier.expectMessage(Level.INFO, expectedReason);
22722272
}
22732273

2274-
@Test
2275-
public void decideSync_featureTest() {
2276-
optimizely = new Optimizely.Builder()
2277-
.withDatafile(datafile)
2278-
.withEventProcessor(new ForwardingEventProcessor(eventHandler, null))
2279-
.build();
2280-
2281-
String flagKey = "feature_2";
2282-
String experimentKey = "exp_no_audience";
2283-
String variationKey = "variation_with_traffic";
2284-
String experimentId = "10420810910";
2285-
String variationId = "10418551353";
2286-
OptimizelyJSON variablesExpected = optimizely.getAllFeatureVariables(flagKey, userId);
2287-
2288-
OptimizelyUserContext user = optimizely.createUserContext(userId);
2289-
OptimizelyDecision decision = user.decideSync(flagKey, Collections.emptyList());
2290-
2291-
assertEquals(decision.getVariationKey(), variationKey);
2292-
assertTrue(decision.getEnabled());
2293-
assertEquals(decision.getVariables().toMap(), variablesExpected.toMap());
2294-
assertEquals(decision.getRuleKey(), experimentKey);
2295-
assertEquals(decision.getFlagKey(), flagKey);
2296-
assertEquals(decision.getUserContext(), user);
2297-
assertTrue(decision.getReasons().isEmpty());
2298-
2299-
DecisionMetadata metadata = new DecisionMetadata.Builder()
2300-
.setFlagKey(flagKey)
2301-
.setRuleKey(experimentKey)
2302-
.setRuleType(FeatureDecision.DecisionSource.FEATURE_TEST.toString())
2303-
.setVariationKey(variationKey)
2304-
.setEnabled(true)
2305-
.build();
2306-
eventHandler.expectImpression(experimentId, variationId, userId, Collections.emptyMap(), metadata);
2307-
}
2308-
2309-
@Test
2310-
public void decideForKeysSync_multipleFlags() {
2311-
String flagKey1 = "feature_1";
2312-
String flagKey2 = "feature_2";
2313-
2314-
List<String> flagKeys = Arrays.asList(flagKey1, flagKey2);
2315-
OptimizelyJSON variablesExpected1 = optimizely.getAllFeatureVariables(flagKey1, userId);
2316-
OptimizelyJSON variablesExpected2 = optimizely.getAllFeatureVariables(flagKey2, userId);
2317-
2318-
OptimizelyUserContext user = optimizely.createUserContext(userId, Collections.singletonMap("gender", "f"));
2319-
Map<String, OptimizelyDecision> decisions = user.decideForKeysSync(flagKeys, Collections.emptyList());
2320-
2321-
assertEquals(decisions.size(), 2);
2322-
2323-
assertEquals(
2324-
decisions.get(flagKey1),
2325-
new OptimizelyDecision("a",
2326-
true,
2327-
variablesExpected1,
2328-
"exp_with_audience",
2329-
flagKey1,
2330-
user,
2331-
Collections.emptyList()));
2332-
assertEquals(
2333-
decisions.get(flagKey2),
2334-
new OptimizelyDecision("variation_with_traffic",
2335-
true,
2336-
variablesExpected2,
2337-
"exp_no_audience",
2338-
flagKey2,
2339-
user,
2340-
Collections.emptyList()));
2341-
}
2342-
2343-
@Test
2344-
public void decideForKeysSync_withOptions() {
2345-
String flagKey1 = "feature_1";
2346-
String flagKey2 = "feature_2";
2347-
2348-
List<String> flagKeys = Arrays.asList(flagKey1, flagKey2);
2349-
List<OptimizelyDecideOption> options = Arrays.asList(OptimizelyDecideOption.EXCLUDE_VARIABLES);
2350-
2351-
OptimizelyUserContext user = optimizely.createUserContext(userId, Collections.singletonMap("gender", "f"));
2352-
Map<String, OptimizelyDecision> decisions = user.decideForKeysSync(flagKeys, options);
2353-
2354-
assertEquals(decisions.size(), 2);
2355-
2356-
// Both decisions should have empty variables due to EXCLUDE_VARIABLES option
2357-
OptimizelyDecision decision1 = decisions.get(flagKey1);
2358-
OptimizelyDecision decision2 = decisions.get(flagKey2);
2359-
2360-
assertTrue(decision1.getVariables().toMap().isEmpty());
2361-
assertTrue(decision2.getVariables().toMap().isEmpty());
2362-
assertEquals(decision1.getVariationKey(), "a");
2363-
assertEquals(decision2.getVariationKey(), "variation_with_traffic");
2364-
}
2365-
2366-
@Test
2367-
public void decideAllSync_allFlags() {
2368-
EventProcessor mockEventProcessor = mock(EventProcessor.class);
2369-
2370-
optimizely = new Optimizely.Builder()
2371-
.withDatafile(datafile)
2372-
.withEventProcessor(mockEventProcessor)
2373-
.build();
2374-
2375-
String flagKey1 = "feature_1";
2376-
String flagKey2 = "feature_2";
2377-
String flagKey3 = "feature_3";
2378-
Map<String, Object> attributes = Collections.singletonMap("gender", "f");
2379-
2380-
OptimizelyJSON variablesExpected1 = optimizely.getAllFeatureVariables(flagKey1, userId);
2381-
OptimizelyJSON variablesExpected2 = optimizely.getAllFeatureVariables(flagKey2, userId);
2382-
OptimizelyJSON variablesExpected3 = new OptimizelyJSON(Collections.emptyMap());
2383-
2384-
OptimizelyUserContext user = optimizely.createUserContext(userId, attributes);
2385-
Map<String, OptimizelyDecision> decisions = user.decideAllSync(Collections.emptyList());
2386-
assertEquals(decisions.size(), 3);
2387-
2388-
assertEquals(
2389-
decisions.get(flagKey1),
2390-
new OptimizelyDecision(
2391-
"a",
2392-
true,
2393-
variablesExpected1,
2394-
"exp_with_audience",
2395-
flagKey1,
2396-
user,
2397-
Collections.emptyList()));
2398-
assertEquals(
2399-
decisions.get(flagKey2),
2400-
new OptimizelyDecision(
2401-
"variation_with_traffic",
2402-
true,
2403-
variablesExpected2,
2404-
"exp_no_audience",
2405-
flagKey2,
2406-
user,
2407-
Collections.emptyList()));
2408-
assertEquals(
2409-
decisions.get(flagKey3),
2410-
new OptimizelyDecision(
2411-
null,
2412-
false,
2413-
variablesExpected3,
2414-
null,
2415-
flagKey3,
2416-
user,
2417-
Collections.emptyList()));
2418-
2419-
ArgumentCaptor<ImpressionEvent> argumentCaptor = ArgumentCaptor.forClass(ImpressionEvent.class);
2420-
verify(mockEventProcessor, times(3)).process(argumentCaptor.capture());
2421-
2422-
List<ImpressionEvent> sentEvents = argumentCaptor.getAllValues();
2423-
assertEquals(sentEvents.size(), 3);
2424-
2425-
assertEquals(sentEvents.get(0).getExperimentKey(), "exp_with_audience");
2426-
assertEquals(sentEvents.get(0).getVariationKey(), "a");
2427-
assertEquals(sentEvents.get(0).getUserContext().getUserId(), userId);
2428-
2429-
assertEquals(sentEvents.get(1).getExperimentKey(), "exp_no_audience");
2430-
assertEquals(sentEvents.get(1).getVariationKey(), "variation_with_traffic");
2431-
assertEquals(sentEvents.get(1).getUserContext().getUserId(), userId);
2432-
2433-
assertEquals(sentEvents.get(2).getExperimentKey(), "");
2434-
assertEquals(sentEvents.get(2).getUserContext().getUserId(), userId);
2435-
}
2436-
2437-
@Test
2438-
public void decideAllSync_withOptions() {
2439-
String flagKey1 = "feature_1";
2440-
OptimizelyJSON variablesExpected1 = optimizely.getAllFeatureVariables(flagKey1, userId);
2441-
2442-
OptimizelyUserContext user = optimizely.createUserContext(userId, Collections.singletonMap("gender", "f"));
2443-
Map<String, OptimizelyDecision> decisions = user.decideAllSync(Arrays.asList(OptimizelyDecideOption.ENABLED_FLAGS_ONLY));
2444-
2445-
assertEquals(decisions.size(), 2); // Only enabled flags
2446-
2447-
assertEquals(
2448-
decisions.get(flagKey1),
2449-
new OptimizelyDecision(
2450-
"a",
2451-
true,
2452-
variablesExpected1,
2453-
"exp_with_audience",
2454-
flagKey1,
2455-
user,
2456-
Collections.emptyList()));
2457-
}
2458-
2459-
@Test
2460-
public void decideAllSync_ups_batching() throws Exception {
2461-
UserProfileService ups = mock(UserProfileService.class);
2462-
2463-
optimizely = new Optimizely.Builder()
2464-
.withDatafile(datafile)
2465-
.withUserProfileService(ups)
2466-
.build();
2467-
2468-
Map<String, Object> attributes = Collections.singletonMap("gender", "f");
2469-
2470-
OptimizelyUserContext user = optimizely.createUserContext(userId, attributes);
2471-
Map<String, OptimizelyDecision> decisions = user.decideAllSync(Collections.emptyList());
2472-
2473-
assertEquals(decisions.size(), 3);
2474-
2475-
ArgumentCaptor<Map> argumentCaptor = ArgumentCaptor.forClass(Map.class);
2476-
2477-
verify(ups, times(1)).lookup(userId);
2478-
verify(ups, times(1)).save(argumentCaptor.capture());
2479-
2480-
Map<String, Object> savedUps = argumentCaptor.getValue();
2481-
UserProfile savedProfile = UserProfileUtils.convertMapToUserProfile(savedUps);
2482-
2483-
assertEquals(savedProfile.userId, userId);
2484-
}
2485-
2486-
@Test
2487-
public void decideSync_sdkNotReady() {
2488-
String flagKey = "feature_1";
2489-
2490-
Optimizely optimizely = new Optimizely.Builder().build();
2491-
OptimizelyUserContext user = optimizely.createUserContext(userId);
2492-
OptimizelyDecision decision = user.decideSync(flagKey, Collections.emptyList());
2493-
2494-
assertNull(decision.getVariationKey());
2495-
assertFalse(decision.getEnabled());
2496-
assertTrue(decision.getVariables().isEmpty());
2497-
assertEquals(decision.getFlagKey(), flagKey);
2498-
assertEquals(decision.getUserContext(), user);
2499-
2500-
assertEquals(decision.getReasons().size(), 1);
2501-
assertEquals(decision.getReasons().get(0), DecisionMessage.SDK_NOT_READY.reason());
2502-
}
2503-
2504-
@Test
2505-
public void decideForKeysSync_sdkNotReady() {
2506-
List<String> flagKeys = Arrays.asList("feature_1");
2507-
2508-
Optimizely optimizely = new Optimizely.Builder().build();
2509-
OptimizelyUserContext user = optimizely.createUserContext(userId);
2510-
Map<String, OptimizelyDecision> decisions = user.decideForKeysSync(flagKeys, Collections.emptyList());
2511-
2512-
assertEquals(decisions.size(), 0);
2513-
}
2514-
@Test
2515-
public void decideSync_bypassUPS() throws Exception {
2516-
String flagKey = "feature_2"; // embedding experiment: "exp_no_audience"
2517-
String experimentId = "10420810910"; // "exp_no_audience"
2518-
String variationId1 = "10418551353";
2519-
String variationId2 = "10418510624";
2520-
String variationKey1 = "variation_with_traffic";
2521-
String variationKey2 = "variation_no_traffic";
2522-
2523-
UserProfileService ups = mock(UserProfileService.class);
2524-
when(ups.lookup(userId)).thenReturn(createUserProfileMap(experimentId, variationId2));
2525-
2526-
optimizely = new Optimizely.Builder()
2527-
.withDatafile(datafile)
2528-
.withUserProfileService(ups)
2529-
.build();
2530-
2531-
OptimizelyUserContext user = optimizely.createUserContext(userId);
2532-
OptimizelyDecision decision = user.decideSync(flagKey, Collections.emptyList());
2533-
// should return variationId2 set by UPS
2534-
assertEquals(decision.getVariationKey(), variationKey2);
2535-
2536-
decision = user.decideSync(flagKey, Arrays.asList(OptimizelyDecideOption.IGNORE_USER_PROFILE_SERVICE));
2537-
// should ignore variationId2 set by UPS and return variationId1
2538-
assertEquals(decision.getVariationKey(), variationKey1);
2539-
// also should not save either
2540-
verify(ups, never()).save(anyObject());
2541-
}
2542-
25432274
@Test
25442275
public void decideAsync_featureTest() throws InterruptedException {
25452276
optimizely = new Optimizely.Builder()

core-api/src/test/java/com/optimizely/ab/internal/DefaultLRUCacheTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@
1616
*/
1717
package com.optimizely.ab.internal;
1818

19-
import org.junit.Test;
20-
2119
import java.util.Arrays;
2220
import java.util.List;
2321

24-
import static org.junit.Assert.*;
22+
import static org.junit.Assert.assertEquals;
23+
import static org.junit.Assert.assertNull;
24+
import org.junit.Test;
2525

2626
public class DefaultLRUCacheTest {
2727

0 commit comments

Comments
 (0)