Skip to content

Commit 6db2e88

Browse files
update: refactor AsyncDecisionsFetcher to AsyncDecisionFetcher and enhance decision handling
1 parent b0d5090 commit 6db2e88

File tree

3 files changed

+118
-120
lines changed

3 files changed

+118
-120
lines changed

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import com.optimizely.ab.odp.ODPSegmentCallback;
3333
import com.optimizely.ab.odp.ODPSegmentOption;
3434
import com.optimizely.ab.optimizelydecision.AsyncDecisionFetcher;
35-
import com.optimizely.ab.optimizelydecision.AsyncDecisionsFetcher;
3635
import com.optimizely.ab.optimizelydecision.OptimizelyDecideOption;
3736
import com.optimizely.ab.optimizelydecision.OptimizelyDecision;
3837
import com.optimizely.ab.optimizelydecision.OptimizelyDecisionCallback;
@@ -307,7 +306,7 @@ public void decideAsync(@Nonnull String key, @Nonnull OptimizelyDecisionCallback
307306
public void decideForKeysAsync(@Nonnull List<String> keys,
308307
@Nonnull OptimizelyDecisionsCallback callback,
309308
@Nonnull List<OptimizelyDecideOption> options) {
310-
AsyncDecisionsFetcher fetcher = new AsyncDecisionsFetcher(this, keys, options, callback);
309+
AsyncDecisionFetcher fetcher = new AsyncDecisionFetcher(this, keys, options, callback);
311310
fetcher.start();
312311
}
313312

@@ -329,7 +328,7 @@ public void decideForKeysAsync(@Nonnull List<String> keys, @Nonnull OptimizelyDe
329328
*/
330329
public void decideAllAsync(@Nonnull OptimizelyDecisionsCallback callback,
331330
@Nonnull List<OptimizelyDecideOption> options) {
332-
AsyncDecisionsFetcher fetcher = new AsyncDecisionsFetcher(this, null, options, callback, true);
331+
AsyncDecisionFetcher fetcher = new AsyncDecisionFetcher(this, options, callback);
333332
fetcher.start();
334333
}
335334

core-api/src/main/java/com/optimizely/ab/optimizelydecision/AsyncDecisionFetcher.java

Lines changed: 116 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,41 @@
1515
*/
1616
package com.optimizely.ab.optimizelydecision;
1717

18-
import com.optimizely.ab.OptimizelyUserContext;
18+
import java.util.Collections;
19+
import java.util.List;
20+
import java.util.Map;
21+
22+
import javax.annotation.Nonnull;
23+
1924
import org.slf4j.Logger;
2025
import org.slf4j.LoggerFactory;
2126

22-
import javax.annotation.Nonnull;
23-
import java.util.List;
27+
import com.optimizely.ab.OptimizelyUserContext;
2428

2529
/**
26-
* AsyncDecisionFetcher handles asynchronous decision fetching for a single flag key.
30+
* AsyncDecisionFetcher handles asynchronous decision fetching for single or multiple flag keys.
2731
* This class follows the same pattern as ODP's async segment fetching.
2832
*/
2933
public class AsyncDecisionFetcher extends Thread {
3034
private static final Logger logger = LoggerFactory.getLogger(AsyncDecisionFetcher.class);
3135

32-
private final String key;
36+
private final String singleKey;
37+
private final List<String> keys;
3338
private final List<OptimizelyDecideOption> options;
34-
private final OptimizelyDecisionCallback callback;
39+
private final OptimizelyDecisionCallback singleCallback;
40+
private final OptimizelyDecisionsCallback multipleCallback;
3541
private final OptimizelyUserContext userContext;
42+
private final boolean decideAll;
43+
private final FetchType fetchType;
44+
45+
private enum FetchType {
46+
SINGLE_DECISION,
47+
MULTIPLE_DECISIONS,
48+
ALL_DECISIONS
49+
}
3650

3751
/**
38-
* Constructor for async decision fetching.
52+
* Constructor for async single decision fetching.
3953
*
4054
* @param userContext The user context to make decisions for
4155
* @param key The flag key to decide on
@@ -47,27 +61,112 @@ public AsyncDecisionFetcher(@Nonnull OptimizelyUserContext userContext,
4761
@Nonnull List<OptimizelyDecideOption> options,
4862
@Nonnull OptimizelyDecisionCallback callback) {
4963
this.userContext = userContext;
50-
this.key = key;
64+
this.singleKey = key;
65+
this.keys = null;
5166
this.options = options;
52-
this.callback = callback;
67+
this.singleCallback = callback;
68+
this.multipleCallback = null;
69+
this.decideAll = false;
70+
this.fetchType = FetchType.SINGLE_DECISION;
5371

54-
// Set thread name for debugging
5572
setName("AsyncDecisionFetcher-" + key);
73+
setDaemon(true);
74+
}
75+
76+
/**
77+
* Constructor for deciding on specific keys.
78+
*
79+
* @param userContext The user context to make decisions for
80+
* @param keys List of flag keys to decide on
81+
* @param options Decision options
82+
* @param callback Callback to invoke when decisions are ready
83+
*/
84+
public AsyncDecisionFetcher(@Nonnull OptimizelyUserContext userContext,
85+
@Nonnull List<String> keys,
86+
@Nonnull List<OptimizelyDecideOption> options,
87+
@Nonnull OptimizelyDecisionsCallback callback) {
88+
this.userContext = userContext;
89+
this.singleKey = null;
90+
this.keys = keys;
91+
this.options = options;
92+
this.singleCallback = null;
93+
this.multipleCallback = callback;
94+
this.decideAll = false;
95+
this.fetchType = FetchType.MULTIPLE_DECISIONS;
5696

57-
// Set as daemon thread so it doesn't prevent JVM shutdown
97+
setName("AsyncDecisionFetcher-keys");
98+
setDaemon(true);
99+
}
100+
101+
/**
102+
* Constructor for deciding on all flags.
103+
*
104+
* @param userContext The user context to make decisions for
105+
* @param options Decision options
106+
* @param callback Callback to invoke when decisions are ready
107+
*/
108+
public AsyncDecisionFetcher(@Nonnull OptimizelyUserContext userContext,
109+
@Nonnull List<OptimizelyDecideOption> options,
110+
@Nonnull OptimizelyDecisionsCallback callback) {
111+
this.userContext = userContext;
112+
this.singleKey = null;
113+
this.keys = null;
114+
this.options = options;
115+
this.singleCallback = null;
116+
this.multipleCallback = callback;
117+
this.decideAll = true;
118+
this.fetchType = FetchType.ALL_DECISIONS;
119+
120+
setName("AsyncDecisionFetcher-all");
58121
setDaemon(true);
59122
}
60123

61124
@Override
62125
public void run() {
63126
try {
64-
OptimizelyDecision decision = userContext.decide(key, options);
65-
callback.onCompleted(decision);
127+
switch (fetchType) {
128+
case SINGLE_DECISION:
129+
handleSingleDecision();
130+
break;
131+
case MULTIPLE_DECISIONS:
132+
handleMultipleDecisions();
133+
break;
134+
case ALL_DECISIONS:
135+
handleAllDecisions();
136+
break;
137+
}
66138
} catch (Exception e) {
67-
logger.error("Error in async decision fetching for key: " + key, e);
68-
// Create an error decision and pass it to the callback
69-
OptimizelyDecision errorDecision = createErrorDecision(key, e.getMessage());
70-
callback.onCompleted(errorDecision);
139+
logger.error("Error in async decision fetching", e);
140+
handleError(e);
141+
}
142+
}
143+
144+
private void handleSingleDecision() {
145+
OptimizelyDecision decision = userContext.decide(singleKey, options);
146+
singleCallback.onCompleted(decision);
147+
}
148+
149+
private void handleMultipleDecisions() {
150+
Map<String, OptimizelyDecision> decisions = userContext.decideForKeys(keys, options);
151+
multipleCallback.onCompleted(decisions);
152+
}
153+
154+
private void handleAllDecisions() {
155+
Map<String, OptimizelyDecision> decisions = userContext.decideAll(options);
156+
multipleCallback.onCompleted(decisions);
157+
}
158+
159+
private void handleError(Exception e) {
160+
switch (fetchType) {
161+
case SINGLE_DECISION:
162+
OptimizelyDecision errorDecision = createErrorDecision(singleKey, e.getMessage());
163+
singleCallback.onCompleted(errorDecision);
164+
break;
165+
case MULTIPLE_DECISIONS:
166+
case ALL_DECISIONS:
167+
// Return empty map on error - this follows the pattern of sync methods
168+
multipleCallback.onCompleted(Collections.emptyMap());
169+
break;
71170
}
72171
}
73172

core-api/src/main/java/com/optimizely/ab/optimizelydecision/AsyncDecisionsFetcher.java

Lines changed: 0 additions & 100 deletions
This file was deleted.

0 commit comments

Comments
 (0)