Skip to content

Commit 045f99c

Browse files
update to load the user profile service asynch and synch. remove inva… (#196)
* update to load the user profile service asynch and synch. remove invalid experiments if started asynch (latest datafile) or used cached datafile. * use a worker thread to clean up the user profile service * add try catch, cleanup unused imports in OptimizelyClient
1 parent 739baf3 commit 045f99c

File tree

4 files changed

+74
-5
lines changed

4 files changed

+74
-5
lines changed

android-sdk/src/main/java/com/optimizely/ab/android/sdk/OptimizelyClient.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,10 @@
2525
import com.optimizely.ab.config.Experiment;
2626
import com.optimizely.ab.config.ProjectConfig;
2727
import com.optimizely.ab.config.Variation;
28-
import com.optimizely.ab.internal.ReservedEventKey;
2928
import com.optimizely.ab.notification.NotificationCenter;
30-
import com.optimizely.ab.notification.NotificationListener;
3129

3230
import org.slf4j.Logger;
3331

34-
import java.util.Collections;
3532
import java.util.HashMap;
3633
import java.util.List;
3734
import java.util.Map;

android-sdk/src/main/java/com/optimizely/ab/android/sdk/OptimizelyManager.java

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import com.optimizely.ab.android.event_handler.EventIntentService;
4040
import com.optimizely.ab.android.user_profile.DefaultUserProfileService;
4141
import com.optimizely.ab.bucketing.UserProfileService;
42+
import com.optimizely.ab.config.ProjectConfig;
4243
import com.optimizely.ab.config.parser.ConfigParseException;
4344
import com.optimizely.ab.error.ErrorHandler;
4445
import com.optimizely.ab.event.EventHandler;
@@ -50,6 +51,8 @@
5051

5152
import java.io.IOException;
5253
import java.io.InputStream;
54+
import java.util.Map;
55+
import java.util.Set;
5356

5457
/**
5558
* Handles loading the Optimizely data file
@@ -156,10 +159,16 @@ protected OptimizelyClient initialize(@NonNull Context context,@Nullable String
156159
return optimizelyClient;
157160
}
158161
try {
159-
if(datafile!=null)
162+
if(datafile!=null) {
163+
if (getUserProfileService() instanceof DefaultUserProfileService) {
164+
DefaultUserProfileService defaultUserProfileService = (DefaultUserProfileService) getUserProfileService();
165+
defaultUserProfileService.start();
166+
}
160167
optimizelyClient = buildOptimizely(context, datafile);
161-
else
168+
}
169+
else {
162170
logger.error("Invalid datafile");
171+
}
163172
} catch (ConfigParseException e) {
164173
logger.error("Unable to parse compiled data file", e);
165174
} catch (Exception e) {
@@ -192,8 +201,13 @@ public OptimizelyClient initialize(@NonNull Context context, @RawRes Integer dat
192201
try {
193202

194203
String datafile;
204+
Boolean datafileInCache = isDatafileCached(context);
195205
datafile = getDatafile(context, datafileRes);
206+
196207
optimizelyClient = initialize(context, datafile, true);
208+
if (datafileInCache) {
209+
cleanupUserProfileCache(getUserProfileService());
210+
}
197211
}catch (NullPointerException e){
198212
logger.error("Unable to find compiled data file in raw resource",e);
199213
}
@@ -202,6 +216,36 @@ public OptimizelyClient initialize(@NonNull Context context, @RawRes Integer dat
202216
return optimizelyClient;
203217
}
204218

219+
private void cleanupUserProfileCache(UserProfileService userProfileService) {
220+
final DefaultUserProfileService defaultUserProfileService;
221+
if (userProfileService instanceof DefaultUserProfileService) {
222+
defaultUserProfileService = (DefaultUserProfileService)userProfileService;
223+
}
224+
else {
225+
return;
226+
}
227+
228+
final ProjectConfig config = optimizelyClient.getProjectConfig();
229+
if (config == null) {
230+
return;
231+
}
232+
233+
new Thread(new Runnable() {
234+
@Override
235+
public void run() {
236+
try {
237+
Set<String> experimentIds = config.getExperimentIdMapping().keySet();
238+
239+
defaultUserProfileService.removeInvalidExperiments(experimentIds);
240+
}
241+
catch (Exception e) {
242+
logger.error("Error removing invalid experiments from default user profile service.", e);
243+
}
244+
}
245+
}).start();
246+
247+
}
248+
205249
/** This function will first try to get datafile from Cache, if file is not cached yet
206250
* than it will read from Raw file
207251
* @param context
@@ -366,6 +410,7 @@ void injectOptimizely(@NonNull final Context context, final @NonNull UserProfile
366410
((DefaultUserProfileService) userProfileService).startInBackground(new DefaultUserProfileService.StartCallback() {
367411
@Override
368412
public void onStartComplete(UserProfileService userProfileService) {
413+
cleanupUserProfileCache(userProfileService);
369414
if (optimizelyStartListener != null) {
370415
logger.info("Sending Optimizely instance to listener");
371416
notifyStartListener();

user-profile/src/main/java/com/optimizely/ab/android/user_profile/DefaultUserProfileService.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.slf4j.LoggerFactory;
3131

3232
import java.util.Map;
33+
import java.util.Set;
3334
import java.util.concurrent.ConcurrentHashMap;
3435
import java.util.concurrent.Executors;
3536

@@ -140,6 +141,14 @@ public void remove(String userId) {
140141
userProfileCache.remove(userId);
141142
}
142143

144+
public void removeInvalidExperiments(Set<String> validExperiments) {
145+
try {
146+
userProfileCache.removeInvalidExperiments(validExperiments);
147+
}
148+
catch (Exception e) {
149+
logger.error("Error calling userProfileCache to remove invalid experiments", e);
150+
}
151+
}
143152
/**
144153
* Remove a decision from a user profile.
145154
*

user-profile/src/main/java/com/optimizely/ab/android/user_profile/UserProfileCache.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
import java.util.Iterator;
3333
import java.util.Map;
34+
import java.util.Set;
3435
import java.util.concurrent.ConcurrentHashMap;
3536
import java.util.concurrent.Executor;
3637

@@ -175,6 +176,23 @@ void remove(String userId, String experimentId) {
175176
}
176177
}
177178

179+
/**
180+
* Remove experiments that are no longer valid
181+
* @param validExperimentIds list of valid experiment ids.
182+
*/
183+
public void removeInvalidExperiments(Set<String> validExperimentIds) {
184+
for (String userId : memoryCache.keySet()) {
185+
Map<String, Object> maps = memoryCache.get(userId);
186+
Map<String, Map<String, String>> experimentBucketMap =
187+
(ConcurrentHashMap<String, Map<String, String>>) maps.get(experimentBucketMapKey);
188+
for (String experimentId : experimentBucketMap.keySet()){
189+
if (!validExperimentIds.contains(experimentId)) {
190+
experimentBucketMap.remove(experimentId);
191+
}
192+
}
193+
}
194+
diskCache.save(memoryCache);
195+
}
178196
/**
179197
* Add a decision to a user profile.
180198
*

0 commit comments

Comments
 (0)