Skip to content

Commit

Permalink
introduce Resolver, a drop in replacement for deprecated Evaluator
Browse files Browse the repository at this point in the history
Signed-off-by: Kavindu Dodanduwa <[email protected]>
  • Loading branch information
Kavindu-Dodan committed May 17, 2024
1 parent f70e6c2 commit 9061607
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 28 deletions.
4 changes: 2 additions & 2 deletions providers/flagd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Consider the following example to create a `FlagdProvider` with in-process evalu
```java
FlagdProvider flagdProvider = new FlagdProvider(
FlagdOptions.builder()
.resolverType(Config.Evaluator.IN_PROCESS)
.resolverType(Config.Resolver.IN_PROCESS)
.build());
```

Expand All @@ -55,7 +55,7 @@ To enable this mode, you should provide a valid flag configuration file with the
```java
FlagdProvider flagdProvider = new FlagdProvider(
FlagdOptions.builder()
.resolverType(Config.Evaluator.IN_PROCESS)
.resolverType(Config.Resolver.IN_PROCESS)
.offlineFlagSourcePath("PATH")
.build());
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*/
@Slf4j
public final class Config {
static final Evaluator DEFAULT_RESOLVER_TYPE = Evaluator.RPC;
static final Resolver DEFAULT_RESOLVER_TYPE = Resolver.RPC;
static final String DEFAULT_PORT = "8013";
static final String DEFAULT_TLS = "false";
static final String DEFAULT_HOST = "localhost";
Expand All @@ -32,6 +32,9 @@ public final class Config {
static final String SOURCE_SELECTOR_ENV_VAR_NAME = "FLAGD_SOURCE_SELECTOR";
static final String OFFLINE_SOURCE_PATH = "FLAGD_OFFLINE_FLAG_SOURCE_PATH";

static final String RESOLVER_RPC = "rpc";
static final String RESOLVER_IN_PROCESS = "in-process";

public static final String STATIC_REASON = "STATIC";
public static final String CACHED_REASON = "CACHED";

Expand Down Expand Up @@ -60,37 +63,80 @@ static int fallBackToEnvOrDefault(String key, int defaultValue) {
}
}

static Evaluator fromValueProvider(Function<String, String> provider) {
static Resolver fromValueProvider(Function<String, String> provider) {
final String resolverVar = provider.apply(RESOLVER_ENV_VAR);
if (resolverVar == null) {
return DEFAULT_RESOLVER_TYPE;
}

switch (resolverVar.toLowerCase()) {
case "in-process":
return Evaluator.IN_PROCESS;
return Resolver.IN_PROCESS;
case "rpc":
return Evaluator.RPC;
return Resolver.RPC;
default:
log.warn("Unsupported resolver variable: {}", resolverVar);
return DEFAULT_RESOLVER_TYPE;
}
}

// intermediate interface to unify deprecated Evaluator & new Resolver
interface EvaluatorType {
String asString();
}

/**
* flagd evaluator type.
* <p>
* Deprecated : Please use {@code Config.Resolver}, which is a drop-in replacement of this.
*/
@Deprecated
public enum Evaluator implements EvaluatorType {
/**
* This is the default resolver type, which connects to flagd instance with flag evaluation gRPC contract.
* Evaluations are performed remotely.
*/
RPC {
public String asString() {
return RESOLVER_RPC;
}
},
/**
* This is the in-process resolving type, where flags are fetched with flag sync gRPC contract and stored
* locally for in-process evaluation.
* Evaluations are preformed in-process.
*/
IN_PROCESS {
public String asString() {
return RESOLVER_IN_PROCESS;
}
}

}


/**
* flagd Resolver type.
*/
public enum Evaluator {
public enum Resolver implements EvaluatorType {
/**
* This is the default resolver type, which connects to flagd instance with flag evaluation gRPC contract.
* Evaluations are performed remotely.
*/
RPC,
RPC {
public String asString() {
return RESOLVER_RPC;
}
},
/**
* This is the in-process resolving type, where flags are fetched with flag sync gRPC contract and stored
* locally for in-process evaluation.
* Evaluations are preformed in-process.
*/
IN_PROCESS
IN_PROCESS {
public String asString() {
return RESOLVER_IN_PROCESS;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class FlagdOptions {
* flagd resolving type.
*/
@Builder.Default
private Config.Evaluator resolverType = fromValueProvider(System::getenv);
private Config.EvaluatorType resolverType = fromValueProvider(System::getenv);

/**
* flagd connection host.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ public FlagdProvider() {
* @param options {@link FlagdOptions} with
*/
public FlagdProvider(final FlagdOptions options) {
switch (options.getResolverType()) {
case IN_PROCESS:
switch (options.getResolverType().asString()) {
case Config.RESOLVER_IN_PROCESS:
this.flagResolver = new InProcessResolver(options, this::setState);
break;
case RPC:
case Config.RESOLVER_RPC:
this.flagResolver =
new GrpcResolver(options,
new Cache(options.getCacheType(), options.getMaxCacheSize()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public void TestDefaults() {
assertNull(builder.getSelector());
assertNull(builder.getOpenTelemetry());
assertNull(builder.getOfflineFlagSourcePath());
assertEquals(Config.Evaluator.RPC, builder.getResolverType());
assertEquals(Config.Resolver.RPC, builder.getResolverType());
}

@Test
Expand All @@ -51,7 +51,7 @@ public void TestBuilderOptions() {
.selector("app=weatherApp")
.offlineFlagSourcePath("some-path")
.openTelemetry(openTelemetry)
.resolverType(Config.Evaluator.IN_PROCESS)
.resolverType(Config.Resolver.IN_PROCESS)
.build();

assertEquals("https://hosted-flagd", flagdOptions.getHost());
Expand All @@ -64,23 +64,23 @@ public void TestBuilderOptions() {
assertEquals("app=weatherApp", flagdOptions.getSelector());
assertEquals("some-path", flagdOptions.getOfflineFlagSourcePath());
assertEquals(openTelemetry, flagdOptions.getOpenTelemetry());
assertEquals(Config.Evaluator.IN_PROCESS, flagdOptions.getResolverType());
assertEquals(Config.Resolver.IN_PROCESS, flagdOptions.getResolverType());
}


@Test
public void testValueProviderForEdgeCase_valid() {
Function<String, String> valueProvider = s -> "in-process";
assertEquals(Config.Evaluator.IN_PROCESS, Config.fromValueProvider(valueProvider));
assertEquals(Config.Resolver.IN_PROCESS, Config.fromValueProvider(valueProvider));

valueProvider = s -> "IN-PROCESS";
assertEquals(Config.Evaluator.IN_PROCESS, Config.fromValueProvider(valueProvider));
assertEquals(Config.Resolver.IN_PROCESS, Config.fromValueProvider(valueProvider));

valueProvider = s -> "rpc";
assertEquals(Config.Evaluator.RPC, Config.fromValueProvider(valueProvider));
assertEquals(Config.Resolver.RPC, Config.fromValueProvider(valueProvider));

valueProvider = s -> "RPC";
assertEquals(Config.Evaluator.RPC, Config.fromValueProvider(valueProvider));
assertEquals(Config.Resolver.RPC, Config.fromValueProvider(valueProvider));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class FlagdInProcessSetup {
@BeforeAll()
public static void setup() throws InterruptedException {
FlagdInProcessSetup.provider = new FlagdProvider(FlagdOptions.builder()
.resolverType(Config.Evaluator.IN_PROCESS)
.resolverType(Config.Resolver.IN_PROCESS)
.deadline(3000)
.port(9090)
.build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ public class FlagdInProcessSetup {
@BeforeAll()
public static void setup() throws InterruptedException {
FeatureProvider workingProvider = new FlagdProvider(FlagdOptions.builder()
.resolverType(Config.Evaluator.IN_PROCESS)
.resolverType(Config.Resolver.IN_PROCESS)
.deadline(3000)
.port(9091)
.build());
StepDefinitions.setUnstableProvider(workingProvider);

FeatureProvider unavailableProvider = new FlagdProvider(FlagdOptions.builder()
.resolverType(Config.Evaluator.IN_PROCESS)
.resolverType(Config.Resolver.IN_PROCESS)
.deadline(100)
.port(9092) // this port isn't serving anything, error expected
.build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class FlagdRpcSetup {
@BeforeAll()
public static void setup() throws InterruptedException {
FeatureProvider workingProvider = new FlagdProvider(FlagdOptions.builder()
.resolverType(Config.Evaluator.RPC)
.resolverType(Config.Resolver.RPC)
.port(8014)
// set a generous deadline, to prevent timeouts in actions
.deadline(3000)
Expand All @@ -27,7 +27,7 @@ public static void setup() throws InterruptedException {
StepDefinitions.setUnstableProvider(workingProvider);

FeatureProvider unavailableProvider = new FlagdProvider(FlagdOptions.builder()
.resolverType(Config.Evaluator.RPC)
.resolverType(Config.Resolver.RPC)
.port(8015) // this port isn't serving anything, error expected
// set a generous deadline, to prevent timeouts in actions
.deadline(100)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class FlagdRpcSetup {
@BeforeAll()
public static void setup() {
FlagdRpcSetup.provider = new FlagdProvider(FlagdOptions.builder()
.resolverType(Config.Evaluator.RPC)
.resolverType(Config.Resolver.RPC)
// set a generous deadline, to prevent timeouts in actions
.deadline(3000)
.cacheType(CacheType.DISABLED.getValue())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ class InProcessResolverTest {
public void connectorSetup(){
// given
FlagdOptions forGrpcOptions =
FlagdOptions.builder().resolverType(Config.Evaluator.IN_PROCESS).host("localhost").port(8080).build();
FlagdOptions.builder().resolverType(Config.Resolver.IN_PROCESS).host("localhost").port(8080).build();
FlagdOptions forOfflineOptions =
FlagdOptions.builder().resolverType(Config.Evaluator.IN_PROCESS).offlineFlagSourcePath("path").build();
FlagdOptions.builder().resolverType(Config.Resolver.IN_PROCESS).offlineFlagSourcePath("path").build();

// then
assertInstanceOf(GrpcStreamConnector.class, InProcessResolver.getConnector(forGrpcOptions));
Expand Down

0 comments on commit 9061607

Please sign in to comment.