@@ -78,6 +78,17 @@ public DecisionService(@Nonnull Bucketer bucketer,
78
78
this .userProfileService = userProfileService ;
79
79
}
80
80
81
+ /**
82
+ * Get a {@link Variation} of an {@link Experiment} for a user to be allocated into.
83
+ *
84
+ * @param experiment The Experiment the user will be bucketed into.
85
+ * @param user The current OptimizelyUserContext
86
+ * @param projectConfig The current projectConfig
87
+ * @param options An array of decision options
88
+ * @param userProfileTracker tracker for reading and updating user profile of the user
89
+ * @param reasons Decision reasons
90
+ * @return A {@link DecisionResponse} including the {@link Variation} that user is bucketed into (or null) and the decision reasons
91
+ */
81
92
@ Nonnull
82
93
public DecisionResponse <Variation > getVariation (@ Nonnull Experiment experiment ,
83
94
@ Nonnull OptimizelyUserContext user ,
@@ -164,19 +175,17 @@ public DecisionResponse<Variation> getVariation(@Nonnull Experiment experiment,
164
175
165
176
// fetch the user profile map from the user profile service
166
177
boolean ignoreUPS = options .contains (OptimizelyDecideOption .IGNORE_USER_PROFILE_SERVICE );
167
- // UserProfile userProfile = null;
168
178
UserProfileTracker userProfileTracker = null ;
169
179
170
180
if (userProfileService != null && !ignoreUPS ) {
171
- UserProfile userProfile = getUserProfile (user .getUserId (), reasons );
172
- userProfileTracker = new UserProfileTracker ( userProfile , false );
181
+ userProfileTracker = new UserProfileTracker (user .getUserId ());
182
+ userProfileTracker . loadUserProfile ( reasons );
173
183
}
174
184
175
-
176
185
DecisionResponse <Variation > response = getVariation (experiment , user , projectConfig , options , userProfileTracker , reasons );
177
186
178
- if (userProfileService != null && !ignoreUPS && userProfileTracker . profileUpdated ) {
179
- saveUserProfile ( userProfileTracker .userProfile );
187
+ if (userProfileService != null && !ignoreUPS ) {
188
+ userProfileTracker .saveUserProfile ( );
180
189
}
181
190
return response ;
182
191
}
@@ -205,45 +214,42 @@ public DecisionResponse<FeatureDecision> getVariationForFeature(@Nonnull Feature
205
214
return getVariationsForFeatureList (Arrays .asList (featureFlag ), user , projectConfig , options ).get (0 );
206
215
}
207
216
208
- private UserProfile getUserProfile (String userId , DecisionReasons reasons ) {
209
- UserProfile userProfile = null ;
217
+ class UserProfileTracker {
218
+ private UserProfile userProfile ;
219
+ private boolean profileUpdated ;
220
+ private String userId ;
210
221
211
- try {
212
- Map <String , Object > userProfileMap = userProfileService .lookup (userId );
213
- if (userProfileMap == null ) {
214
- String message = reasons .addInfo ("We were unable to get a user profile map from the UserProfileService." );
215
- logger .info (message );
216
- } else if (UserProfileUtils .isValidUserProfileMap (userProfileMap )) {
217
- userProfile = UserProfileUtils .convertMapToUserProfile (userProfileMap );
218
- } else {
219
- String message = reasons .addInfo ("The UserProfileService returned an invalid map." );
220
- logger .warn (message );
221
- }
222
- } catch (Exception exception ) {
223
- String message = reasons .addInfo (exception .getMessage ());
224
- logger .error (message );
225
- errorHandler .handleError (new OptimizelyRuntimeException (exception ));
222
+ UserProfileTracker (String userId ) {
223
+ this .userId = userId ;
224
+ this .profileUpdated = false ;
225
+ this .userProfile = null ;
226
226
}
227
227
228
- if (userProfile == null ) {
229
- userProfile = new UserProfile (userId , new HashMap <String , Decision >());
230
- }
231
-
232
- return userProfile ;
233
- }
234
-
235
- static class UserProfileTracker {
236
- public UserProfile userProfile ;
237
- public boolean profileUpdated ;
228
+ public void loadUserProfile (DecisionReasons reasons ) {
229
+ try {
230
+ Map <String , Object > userProfileMap = userProfileService .lookup (userId );
231
+ if (userProfileMap == null ) {
232
+ String message = reasons .addInfo ("We were unable to get a user profile map from the UserProfileService." );
233
+ logger .info (message );
234
+ } else if (UserProfileUtils .isValidUserProfileMap (userProfileMap )) {
235
+ userProfile = UserProfileUtils .convertMapToUserProfile (userProfileMap );
236
+ } else {
237
+ String message = reasons .addInfo ("The UserProfileService returned an invalid map." );
238
+ logger .warn (message );
239
+ }
240
+ } catch (Exception exception ) {
241
+ String message = reasons .addInfo (exception .getMessage ());
242
+ logger .error (message );
243
+ errorHandler .handleError (new OptimizelyRuntimeException (exception ));
244
+ }
238
245
239
- UserProfileTracker ( UserProfile userProfile , boolean profileUpdated ) {
240
- this . userProfile = userProfile ;
241
- this . profileUpdated = profileUpdated ;
246
+ if ( userProfile == null ) {
247
+ userProfile = new UserProfile ( userId , new HashMap < String , Decision >()) ;
248
+ }
242
249
}
243
250
244
- void updateUserProfile (@ Nonnull Experiment experiment ,
251
+ public void updateUserProfile (@ Nonnull Experiment experiment ,
245
252
@ Nonnull Variation variation ) {
246
-
247
253
String experimentId = experiment .getId ();
248
254
String variationId = variation .getId ();
249
255
Decision decision ;
@@ -258,10 +264,27 @@ void updateUserProfile(@Nonnull Experiment experiment,
258
264
logger .info ("Updated variation \" {}\" of experiment \" {}\" for user \" {}\" ." ,
259
265
variationId , experimentId , userProfile .userId );
260
266
}
267
+
268
+ public void saveUserProfile () {
269
+ // if there were no updates, no need to save
270
+ if (!this .profileUpdated ) {
271
+ return ;
272
+ }
273
+
274
+ try {
275
+ userProfileService .save (userProfile .toMap ());
276
+ logger .info ("Saved user profile of user \" {}\" ." ,
277
+ userProfile .userId );
278
+ } catch (Exception exception ) {
279
+ logger .warn ("Failed to save user profile of user \" {}\" ." ,
280
+ userProfile .userId );
281
+ errorHandler .handleError (new OptimizelyRuntimeException (exception ));
282
+ }
283
+ }
261
284
}
262
285
263
286
/**
264
- * Get the variations the user is bucketed into for the the list of feature flags
287
+ * Get the variations the user is bucketed into for the list of feature flags
265
288
*
266
289
* @param featureFlags The feature flag list the user wants to access.
267
290
* @param user The current OptimizelyuserContext
@@ -280,8 +303,8 @@ public List<DecisionResponse<FeatureDecision>> getVariationsForFeatureList(@Non
280
303
UserProfileTracker userProfileTracker = null ;
281
304
282
305
if (userProfileService != null && !ignoreUPS ) {
283
- UserProfile userProfile = getUserProfile (user .getUserId (), upsReasons );
284
- userProfileTracker = new UserProfileTracker ( userProfile , false );
306
+ userProfileTracker = new UserProfileTracker (user .getUserId ());
307
+ userProfileTracker . loadUserProfile ( upsReasons );
285
308
}
286
309
287
310
List <DecisionResponse <FeatureDecision >> decisions = new ArrayList <>();
@@ -316,8 +339,8 @@ public List<DecisionResponse<FeatureDecision>> getVariationsForFeatureList(@Non
316
339
decisions .add (new DecisionResponse (decision , reasons ));
317
340
}
318
341
319
- if (userProfileService != null && !ignoreUPS && userProfileTracker . profileUpdated ) {
320
- saveUserProfile ( userProfileTracker .userProfile );
342
+ if (userProfileService != null && !ignoreUPS ) {
343
+ userProfileTracker .saveUserProfile ( );
321
344
}
322
345
323
346
return decisions ;
@@ -548,22 +571,6 @@ void saveVariation(@Nonnull Experiment experiment,
548
571
}
549
572
}
550
573
551
- void saveUserProfile (@ Nonnull UserProfile userProfile ) {
552
- if (userProfileService == null ) {
553
- return ;
554
- }
555
-
556
- try {
557
- userProfileService .save (userProfile .toMap ());
558
- logger .info ("Saved user profile of user \" {}\" ." ,
559
- userProfile .userId );
560
- } catch (Exception exception ) {
561
- logger .warn ("Failed to save user profile of user \" {}\" ." ,
562
- userProfile .userId );
563
- errorHandler .handleError (new OptimizelyRuntimeException (exception ));
564
- }
565
- }
566
-
567
574
/**
568
575
* Get the bucketingId of a user if a bucketingId exists in attributes, or else default to userId.
569
576
*
0 commit comments