Skip to content

Commit 6833433

Browse files
authored
feat: add gRPC keepalive (#930)
Signed-off-by: Todd Baert <[email protected]>
1 parent fa663a2 commit 6833433

File tree

6 files changed

+28
-1
lines changed

6 files changed

+28
-1
lines changed

providers/flagd/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ Given below are the supported configurations:
105105
| socketPath | FLAGD_SOCKET_PATH | String | null | rpc & in-process |
106106
| certPath | FLAGD_SERVER_CERT_PATH | String | null | rpc & in-process |
107107
| deadline | FLAGD_DEADLINE_MS | int | 500 | rpc & in-process |
108+
| keepAliveTime | FLAGD_KEEP_ALIVE_TIME | long | 0 | rpc & in-process |
108109
| selector | FLAGD_SOURCE_SELECTOR | String | null | in-process |
109110
| cache | FLAGD_CACHE | String - lru, disabled | lru | rpc |
110111
| maxCacheSize | FLAGD_MAX_CACHE_SIZE | int | 1000 | rpc |

providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/Config.java

+10
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public final class Config {
1818

1919
static final int DEFAULT_DEADLINE = 500;
2020
static final int DEFAULT_MAX_CACHE_SIZE = 1000;
21+
static final long DEFAULT_KEEP_ALIVE = 0;
2122

2223
static final String RESOLVER_ENV_VAR = "FLAGD_RESOLVER";
2324
static final String HOST_ENV_VAR_NAME = "FLAGD_HOST";
@@ -32,6 +33,7 @@ public final class Config {
3233
static final String DEADLINE_MS_ENV_VAR_NAME = "FLAGD_DEADLINE_MS";
3334
static final String SOURCE_SELECTOR_ENV_VAR_NAME = "FLAGD_SOURCE_SELECTOR";
3435
static final String OFFLINE_SOURCE_PATH = "FLAGD_OFFLINE_FLAG_SOURCE_PATH";
36+
static final String KEEP_ALIVE_ENV_VAR_NAME = "FLAGD_KEEP_ALIVE_TIME";
3537

3638
static final String RESOLVER_RPC = "rpc";
3739
static final String RESOLVER_IN_PROCESS = "in-process";
@@ -64,6 +66,14 @@ static int fallBackToEnvOrDefault(String key, int defaultValue) {
6466
}
6567
}
6668

69+
static long fallBackToEnvOrDefault(String key, long defaultValue) {
70+
try {
71+
return System.getenv(key) != null ? Long.parseLong(System.getenv(key)) : defaultValue;
72+
} catch (Exception e) {
73+
return defaultValue;
74+
}
75+
}
76+
6777
static Resolver fromValueProvider(Function<String, String> provider) {
6878
final String resolverVar = provider.apply(RESOLVER_ENV_VAR);
6979
if (resolverVar == null) {

providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/FlagdOptions.java

+8
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,14 @@ public class FlagdOptions {
9393
@Builder.Default
9494
private String selector = fallBackToEnvOrDefault(Config.SOURCE_SELECTOR_ENV_VAR_NAME, null);
9595

96+
/**
97+
* gRPC client KeepAlive in milliseconds. Disabled with 0.
98+
* Defaults to 0 (disabled).
99+
*
100+
**/
101+
@Builder.Default
102+
private long keepAlive = fallBackToEnvOrDefault(Config.KEEP_ALIVE_ENV_VAR_NAME, Config.DEFAULT_KEEP_ALIVE);
103+
96104
/**
97105
* File source of flags to be used by offline mode.
98106
* Setting this enables the offline mode of the in-process provider.

providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/common/ChannelBuilder.java

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import javax.net.ssl.SSLException;
1515
import java.io.File;
16+
import java.util.concurrent.TimeUnit;
1617

1718
/**
1819
* gRPC channel builder helper.
@@ -36,6 +37,9 @@ public static ManagedChannel nettyChannel(final FlagdOptions options) {
3637

3738
return NettyChannelBuilder
3839
.forAddress(new DomainSocketAddress(options.getSocketPath()))
40+
// keepAliveTime: Long.MAX_VALUE disables keepAlive; very small values are increased automatically
41+
.keepAliveTime(options.getKeepAlive() == 0 ? Long.MAX_VALUE : options.getKeepAlive(),
42+
TimeUnit.MILLISECONDS)
3943
.eventLoopGroup(new EpollEventLoopGroup())
4044
.channelType(EpollDomainSocketChannel.class)
4145
.usePlaintext()

providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdOptionsTest.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import dev.openfeature.contrib.providers.flagd.resolver.process.storage.MockConnector;
44
import dev.openfeature.contrib.providers.flagd.resolver.process.storage.connector.Connector;
55
import io.opentelemetry.api.OpenTelemetry;
6-
import org.junit.jupiter.api.Disabled;
76
import org.junit.jupiter.api.Test;
87
import org.junitpioneer.jupiter.SetEnvironmentVariable;
98
import org.mockito.Mockito;
@@ -33,6 +32,7 @@ void TestDefaults() {
3332
assertNull(builder.getCustomConnector());
3433
assertNull(builder.getOfflineFlagSourcePath());
3534
assertEquals(Resolver.RPC, builder.getResolverType());
35+
assertEquals(0, builder.getKeepAlive());
3636
}
3737

3838
@Test
@@ -53,6 +53,7 @@ void TestBuilderOptions() {
5353
.openTelemetry(openTelemetry)
5454
.customConnector(connector)
5555
.resolverType(Resolver.IN_PROCESS)
56+
.keepAlive(1000)
5657
.build();
5758

5859
assertEquals("https://hosted-flagd", flagdOptions.getHost());
@@ -67,6 +68,7 @@ void TestBuilderOptions() {
6768
assertEquals(openTelemetry, flagdOptions.getOpenTelemetry());
6869
assertEquals(connector, flagdOptions.getCustomConnector());
6970
assertEquals(Resolver.IN_PROCESS, flagdOptions.getResolverType());
71+
assertEquals(1000, flagdOptions.getKeepAlive());
7072
}
7173

7274

providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/resolver/grpc/GrpcConnectorTest.java

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import static org.junit.jupiter.api.Assertions.assertThrows;
66
import static org.mockito.ArgumentMatchers.any;
77
import static org.mockito.ArgumentMatchers.anyInt;
8+
import static org.mockito.ArgumentMatchers.anyLong;
89
import static org.mockito.ArgumentMatchers.anyString;
910
import static org.mockito.ArgumentMatchers.argThat;
1011
import static org.mockito.Mockito.doAnswer;
@@ -277,6 +278,7 @@ private NettyChannelBuilder getMockChannelBuilderSocket() {
277278
when(mockChannelBuilder.eventLoopGroup(any(EventLoopGroup.class))).thenReturn(mockChannelBuilder);
278279
when(mockChannelBuilder.channelType(any(Class.class))).thenReturn(mockChannelBuilder);
279280
when(mockChannelBuilder.usePlaintext()).thenReturn(mockChannelBuilder);
281+
when(mockChannelBuilder.keepAliveTime(anyLong(), any())).thenReturn(mockChannelBuilder);
280282
when(mockChannelBuilder.build()).thenReturn(null);
281283
return mockChannelBuilder;
282284
}

0 commit comments

Comments
 (0)