-
Notifications
You must be signed in to change notification settings - Fork 32
feat(api): Accepting all types for attributes values #207
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
c401466
d73f4eb
6173eee
be4de1c
0b23827
cc9a5a6
20f83bf
881774f
6274260
a47f8af
e49c473
20974f4
6ef444d
7c868cb
9f0593f
b484960
4aa66fe
7e1dd58
a17bdbd
f90b466
d9d23e2
0b6aad9
182c4fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -80,7 +80,7 @@ public DecisionService(@Nonnull Bucketer bucketer, | |
*/ | ||
public @Nullable Variation getVariation(@Nonnull Experiment experiment, | ||
@Nonnull String userId, | ||
@Nonnull Map<String, String> filteredAttributes) { | ||
@Nonnull Map<String, ?> filteredAttributes) { | ||
|
||
if (!ExperimentUtils.isExperimentActive(experiment)) { | ||
return null; | ||
|
@@ -131,7 +131,7 @@ public DecisionService(@Nonnull Bucketer bucketer, | |
if (ExperimentUtils.isUserInExperiment(projectConfig, experiment, filteredAttributes)) { | ||
String bucketingId = userId; | ||
if (filteredAttributes.containsKey(ControlAttribute.BUCKETING_ATTRIBUTE.toString())) { | ||
bucketingId = filteredAttributes.get(ControlAttribute.BUCKETING_ATTRIBUTE.toString()); | ||
bucketingId = (String) filteredAttributes.get(ControlAttribute.BUCKETING_ATTRIBUTE.toString()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should probably check the type just to be safe. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If it isn't a string, should we keep it as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct, we don't use the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And I assume you're on top of this, but we should log a ~warning if we're ignoring the And while you're at it...we should also log at ~info level in cases where do ingest a usable |
||
} | ||
variation = bucketer.bucket(experiment, bucketingId); | ||
|
||
|
@@ -159,7 +159,7 @@ public DecisionService(@Nonnull Bucketer bucketer, | |
*/ | ||
public @Nonnull FeatureDecision getVariationForFeature(@Nonnull FeatureFlag featureFlag, | ||
@Nonnull String userId, | ||
@Nonnull Map<String, String> filteredAttributes) { | ||
@Nonnull Map<String, ?> filteredAttributes) { | ||
if (!featureFlag.getExperimentIds().isEmpty()) { | ||
for (String experimentId : featureFlag.getExperimentIds()) { | ||
Experiment experiment = projectConfig.getExperimentIdMapping().get(experimentId); | ||
|
@@ -195,7 +195,7 @@ public DecisionService(@Nonnull Bucketer bucketer, | |
*/ | ||
@Nonnull FeatureDecision getVariationForFeatureInRollout(@Nonnull FeatureFlag featureFlag, | ||
@Nonnull String userId, | ||
@Nonnull Map<String, String> filteredAttributes) { | ||
@Nonnull Map<String, ?> filteredAttributes) { | ||
// use rollout to get variation for feature | ||
if (featureFlag.getRolloutId().isEmpty()) { | ||
logger.info("The feature flag \"{}\" is not used in a rollout.", featureFlag.getKey()); | ||
|
@@ -212,7 +212,7 @@ public DecisionService(@Nonnull Bucketer bucketer, | |
int rolloutRulesLength = rollout.getExperiments().size(); | ||
String bucketingId = userId; | ||
if (filteredAttributes.containsKey(ControlAttribute.BUCKETING_ATTRIBUTE.toString())) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should check for null value and that the value is a string. |
||
bucketingId = filteredAttributes.get(ControlAttribute.BUCKETING_ATTRIBUTE.toString()); | ||
bucketingId = (String) filteredAttributes.get(ControlAttribute.BUCKETING_ATTRIBUTE.toString()); | ||
} | ||
Variation variation; | ||
for (int i = 0; i < rolloutRulesLength - 1; i++) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,5 +23,5 @@ | |
*/ | ||
public interface Condition { | ||
|
||
boolean evaluate(Map<String, String> attributes); | ||
boolean evaluate(Map<String, ?> attributes); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update the header on this file to be |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,7 +37,7 @@ public Condition getCondition() { | |
return condition; | ||
} | ||
|
||
public boolean evaluate(Map<String, String> attributes) { | ||
public boolean evaluate(Map<String, ?> attributes) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to update the |
||
return !condition.evaluate(attributes); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,7 +36,7 @@ public List<Condition> getConditions() { | |
return conditions; | ||
} | ||
|
||
public boolean evaluate(Map<String, String> attributes) { | ||
public boolean evaluate(Map<String, ?> attributes) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above re: the toString method |
||
for (Condition condition : conditions) { | ||
if (condition.evaluate(attributes)) | ||
return true; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,9 +29,9 @@ public class UserAttribute implements Condition { | |
|
||
private final String name; | ||
private final String type; | ||
private final String value; | ||
private final Object value; | ||
|
||
public UserAttribute(@Nonnull String name, @Nonnull String type, @Nullable String value) { | ||
public UserAttribute(@Nonnull String name, @Nonnull String type, @Nullable Object value) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @thomaszurkan-optimizely do we need to overload this constructor to allow you to pass in a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you mean There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nevermind, I think this will be fine as is. Can ignore my previous comment. |
||
this.name = name; | ||
this.type = type; | ||
this.value = value; | ||
|
@@ -45,12 +45,12 @@ public String getType() { | |
return type; | ||
} | ||
|
||
public String getValue() { | ||
public Object getValue() { | ||
return value; | ||
} | ||
|
||
public boolean evaluate(Map<String, String> attributes) { | ||
String userAttributeValue = attributes.get(name); | ||
public boolean evaluate(Map<String, ?> attributes) { | ||
Object userAttributeValue = attributes.get(name); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm should be careful with this. Eventually when we do accept objects and arrays to be passed in, the |
||
|
||
if (value != null) { // if there is a value in the condition | ||
// check user attribute value is equal | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should add a test that actually removes unknown attributes to see what happens here. But my understanding is that
Object
is actually different from?
.See https://stackoverflow.com/questions/678822/what-is-the-difference-between-and-object-in-java-generics
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't use a question mark in a constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually think that the proper way to use the constructor is HashMap<>(attributes). So, @wangjoshuah is correct.
Please update to something like:
HashMap<String, ?> attr = new HashMap<>();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like
<>
was not introduced until Java 7 and we're currently on Java 6. Thoughts?https://stackoverflow.com/questions/16612157/why-does-new-hashmap-produce-an-error-in-jdk-1-6-but-not-1-7?lq=1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, it sounds like
is indeed the way to go...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#208 is the way to go. Good call @thomaszurkan-optimizely