-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: expose sync-metadata, call RPC with (re)connect (#967)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com> Co-authored-by: Simon Schrottner <simon.schrottner@dynatrace.com>
- Loading branch information
Showing
30 changed files
with
1,656 additions
and
1,230 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
...rc/main/java/dev/openfeature/contrib/providers/flagd/resolver/common/ConnectionEvent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package dev.openfeature.contrib.providers.flagd.resolver.common; | ||
|
||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
|
||
/** | ||
* Event payload for a | ||
* {@link dev.openfeature.contrib.providers.flagd.resolver.Resolver} connection | ||
* state change event. | ||
*/ | ||
@AllArgsConstructor | ||
public class ConnectionEvent { | ||
@Getter | ||
private final boolean connected; | ||
private final List<String> flagsChanged; | ||
private final Map<String, Object> syncMetadata; | ||
|
||
/** | ||
* Construct a new ConnectionEvent. | ||
* | ||
* @param connected status of the connection | ||
*/ | ||
public ConnectionEvent(boolean connected) { | ||
this(connected, Collections.emptyList(), Collections.emptyMap()); | ||
} | ||
|
||
/** | ||
* Construct a new ConnectionEvent. | ||
* | ||
* @param connected status of the connection | ||
* @param flagsChanged list of flags changed | ||
*/ | ||
public ConnectionEvent(boolean connected, List<String> flagsChanged) { | ||
this(connected, flagsChanged, Collections.emptyMap()); | ||
} | ||
|
||
/** | ||
* Construct a new ConnectionEvent. | ||
* | ||
* @param connected status of the connection | ||
* @param syncMetadata sync.getMetadata | ||
*/ | ||
public ConnectionEvent(boolean connected, Map<String, Object> syncMetadata) { | ||
this(connected, Collections.emptyList(), syncMetadata); | ||
} | ||
|
||
/** | ||
* Get changed flags. | ||
* | ||
* @return an unmodifiable view of the changed flags | ||
*/ | ||
public List<String> getFlagsChanged() { | ||
return Collections.unmodifiableList(flagsChanged); | ||
} | ||
|
||
/** | ||
* Get changed sync metadata. | ||
* | ||
* @return an unmodifiable view of the sync metadata | ||
*/ | ||
public Map<String, Object> getSyncMetadata() { | ||
return Collections.unmodifiableMap(syncMetadata); | ||
} | ||
} |
184 changes: 184 additions & 0 deletions
184
.../flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/common/Convert.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
package dev.openfeature.contrib.providers.flagd.resolver.common; | ||
|
||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
|
||
import com.google.protobuf.Descriptors; | ||
import com.google.protobuf.ListValue; | ||
import com.google.protobuf.Message; | ||
import com.google.protobuf.NullValue; | ||
import com.google.protobuf.Struct; | ||
|
||
import dev.openfeature.sdk.EvaluationContext; | ||
import dev.openfeature.sdk.MutableStructure; | ||
import dev.openfeature.sdk.Structure; | ||
import dev.openfeature.sdk.Value; | ||
|
||
/** | ||
* gRPC type conversion utils. | ||
*/ | ||
public class Convert { | ||
/** | ||
* Recursively convert protobuf structure to openfeature value. | ||
*/ | ||
public static Value convertObjectResponse(Struct protobuf) { | ||
return convertProtobufMap(protobuf.getFieldsMap()); | ||
} | ||
|
||
/** | ||
* Recursively convert the Evaluation context to a protobuf structure. | ||
*/ | ||
public static Struct convertContext(EvaluationContext ctx) { | ||
Map<String, Value> ctxMap = ctx.asMap(); | ||
// asMap() does not provide explicitly set targeting key (ex:- new | ||
// ImmutableContext("TargetingKey") ). | ||
// Hence, we add this explicitly here for targeting rule processing. | ||
ctxMap.put("targetingKey", new Value(ctx.getTargetingKey())); | ||
|
||
return convertMap(ctxMap).getStructValue(); | ||
} | ||
|
||
/** | ||
* Convert any openfeature value to a protobuf value. | ||
*/ | ||
public static com.google.protobuf.Value convertAny(Value value) { | ||
if (value.isList()) { | ||
return convertList(value.asList()); | ||
} else if (value.isStructure()) { | ||
return convertMap(value.asStructure().asMap()); | ||
} else { | ||
return convertPrimitive(value); | ||
} | ||
} | ||
|
||
/** | ||
* Convert any protobuf value to {@link Value}. | ||
*/ | ||
public static Value convertAny(com.google.protobuf.Value protobuf) { | ||
if (protobuf.hasListValue()) { | ||
return convertList(protobuf.getListValue()); | ||
} else if (protobuf.hasStructValue()) { | ||
return convertProtobufMap(protobuf.getStructValue().getFieldsMap()); | ||
} else { | ||
return convertPrimitive(protobuf); | ||
} | ||
} | ||
|
||
/** | ||
* Convert OpenFeature map to protobuf {@link com.google.protobuf.Value}. | ||
*/ | ||
public static com.google.protobuf.Value convertMap(Map<String, Value> map) { | ||
Map<String, com.google.protobuf.Value> values = new HashMap<>(); | ||
|
||
map.keySet().forEach((String key) -> { | ||
Value value = map.get(key); | ||
values.put(key, convertAny(value)); | ||
}); | ||
Struct struct = Struct.newBuilder() | ||
.putAllFields(values).build(); | ||
return com.google.protobuf.Value.newBuilder().setStructValue(struct).build(); | ||
} | ||
|
||
/** | ||
* Convert protobuf map with {@link com.google.protobuf.Value} to OpenFeature | ||
* map. | ||
*/ | ||
public static Value convertProtobufMap(Map<String, com.google.protobuf.Value> map) { | ||
return new Value(convertProtobufMapToStructure(map)); | ||
} | ||
|
||
/** | ||
* Convert protobuf map with {@link com.google.protobuf.Value} to OpenFeature | ||
* map. | ||
*/ | ||
public static Structure convertProtobufMapToStructure(Map<String, com.google.protobuf.Value> map) { | ||
Map<String, Value> values = new HashMap<>(); | ||
|
||
map.keySet().forEach((String key) -> { | ||
com.google.protobuf.Value value = map.get(key); | ||
values.put(key, convertAny(value)); | ||
}); | ||
return new MutableStructure(values); | ||
} | ||
|
||
/** | ||
* Convert OpenFeature list to protobuf {@link com.google.protobuf.Value}. | ||
*/ | ||
public static com.google.protobuf.Value convertList(List<Value> values) { | ||
ListValue list = ListValue.newBuilder() | ||
.addAllValues(values.stream() | ||
.map(v -> convertAny(v)).collect(Collectors.toList())) | ||
.build(); | ||
return com.google.protobuf.Value.newBuilder().setListValue(list).build(); | ||
} | ||
|
||
/** | ||
* Convert protobuf list to OpenFeature {@link com.google.protobuf.Value}. | ||
*/ | ||
public static Value convertList(ListValue protobuf) { | ||
return new Value(protobuf.getValuesList().stream().map(p -> convertAny(p)).collect(Collectors.toList())); | ||
} | ||
|
||
/** | ||
* Convert OpenFeature {@link Value} to protobuf | ||
* {@link com.google.protobuf.Value}. | ||
*/ | ||
public static com.google.protobuf.Value convertPrimitive(Value value) { | ||
com.google.protobuf.Value.Builder builder = com.google.protobuf.Value.newBuilder(); | ||
|
||
if (value.isBoolean()) { | ||
builder.setBoolValue(value.asBoolean()); | ||
} else if (value.isString()) { | ||
builder.setStringValue(value.asString()); | ||
} else if (value.isNumber()) { | ||
builder.setNumberValue(value.asDouble()); | ||
} else { | ||
builder.setNullValue(NullValue.NULL_VALUE); | ||
} | ||
return builder.build(); | ||
} | ||
|
||
/** | ||
* Convert protobuf {@link com.google.protobuf.Value} to OpenFeature | ||
* {@link Value}. | ||
*/ | ||
public static Value convertPrimitive(com.google.protobuf.Value protobuf) { | ||
final Value value; | ||
if (protobuf.hasBoolValue()) { | ||
value = new Value(protobuf.getBoolValue()); | ||
} else if (protobuf.hasStringValue()) { | ||
value = new Value(protobuf.getStringValue()); | ||
} else if (protobuf.hasNumberValue()) { | ||
value = new Value(protobuf.getNumberValue()); | ||
} else { | ||
value = new Value(); | ||
} | ||
|
||
return value; | ||
} | ||
|
||
/** | ||
* Get the specified protobuf field from the message. | ||
* | ||
* @param <T> type | ||
* @param message protobuf message | ||
* @param name field name | ||
* @return field value | ||
*/ | ||
public static <T> T getField(Message message, String name) { | ||
return (T) message.getField(getFieldDescriptor(message, name)); | ||
} | ||
|
||
/** | ||
* Get the specified protobuf field descriptor from the message. | ||
* | ||
* @param message protobuf message | ||
* @param name field name | ||
* @return field descriptor | ||
*/ | ||
public static Descriptors.FieldDescriptor getFieldDescriptor(Message message, String name) { | ||
return message.getDescriptorForType().findFieldByName(name); | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
.../flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/grpc/Constants.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package dev.openfeature.contrib.providers.flagd.resolver.grpc; | ||
|
||
/** | ||
* Constants for evaluation proto. | ||
*/ | ||
public class Constants { | ||
public static final String CONFIGURATION_CHANGE = "configuration_change"; | ||
public static final String PROVIDER_READY = "provider_ready"; | ||
public static final String FLAGS_KEY = "flags"; | ||
} |
Oops, something went wrong.