Skip to content

Commit

Permalink
fixup! feat: Update in-process resolver to support flag metadata open…
Browse files Browse the repository at this point in the history
…-feature#1102

Signed-off-by: christian.lutnik <[email protected]>
  • Loading branch information
chrfwow committed Jan 9, 2025
1 parent 4c6393a commit da9e92b
Show file tree
Hide file tree
Showing 9 changed files with 526 additions and 427 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@

import static dev.openfeature.contrib.providers.flagd.resolver.process.model.FeatureFlag.EMPTY_TARGETING_STRING;

import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;

import dev.openfeature.contrib.providers.flagd.FlagdOptions;
import dev.openfeature.contrib.providers.flagd.resolver.Resolver;
import dev.openfeature.contrib.providers.flagd.resolver.common.ConnectionEvent;
Expand All @@ -27,6 +23,7 @@
import dev.openfeature.sdk.Value;
import dev.openfeature.sdk.exceptions.ParseError;
import dev.openfeature.sdk.exceptions.TypeMismatchError;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -53,8 +50,10 @@ public class InProcessResolver implements Resolver {
* @param connectedSupplier lambda providing current connection status from caller
* @param onConnectionEvent lambda which handles changes in the connection/stream
*/
public InProcessResolver(FlagdOptions options, final Supplier<Boolean> connectedSupplier,
Consumer<ConnectionEvent> onConnectionEvent) {
public InProcessResolver(
FlagdOptions options,
final Supplier<Boolean> connectedSupplier,
Consumer<ConnectionEvent> onConnectionEvent) {
this.flagStore = new FlagStore(getConnector(options));
this.deadline = options.getDeadline();
this.onConnectionEvent = onConnectionEvent;
Expand All @@ -65,9 +64,7 @@ public InProcessResolver(FlagdOptions options, final Supplier<Boolean> connected
this.fallBackMetadata = null;
} else {
this.scope = options.getSelector();
this.fallBackMetadata = ImmutableMetadata.builder()
.addString("scope", this.scope)
.build();
this.fallBackMetadata = ImmutableMetadata.builder().addString("scope", this.scope).build();
}
}

Expand Down Expand Up @@ -119,11 +116,7 @@ public void shutdown() throws InterruptedException {
/**
* Resolve a boolean flag.
*/
public ProviderEvaluation<Boolean> booleanEvaluation(
String key,
Boolean defaultValue,
EvaluationContext ctx
) {
public ProviderEvaluation<Boolean> booleanEvaluation(String key, Boolean defaultValue, EvaluationContext ctx) {
return resolve(Boolean.class, key, ctx);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.HashMap;
import java.util.Map;
import lombok.EqualsAndHashCode;
import lombok.Getter;
Expand All @@ -27,17 +28,42 @@ public class FeatureFlag {

/** Construct a flagd feature flag. */
@JsonCreator
public FeatureFlag(@JsonProperty("state") String state,
@JsonProperty("defaultVariant") String defaultVariant,
@JsonProperty("variants") Map<String, Object> variants,
@JsonProperty("targeting") @JsonDeserialize(using = StringSerializer.class) String targeting,
@JsonProperty("metadata") Map<String, Object> metadata
) {
public FeatureFlag(
@JsonProperty("state") String state,
@JsonProperty("defaultVariant") String defaultVariant,
@JsonProperty("variants") Map<String, Object> variants,
@JsonProperty("targeting") @JsonDeserialize(using = StringSerializer.class) String targeting,
@JsonProperty("metadata") Map<String, Object> metadata) {
this.state = state;
this.defaultVariant = defaultVariant;
this.variants = variants;
this.targeting = targeting;
this.metadata = metadata;
if (metadata == null) {
this.metadata = new HashMap<>();
} else {
this.metadata = metadata;
}
}

/** Construct a flagd feature flag. */
public FeatureFlag(String state, String defaultVariant, Map<String, Object> variants, String targeting) {
this.state = state;
this.defaultVariant = defaultVariant;
this.variants = variants;
this.targeting = targeting;
this.metadata = new HashMap<>();
}

/**
* Add global metadata to this FeatureFlag. Keys that already exist in the metadata of this flag are not
* overwritten.
*
* @param metadata The metadata to add to this flag
*/
public void addMetadata(Map<String, Object> metadata) {
for (Map.Entry<String, Object> entry : metadata.entrySet()) {
this.metadata.putIfAbsent(entry.getKey(), entry.getValue());
}
}

/** Get targeting rule of the flag. */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package dev.openfeature.contrib.providers.flagd.resolver.process.model;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.networknt.schema.JsonSchema;
import com.networknt.schema.JsonSchemaFactory;
Expand All @@ -24,6 +26,7 @@
justification = "Feature flag comes as a Json configuration, hence they must be exposed")
public class FlagParser {
private static final String FLAG_KEY = "flags";
private static final String METADATA_KEY = "metadata";
private static final String EVALUATOR_KEY = "$evaluators";
private static final String REPLACER_FORMAT = "\"\\$ref\":(\\s)*\"%s\"";
private static final ObjectMapper MAPPER = new ObjectMapper();
Expand Down Expand Up @@ -73,6 +76,8 @@ public static Map<String, FeatureFlag> parseString(final String configuration, b
try (JsonParser parser = MAPPER.createParser(transposedConfiguration)) {
final TreeNode treeNode = parser.readValueAsTree();
final TreeNode flagNode = treeNode.get(FLAG_KEY);
final TreeNode metadataNode = treeNode.get(METADATA_KEY);
final Map<String, Object> metadata = parseMetadata(metadataNode);

if (flagNode == null) {
throw new IllegalArgumentException("No flag configurations found in the payload");
Expand All @@ -81,13 +86,24 @@ public static Map<String, FeatureFlag> parseString(final String configuration, b
final Iterator<String> it = flagNode.fieldNames();
while (it.hasNext()) {
final String key = it.next();
flagMap.put(key, MAPPER.treeToValue(flagNode.get(key), FeatureFlag.class));
FeatureFlag flag = MAPPER.treeToValue(flagNode.get(key), FeatureFlag.class);
flag.addMetadata(metadata);
flagMap.put(key, flag);
}
}

return flagMap;
}

private static Map<String, Object> parseMetadata(TreeNode metadataNode) throws JsonProcessingException {
if (metadataNode == null) {
return new HashMap<>();
}

TypeReference<Map<String, Object>> typeRef = new TypeReference<Map<String, Object>>() {};
return MAPPER.treeToValue(metadataNode, typeRef);
}

private static String transposeEvaluators(final String configuration) throws IOException {
try (JsonParser parser = MAPPER.createParser(configuration)) {
final Map<String, Pattern> patternMap = new HashMap<>();
Expand Down
Loading

0 comments on commit da9e92b

Please sign in to comment.