Skip to content

Commit 03037e2

Browse files
refactor: extract UserProfileTracker
1 parent c23e898 commit 03037e2

File tree

3 files changed

+124
-101
lines changed

3 files changed

+124
-101
lines changed

OptimizelySDK/Bucketing/DecisionService.cs

Lines changed: 15 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ public class DecisionService
4141
public const string LOGGING_KEY_TYPE_RULE = "rule";
4242

4343
private Bucketer Bucketer;
44-
private static IErrorHandler ErrorHandler;
44+
private readonly IErrorHandler ErrorHandler;
4545
private static UserProfileService UserProfileService;
46-
private static ILogger Logger;
46+
private readonly ILogger Logger;
4747

4848
/// <summary>
4949
/// Associative array of user IDs to an associative array
@@ -118,7 +118,8 @@ OptimizelyDecideOption[] options
118118

119119
if (UserProfileService != null && !ignoreUps)
120120
{
121-
userProfileTracker = new UserProfileTracker(user.GetUserId());
121+
userProfileTracker = new UserProfileTracker(UserProfileService, user.GetUserId(),
122+
Logger, ErrorHandler);
122123
userProfileTracker.LoadUserProfile(reasons);
123124
}
124125

@@ -690,7 +691,8 @@ public virtual Result<FeatureDecision> GetVariationForFeatureExperiment(
690691
}
691692
else
692693
{
693-
var decisionResponse = GetVariation(experiment, user, config, options, userProfileTracker);
694+
var decisionResponse = GetVariation(experiment, user, config, options,
695+
userProfileTracker);
694696

695697
reasons += decisionResponse?.DecisionReasons;
696698
decisionVariation = decisionResponse.ResultObject;
@@ -730,97 +732,6 @@ public virtual Result<FeatureDecision> GetVariationForFeature(FeatureFlag featur
730732
new OptimizelyDecideOption[] { });
731733
}
732734

733-
public class UserProfileTracker
734-
{
735-
public UserProfile UserProfile { get; private set; }
736-
public bool ProfileUpdated { get; private set; }
737-
private string UserId { get; }
738-
739-
public UserProfileTracker(string userId)
740-
{
741-
UserId = userId;
742-
ProfileUpdated = false;
743-
UserProfile = null;
744-
}
745-
746-
public void LoadUserProfile(DecisionReasons reasons)
747-
{
748-
try
749-
{
750-
var userProfileMap = UserProfileService.Lookup(UserId);
751-
if (userProfileMap == null)
752-
{
753-
Logger.Log(LogLevel.INFO,
754-
reasons.AddInfo(
755-
"We were unable to get a user profile map from the UserProfileService."));
756-
}
757-
else if (UserProfileUtil.IsValidUserProfileMap(userProfileMap))
758-
{
759-
UserProfile = UserProfileUtil.ConvertMapToUserProfile(userProfileMap);
760-
}
761-
else
762-
{
763-
Logger.Log(LogLevel.WARN,
764-
reasons.AddInfo("The UserProfileService returned an invalid map."));
765-
}
766-
}
767-
catch (Exception exception)
768-
{
769-
Logger.Log(LogLevel.ERROR, reasons.AddInfo(exception.Message));
770-
ErrorHandler.HandleError(
771-
new Exceptions.OptimizelyRuntimeException(exception.Message));
772-
}
773-
774-
if (UserProfile == null)
775-
{
776-
UserProfile = new UserProfile(UserId, new Dictionary<string, Decision>());
777-
}
778-
}
779-
780-
public void UpdateUserProfile(Experiment experiment, Variation variation)
781-
{
782-
var experimentId = experiment.Id;
783-
var variationId = variation.Id;
784-
Decision decision;
785-
if (UserProfile.ExperimentBucketMap.ContainsKey(experimentId))
786-
{
787-
decision = UserProfile.ExperimentBucketMap[experimentId];
788-
decision.VariationId = variationId;
789-
}
790-
else
791-
{
792-
decision = new Decision(variationId);
793-
}
794-
795-
UserProfile.ExperimentBucketMap[experimentId] = decision;
796-
ProfileUpdated = true;
797-
798-
Logger.Log(LogLevel.INFO,
799-
$"Saved variation \"{variationId}\" of experiment \"{experimentId}\" for user \"{UserProfile.UserId}\".");
800-
}
801-
802-
public void SaveUserProfile()
803-
{
804-
if (!ProfileUpdated)
805-
{
806-
return;
807-
}
808-
809-
try
810-
{
811-
UserProfileService.Save(UserProfile.ToMap());
812-
Logger.Log(LogLevel.INFO,
813-
$"Saved user profile of user \"{UserProfile.UserId}\".");
814-
}
815-
catch (Exception exception)
816-
{
817-
Logger.Log(LogLevel.WARN,
818-
$"Failed to save user profile of user \"{UserProfile.UserId}\".");
819-
ErrorHandler.HandleError(new Exceptions.OptimizelyRuntimeException(exception.Message));
820-
}
821-
}
822-
}
823-
824735
public virtual List<Result<FeatureDecision>> GetVariationsForFeatureList(
825736
List<FeatureFlag> featureFlags,
826737
OptimizelyUserContext user,
@@ -836,7 +747,8 @@ OptimizelyDecideOption[] options
836747

837748
if (UserProfileService != null && !ignoreUps)
838749
{
839-
userProfileTracker = new UserProfileTracker(user.GetUserId());
750+
userProfileTracker = new UserProfileTracker(UserProfileService, user.GetUserId(),
751+
Logger, ErrorHandler);
840752
userProfileTracker.LoadUserProfile(upsReasons);
841753
}
842754

@@ -883,7 +795,8 @@ OptimizelyDecideOption[] options
883795
}
884796
}
885797

