Skip to content

Commit

Permalink
new-feauture: segment and some code improvements (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
dsun0720 authored Mar 22, 2022
1 parent f5f463a commit 9daf9fb
Show file tree
Hide file tree
Showing 21 changed files with 219 additions and 191 deletions.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
80a907f51c04fad026bc287a04d8843b
94657cb12ae33b495c6c8229ca50e20b
Original file line number Diff line number Diff line change
@@ -1 +1 @@
897c0424aa3b3b1812f1a9faea79e2a4b89d7320
717de0333e701c57eae4ae412a58a7a33ed16545
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7d778cbb25a26f4fb8fd39bad0f6884c
53e557e40f5ee576a3bc77fda82a6b4c
Original file line number Diff line number Diff line change
@@ -1 +1 @@
72d61374b26b0f05005a5c526a8100a1449c9eaa
bbe55c8e5fdb6c8dd07c0c633ca0eb60e8d9e5bc
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
f48f73e8ac2edf3691a4dba10b07bf66
9f2712ae50c72a8e34d3c529b331b4b4
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ae0fc021dbe3ee0c9c44b7eb3f4c0d3a7022c4de
48df912e5f6310f4207d9604257fb56cd6cfbb51
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
<versions>
<version>1.0</version>
</versions>
<lastUpdated>20220302211136</lastUpdated>
<lastUpdated>20220322132121</lastUpdated>
</versioning>
</metadata>
Original file line number Diff line number Diff line change
@@ -1 +1 @@
e126334975ad39d60d558403e5d1e059
2ae6b9273632b0afb5378a2952833b6e
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6984480f2b645451bc59ce262e5c459420dbbba1
3332ae900214c9b0be5b19856a1131093abb10a6
143 changes: 91 additions & 52 deletions src/main/java/co/featureflags/server/DataModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public interface TimestampData {
Integer FFC_FEATURE_FLAG = 100;
Integer FFC_ARCHIVED_VDATA = 200;
Integer FFC_PERSISTENT_VDATA = 300;
Integer FFC_SEGMENT = 400;

/**
* return the unique id
Expand Down Expand Up @@ -123,8 +124,7 @@ public String getMessageType() {
}

boolean isProcessData() {
return "data-sync".equalsIgnoreCase(messageType) && data != null
&& ("full".equalsIgnoreCase(data.eventType) || "patch".equalsIgnoreCase(data.eventType));
return "data-sync".equalsIgnoreCase(messageType) && data != null && ("full".equalsIgnoreCase(data.eventType) || "patch".equalsIgnoreCase(data.eventType));
}
}

Expand All @@ -136,23 +136,30 @@ static class Data implements JsonHelper.AfterJsonParseDeserializable {

private final String eventType;
private final List<FeatureFlag> featureFlags;
private final List<Segment> segments;
private Long timestamp;

Data(String eventType, List<FeatureFlag> featureFlags) {
Data(String eventType, List<FeatureFlag> featureFlags, List<Segment> segments) {
this.eventType = eventType;
this.featureFlags = featureFlags;
this.segments = segments;
}

@Override
public void afterDeserialization() {
timestamp = (featureFlags != null)
? featureFlags.stream().map(flag -> flag.timestamp).max(Long::compare).orElse(0L) : 0L;
Long v1 = (featureFlags != null) ? featureFlags.stream().map(flag -> flag.timestamp).max(Long::compare).orElse(0L) : 0L;
Long v2 = (segments != null) ? segments.stream().map(segment -> segment.timestamp).max(Long::compare).orElse(0L) : 0L;
timestamp = Math.max(v1, v2);
}

public List<FeatureFlag> getFeatureFlags() {
return featureFlags == null ? Collections.emptyList() : featureFlags;
}

public List<Segment> getSegments() {
return segments == null ? Collections.emptyList() : segments;
}

public String getEventType() {
return eventType;
}
Expand All @@ -162,12 +169,77 @@ public Long getTimestamp() {
}

Map<DataStoreTypes.Category, Map<String, DataStoreTypes.Item>> toStorageType() {
ImmutableMap.Builder<String, DataStoreTypes.Item> newItems = ImmutableMap.builder();
ImmutableMap.Builder<String, DataStoreTypes.Item> flags = ImmutableMap.builder();
for (FeatureFlag flag : getFeatureFlags()) {
TimestampData data = flag.isArchived ? flag.toArchivedTimestampData() : flag;
newItems.put(data.getId(), new DataStoreTypes.Item(data));
flags.put(data.getId(), new DataStoreTypes.Item(data));
}
ImmutableMap.Builder<String, DataStoreTypes.Item> segments = ImmutableMap.builder();
for (Segment segment : getSegments()) {
TimestampData data = segment.isArchived ? segment.toArchivedTimestampData() : segment;
segments.put(data.getId(), new DataStoreTypes.Item(data));
}
return ImmutableMap.of(DataStoreTypes.FEATURES, flags.build(), DataStoreTypes.SEGMENTS, segments.build());
}
}

static class Segment implements TimestampData {

private final String id;

private final Boolean isArchived;

private final Long timestamp;

private final List<String> included;

private final List<String> excluded;

Segment(String id, Boolean isArchived, Long timestamp, List<String> included, List<String> excluded) {
this.id = id;
this.isArchived = isArchived;
this.timestamp = timestamp;
this.included = included;
this.excluded = excluded;
}

@Override
public String getId() {
return id;
}

@Override
public boolean isArchived() {
return isArchived != null && isArchived;
}

@Override
public Long getTimestamp() {
return timestamp;
}

@Override
public Integer getType() {
return FFC_SEGMENT;
}

public List<String> getIncluded() {
return included == null ? Collections.emptyList() : included;
}

public List<String> getExcluded() {
return excluded == null ? Collections.emptyList() : excluded;
}

public boolean isMatchUser(String userKeyId) {
if (getExcluded().contains(userKeyId)) {
return false;
}
return ImmutableMap.of(DataStoreTypes.FEATURES, newItems.build());
return getIncluded().contains(userKeyId);
}

public TimestampData toArchivedTimestampData() {
return new ArchivedTimestampData(this.id, this.timestamp);
}
}

Expand All @@ -187,15 +259,7 @@ static class FeatureFlag implements TimestampData {
@SerializedName("variationOptions")
private final List<VariationOption> variations;

FeatureFlag(String id,
Boolean isArchived,
Long timestamp,
Boolean exptIncludeAllRules,
FeatureFlagBasicInfo info,
List<FeatureFlagPrerequisite> prerequisites,
List<FeatureFlagTargetUsersWhoMatchTheseRuleParam> rules,
List<TargetIndividualForVariationOption> targets,
List<VariationOption> variations) {
FeatureFlag(String id, Boolean isArchived, Long timestamp, Boolean exptIncludeAllRules, FeatureFlagBasicInfo info, List<FeatureFlagPrerequisite> prerequisites, List<FeatureFlagTargetUsersWhoMatchTheseRuleParam> rules, List<TargetIndividualForVariationOption> targets, List<VariationOption> variations) {
this.id = id;
this.isArchived = isArchived;
this.timestamp = timestamp;
Expand Down Expand Up @@ -267,15 +331,7 @@ static class FeatureFlagBasicInfo {
private final List<VariationOptionPercentageRollout> defaultRulePercentageRollouts;
private final VariationOption variationOptionWhenDisabled;

FeatureFlagBasicInfo(String id,
String name,
Integer type,
String keyName,
String status,
Boolean isDefaultRulePercentageRolloutsIncludedInExpt,
Date lastUpdatedTime,
List<VariationOptionPercentageRollout> defaultRulePercentageRollouts,
VariationOption variationOptionWhenDisabled) {
FeatureFlagBasicInfo(String id, String name, Integer type, String keyName, String status, Boolean isDefaultRulePercentageRolloutsIncludedInExpt, Date lastUpdatedTime, List<VariationOptionPercentageRollout> defaultRulePercentageRollouts, VariationOption variationOptionWhenDisabled) {
this.id = id;
this.name = name;
this.type = type;
Expand Down Expand Up @@ -308,8 +364,7 @@ public String getStatus() {
}

public Boolean isDefaultRulePercentageRolloutsIncludedInExpt() {
return isDefaultRulePercentageRolloutsIncludedInExpt == null
? Boolean.FALSE : isDefaultRulePercentageRolloutsIncludedInExpt;
return isDefaultRulePercentageRolloutsIncludedInExpt == null ? Boolean.FALSE : isDefaultRulePercentageRolloutsIncludedInExpt;
}

public Date getLastUpdatedTime() {
Expand All @@ -329,8 +384,7 @@ static class FeatureFlagPrerequisite {
private final String prerequisiteFeatureFlagId;
private final VariationOption ValueOptionsVariationValue;

FeatureFlagPrerequisite(String prerequisiteFeatureFlagId,
VariationOption valueOptionsVariationValue) {
FeatureFlagPrerequisite(String prerequisiteFeatureFlagId, VariationOption valueOptionsVariationValue) {
this.prerequisiteFeatureFlagId = prerequisiteFeatureFlagId;
ValueOptionsVariationValue = valueOptionsVariationValue;
}
Expand All @@ -351,11 +405,7 @@ static class FeatureFlagTargetUsersWhoMatchTheseRuleParam {
private final List<FeatureFlagRuleJsonContent> ruleJsonContent;
private final List<VariationOptionPercentageRollout> valueOptionsVariationRuleValues;

FeatureFlagTargetUsersWhoMatchTheseRuleParam(String ruleId,
String ruleName,
Boolean isIncludedInExpt,
List<FeatureFlagRuleJsonContent> ruleJsonContent,
List<VariationOptionPercentageRollout> valueOptionsVariationRuleValues) {
FeatureFlagTargetUsersWhoMatchTheseRuleParam(String ruleId, String ruleName, Boolean isIncludedInExpt, List<FeatureFlagRuleJsonContent> ruleJsonContent, List<VariationOptionPercentageRollout> valueOptionsVariationRuleValues) {
this.ruleId = ruleId;
this.ruleName = ruleName;
this.isIncludedInExpt = isIncludedInExpt;
Expand Down Expand Up @@ -388,8 +438,7 @@ static class TargetIndividualForVariationOption {
private final List<FeatureFlagTargetIndividualUser> individuals;
private final VariationOption valueOption;

TargetIndividualForVariationOption(List<FeatureFlagTargetIndividualUser> individuals,
VariationOption valueOption) {
TargetIndividualForVariationOption(List<FeatureFlagTargetIndividualUser> individuals, VariationOption valueOption) {
this.individuals = individuals;
this.valueOption = valueOption;
}
Expand All @@ -403,8 +452,7 @@ public VariationOption getValueOption() {
}

public boolean isTargeted(String userKeyId) {
if (individuals == null)
return false;
if (individuals == null) return false;
return individuals.stream().anyMatch(i -> i.keyId.equals(userKeyId));
}
}
Expand All @@ -414,9 +462,7 @@ static class VariationOption {
private final Integer displayOrder;
private final String variationValue;

VariationOption(Integer localId,
Integer displayOrder,
String variationValue) {
VariationOption(Integer localId, Integer displayOrder, String variationValue) {
this.localId = localId;
this.displayOrder = displayOrder;
this.variationValue = variationValue;
Expand All @@ -441,9 +487,7 @@ static class VariationOptionPercentageRollout {
private final List<Double> rolloutPercentage;
private final VariationOption valueOption;

VariationOptionPercentageRollout(Double exptRollout,
List<Double> rolloutPercentage,
VariationOption valueOption) {
VariationOptionPercentageRollout(Double exptRollout, List<Double> rolloutPercentage, VariationOption valueOption) {
this.exptRollout = exptRollout;
this.rolloutPercentage = rolloutPercentage;
this.valueOption = valueOption;
Expand All @@ -467,9 +511,7 @@ static class FeatureFlagRuleJsonContent {
private final String operation;
private final String value;

FeatureFlagRuleJsonContent(String property,
String operation,
String value) {
FeatureFlagRuleJsonContent(String property, String operation, String value) {
this.property = property;
this.operation = operation;
this.value = value;
Expand All @@ -494,10 +536,7 @@ static class FeatureFlagTargetIndividualUser {
private final String keyId;
private final String email;

FeatureFlagTargetIndividualUser(String id,
String name,
String keyId,
String email) {
FeatureFlagTargetIndividualUser(String id, String name, String keyId, String email) {
this.id = id;
this.name = name;
this.keyId = keyId;
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/co/featureflags/server/Evaluator.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,21 @@ abstract class Evaluator {
protected static final String IS_FALSE_CLAUSE = "IsFalse";
protected static final String MATCH_REGEX_CLAUSE = "MatchRegex";
protected static final String NOT_MATCH_REGEX_CLAUSE = "NotMatchRegex";
protected static final String IS_IN_SEGMENT_CLAUSE = "User is in segment";
protected static final String NOT_IN_SEGMENT_CLAUSE = "User is not in segment";


protected static final String FLAG_DISABLE_STATS = "Disabled";
protected static final String FLAG_ENABLE_STATS = "Enabled";

protected final Getter<DataModel.FeatureFlag> flagGetter;

Evaluator(Getter<DataModel.FeatureFlag> flagGetter) {
protected final Getter<DataModel.Segment> segmentGetter;

Evaluator(Getter<DataModel.FeatureFlag> flagGetter,
Getter<DataModel.Segment> segmentGetter) {
this.flagGetter = flagGetter;
this.segmentGetter = segmentGetter;
}

abstract EvalResult evaluate(DataModel.FeatureFlag flag, FFCUser user, InsightTypes.Event event);
Expand Down
Loading

0 comments on commit 9daf9fb

Please sign in to comment.