Skip to content

feat: add gRPC keepalive #930

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public final class Config {

static final int DEFAULT_DEADLINE = 500;
static final int DEFAULT_MAX_CACHE_SIZE = 1000;
static final long DEFAULT_KEEP_ALIVE = 0;

static final String RESOLVER_ENV_VAR = "FLAGD_RESOLVER";
static final String HOST_ENV_VAR_NAME = "FLAGD_HOST";
Expand All @@ -32,6 +33,7 @@ public final class Config {
static final String DEADLINE_MS_ENV_VAR_NAME = "FLAGD_DEADLINE_MS";
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 KEEP_ALIVE_ENV_VAR_NAME = "FLAGD_KEEP_ALIVE";

static final String RESOLVER_RPC = "rpc";
static final String RESOLVER_IN_PROCESS = "in-process";
Expand Down Expand Up @@ -64,6 +66,14 @@ static int fallBackToEnvOrDefault(String key, int defaultValue) {
}
}

static long fallBackToEnvOrDefault(String key, long defaultValue) {
try {
return System.getenv(key) != null ? Long.parseLong(System.getenv(key)) : defaultValue;
} catch (Exception e) {
return defaultValue;
}
}

static Resolver fromValueProvider(Function<String, String> provider) {
final String resolverVar = provider.apply(RESOLVER_ENV_VAR);
if (resolverVar == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@ public class FlagdOptions {
@Builder.Default
private String selector = fallBackToEnvOrDefault(Config.SOURCE_SELECTOR_ENV_VAR_NAME, null);

/**
* gRPC client KeepAlive in milliseconds. Disabled with 0.
* Defaults to 0 (disabled).
*
**/
@Builder.Default
private long keepAlive = fallBackToEnvOrDefault(Config.KEEP_ALIVE_ENV_VAR_NAME, Config.DEFAULT_KEEP_ALIVE);

/**
* File source of flags to be used by offline mode.
* Setting this enables the offline mode of the in-process provider.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import javax.net.ssl.SSLException;
import java.io.File;
import java.util.concurrent.TimeUnit;

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

return NettyChannelBuilder
.forAddress(new DomainSocketAddress(options.getSocketPath()))
// keepAliveTime: Long.MAX_VALUE disables keepAlive; very small values are increased automatically
.keepAliveTime(options.getKeepAlive() == 0 ? Long.MAX_VALUE : options.getKeepAlive(),
TimeUnit.MILLISECONDS)
.eventLoopGroup(new EpollEventLoopGroup())
.channelType(EpollDomainSocketChannel.class)
.usePlaintext()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import dev.openfeature.contrib.providers.flagd.resolver.process.storage.MockConnector;
import dev.openfeature.contrib.providers.flagd.resolver.process.storage.connector.Connector;
import io.opentelemetry.api.OpenTelemetry;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junitpioneer.jupiter.SetEnvironmentVariable;
import org.mockito.Mockito;
Expand Down Expand Up @@ -33,6 +32,7 @@ void TestDefaults() {
assertNull(builder.getCustomConnector());
assertNull(builder.getOfflineFlagSourcePath());
assertEquals(Resolver.RPC, builder.getResolverType());
assertEquals(0, builder.getKeepAlive());
}

@Test
Expand All @@ -53,6 +53,7 @@ void TestBuilderOptions() {
.openTelemetry(openTelemetry)
.customConnector(connector)
.resolverType(Resolver.IN_PROCESS)
.keepAlive(1000)
.build();

assertEquals("https://hosted-flagd", flagdOptions.getHost());
Expand All @@ -67,6 +68,7 @@ void TestBuilderOptions() {
assertEquals(openTelemetry, flagdOptions.getOpenTelemetry());
assertEquals(connector, flagdOptions.getCustomConnector());
assertEquals(Resolver.IN_PROCESS, flagdOptions.getResolverType());
assertEquals(1000, flagdOptions.getKeepAlive());
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.doAnswer;
Expand Down Expand Up @@ -277,6 +278,7 @@ private NettyChannelBuilder getMockChannelBuilderSocket() {
when(mockChannelBuilder.eventLoopGroup(any(EventLoopGroup.class))).thenReturn(mockChannelBuilder);
when(mockChannelBuilder.channelType(any(Class.class))).thenReturn(mockChannelBuilder);
when(mockChannelBuilder.usePlaintext()).thenReturn(mockChannelBuilder);
when(mockChannelBuilder.keepAliveTime(anyLong(), any())).thenReturn(mockChannelBuilder);
when(mockChannelBuilder.build()).thenReturn(null);
return mockChannelBuilder;
}
Expand Down
Loading