886-
if (UserProfileService != null && !ignoreUps && userProfileTracker?.ProfileUpdated == true)
798+
if (UserProfileService != null && !ignoreUps &&
799+
userProfileTracker?.ProfileUpdated == true)
887800
{
888801
userProfileTracker.SaveUserProfile();
889802
}
@@ -909,10 +822,11 @@ OptimizelyDecideOption[] options
909822
)
910823
{
911824
return GetVariationsForFeatureList(new List<FeatureFlag> { featureFlag },
912-
user,
913-
config,
914-
filteredAttributes,
915-
options).First();
825+
user,
826+
config,
827+
filteredAttributes,
828+
options).
829+
First();
916830
}
917831

918832
/// <summary>
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using OptimizelySDK.Entity;
4+
using OptimizelySDK.ErrorHandler;
5+
using OptimizelySDK.Logger;
6+
using OptimizelySDK.OptimizelyDecisions;
7+
8+
namespace OptimizelySDK.Bucketing
9+
{
10+
public class UserProfileTracker
11+
{
12+
public UserProfile UserProfile { get; private set; }
13+
public bool ProfileUpdated { get; private set; }
14+
15+
private readonly UserProfileService _userProfileService;
16+
private readonly string _userId;
17+
private readonly ILogger _logger;
18+
private readonly IErrorHandler _errorHandler;
19+
20+
public UserProfileTracker(UserProfileService userProfileService, string userId, ILogger logger, IErrorHandler errorHandler)
21+
{
22+
_userProfileService = userProfileService;
23+
_userId = userId;
24+
_logger = logger;
25+
_errorHandler = errorHandler;
26+
ProfileUpdated = false;
27+
UserProfile = null;
28+
}
29+
30+
public void LoadUserProfile(DecisionReasons reasons)
31+
{
32+
try
33+
{
34+
var userProfileMap = _userProfileService.Lookup(_userId);
35+
if (userProfileMap == null)
36+
{
37+
_logger.Log(LogLevel.INFO,
38+
reasons.AddInfo(
39+
"We were unable to get a user profile map from the UserProfileService."));
40+
}
41+
else if (UserProfileUtil.IsValidUserProfileMap(userProfileMap))
42+
{
43+
UserProfile = UserProfileUtil.ConvertMapToUserProfile(userProfileMap);
44+
}
45+
else
46+
{
47+
_logger.Log(LogLevel.WARN,
48+
reasons.AddInfo("The UserProfileService returned an invalid map."));
49+
}
50+
}
51+
catch (Exception exception)
52+
{
53+
_logger.Log(LogLevel.ERROR, reasons.AddInfo(exception.Message));
54+
_errorHandler.HandleError(
55+
new Exceptions.OptimizelyRuntimeException(exception.Message));
56+
}
57+
58+
if (UserProfile == null)
59+
{
60+
UserProfile = new UserProfile(_userId, new Dictionary<string, Decision>());
61+
}
62+
}
63+
64+
public void UpdateUserProfile(Experiment experiment, Variation variation)
65+
{
66+
var experimentId = experiment.Id;
67+
var variationId = variation.Id;
68+
Decision decision;
69+
if (UserProfile.ExperimentBucketMap.ContainsKey(experimentId))
70+
{
71+
decision = UserProfile.ExperimentBucketMap[experimentId];
72+
decision.VariationId = variationId;
73+
}
74+
else
75+
{
76+
decision = new Decision(variationId);
77+
}
78+
79+
UserProfile.ExperimentBucketMap[experimentId] = decision;
80+
ProfileUpdated = true;
81+
82+
_logger.Log(LogLevel.INFO,
83+
$"Saved variation \"{variationId}\" of experiment \"{experimentId}\" for user \"{UserProfile.UserId}\".");
84+
}
85+
86+
public void SaveUserProfile()
87+
{
88+
if (!ProfileUpdated)
89+
{
90+
return;
91+
}
92+
93+
try
94+
{
95+
_userProfileService.Save(UserProfile.ToMap());
96+
_logger.Log(LogLevel.INFO,
97+
$"Saved user profile of user \"{UserProfile.UserId}\".");
98+
}
99+
catch (Exception exception)
100+
{
101+
_logger.Log(LogLevel.WARN,
102+
$"Failed to save user profile of user \"{UserProfile.UserId}\".");
103+
_errorHandler.HandleError(
104+
new Exceptions.OptimizelyRuntimeException(exception.Message));
105+
}
106+
}
107+
}
108+
}

OptimizelySDK/OptimizelySDK.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
<Compile Include="AudienceConditions\OrCondition.cs"/>
7676
<Compile Include="Bucketing\Bucketer.cs"/>
7777
<Compile Include="Bucketing\Decision.cs"/>
78+
<Compile Include="Bucketing\UserProfileTracker.cs" />
7879
<Compile Include="ClientConfigHandler.cs"/>
7980
<Compile Include="Entity\Attribute.cs"/>
8081
<Compile Include="Entity\Audience.cs"/>

0 commit comments

Comments
 (0)