Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.spotify.confidence.shaded.flags.resolver.v1.InternalFlagLoggerServiceGrpc;
import com.spotify.confidence.shaded.flags.resolver.v1.WriteFlagLogsRequest;
import com.spotify.confidence.shaded.flags.resolver.v1.WriteFlagLogsResponse;
import com.spotify.confidence.shaded.iam.v1.AuthServiceGrpc;
import io.grpc.Channel;
import io.grpc.ClientInterceptors;
Expand All @@ -16,7 +15,7 @@
public class GrpcWasmFlagLogger implements WasmFlagLogger {
private static final String CONFIDENCE_DOMAIN = "edge-grpc.spotify.com";
private static final Logger logger = LoggerFactory.getLogger(GrpcWasmFlagLogger.class);
private final InternalFlagLoggerServiceGrpc.InternalFlagLoggerServiceBlockingStub stub;
private final InternalFlagLoggerServiceGrpc.InternalFlagLoggerServiceFutureStub stub;

public GrpcWasmFlagLogger(ApiSecret apiSecret) {
final var channel = createConfidenceChannel();
Expand All @@ -27,12 +26,12 @@ public GrpcWasmFlagLogger(ApiSecret apiSecret) {
final TokenHolder.Token token = tokenHolder.getToken();
final Channel authenticatedChannel =
ClientInterceptors.intercept(channel, new JwtAuthClientInterceptor(tokenHolder));
this.stub = InternalFlagLoggerServiceGrpc.newBlockingStub(authenticatedChannel);
this.stub = InternalFlagLoggerServiceGrpc.newFutureStub(authenticatedChannel);
}

@Override
public WriteFlagLogsResponse write(WriteFlagLogsRequest request) {
return stub.writeFlagLogs(request);
public void write(WriteFlagLogsRequest request) {
final var ignore = stub.writeFlagLogs(request);
}

private static ManagedChannel createConfidenceChannel() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class LocalResolverServiceFactory implements ResolverServiceFactory {
private static final MetricRegistry metricRegistry = new MetricRegistry();
private static final String CONFIDENCE_DOMAIN = "edge-grpc.spotify.com";
private static final Duration ASSIGN_LOG_INTERVAL = Duration.ofSeconds(10);
private static final Duration POLL_LOG_INTERVAL = Duration.ofSeconds(10);
private static final ScheduledExecutorService flagsFetcherExecutor =
Executors.newScheduledThreadPool(1, new ThreadFactoryBuilder().setDaemon(true).build());
private static final Duration RESOLVE_INFO_LOG_INTERVAL = Duration.ofMinutes(1);
Expand All @@ -67,27 +68,22 @@ static FlagResolverService from(
ApiSecret apiSecret,
String clientSecret,
boolean isWasm,
StickyResolveStrategy stickyResolveStrategy,
RetryStrategy retryStrategy) {
return createFlagResolverService(
apiSecret, clientSecret, isWasm, stickyResolveStrategy, retryStrategy);
StickyResolveStrategy stickyResolveStrategy) {
return createFlagResolverService(apiSecret, clientSecret, isWasm, stickyResolveStrategy);
}

static FlagResolverService from(
AccountStateProvider accountStateProvider,
String accountId,
StickyResolveStrategy stickyResolveStrategy,
RetryStrategy retryStrategy) {
return createFlagResolverService(
accountStateProvider, accountId, stickyResolveStrategy, retryStrategy);
StickyResolveStrategy stickyResolveStrategy) {
return createFlagResolverService(accountStateProvider, accountId, stickyResolveStrategy);
}

private static FlagResolverService createFlagResolverService(
ApiSecret apiSecret,
String clientSecret,
boolean isWasm,
StickyResolveStrategy stickyResolveStrategy,
RetryStrategy retryStrategy) {
StickyResolveStrategy stickyResolveStrategy) {
final var channel = createConfidenceChannel();
final AuthServiceBlockingStub authService = AuthServiceGrpc.newBlockingStub(channel);
final TokenHolder tokenHolder =
Expand Down Expand Up @@ -116,8 +112,7 @@ private static FlagResolverService createFlagResolverService(
wasmFlagLogger,
sidecarFlagsAdminFetcher.rawStateHolder().get().toByteArray(),
sidecarFlagsAdminFetcher.accountId,
stickyResolveStrategy,
retryStrategy);
stickyResolveStrategy);
flagsFetcherExecutor.scheduleAtFixedRate(
sidecarFlagsAdminFetcher::reload,
pollIntervalSeconds,
Expand All @@ -130,8 +125,8 @@ private static FlagResolverService createFlagResolverService(
sidecarFlagsAdminFetcher.rawStateHolder().get().toByteArray(),
sidecarFlagsAdminFetcher.accountId);
},
10,
10,
POLL_LOG_INTERVAL.getSeconds(),
POLL_LOG_INTERVAL.getSeconds(),
TimeUnit.SECONDS);

return new WasmFlagResolverService(wasmResolverApi, stickyResolveStrategy);
Expand Down Expand Up @@ -173,8 +168,7 @@ private static boolean getFailFast(StickyResolveStrategy stickyResolveStrategy)
private static FlagResolverService createFlagResolverService(
AccountStateProvider accountStateProvider,
String accountId,
StickyResolveStrategy stickyResolveStrategy,
RetryStrategy retryStrategy) {
StickyResolveStrategy stickyResolveStrategy) {
final var mode = System.getenv("LOCAL_RESOLVE_MODE");
if (!(mode == null || mode.equals("WASM"))) {
throw new RuntimeException("Only WASM mode supported with AccountStateProvider");
Expand All @@ -183,19 +177,22 @@ private static FlagResolverService createFlagResolverService(
Optional.ofNullable(System.getenv("CONFIDENCE_RESOLVER_POLL_INTERVAL_SECONDS"))
.map(Long::parseLong)
.orElse(Duration.ofMinutes(5).toSeconds());
final byte[] resolverStateProtobuf = accountStateProvider.provide();
final AtomicReference<byte[]> resolverStateProtobuf =
new AtomicReference<>(accountStateProvider.provide());
final WasmFlagLogger flagLogger = request -> WriteFlagLogsResponse.getDefaultInstance();
final ResolverApi wasmResolverApi =
new ThreadLocalSwapWasmResolverApi(
flagLogger, resolverStateProtobuf, accountId, stickyResolveStrategy, retryStrategy);
flagLogger, resolverStateProtobuf.get(), accountId, stickyResolveStrategy);
flagsFetcherExecutor.scheduleAtFixedRate(
() -> {
wasmResolverApi.updateStateAndFlushLogs(accountStateProvider.provide(), accountId);
},
() -> resolverStateProtobuf.set(accountStateProvider.provide()),
pollIntervalSeconds,
pollIntervalSeconds,
TimeUnit.SECONDS);

logPollExecutor.scheduleAtFixedRate(
() -> wasmResolverApi.updateStateAndFlushLogs(resolverStateProtobuf.get(), accountId),
POLL_LOG_INTERVAL.getSeconds(),
POLL_LOG_INTERVAL.getSeconds(),
TimeUnit.SECONDS);
return new WasmFlagResolverService(wasmResolverApi, stickyResolveStrategy);
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -90,28 +90,7 @@ public class OpenFeatureLocalResolveProvider implements FeatureProvider {
* @since 0.2.4
*/
public OpenFeatureLocalResolveProvider(ApiSecret apiSecret, String clientSecret) {
this(apiSecret, clientSecret, new RemoteResolverFallback(), new NoRetryStrategy());
}

/**
* Creates a new OpenFeature provider for local flag resolution with configurable sticky resolve
* strategy and no retry.
*
* <p>The provider will automatically determine the resolution mode (WASM or Java) based on the
* {@code LOCAL_RESOLVE_MODE} environment variable, defaulting to WASM mode.
*
* @param apiSecret the API credentials containing client ID and client secret for authenticating
* with the Confidence service. Create using {@code new ApiSecret("client-id",
* "client-secret")}
* @param clientSecret the client secret for your application, used for flag resolution
* authentication. This is different from the API secret and is specific to your application
* configuration
* @param stickyResolveStrategy the strategy to use for handling sticky flag resolution
* @since 0.2.4
*/
public OpenFeatureLocalResolveProvider(
ApiSecret apiSecret, String clientSecret, StickyResolveStrategy stickyResolveStrategy) {
this(apiSecret, clientSecret, stickyResolveStrategy, new NoRetryStrategy());
this(apiSecret, clientSecret, new RemoteResolverFallback());
}

/**
Expand All @@ -128,56 +107,25 @@ public OpenFeatureLocalResolveProvider(
* authentication. This is different from the API secret and is specific to your application
* configuration
* @param stickyResolveStrategy the strategy to use for handling sticky flag resolution
* @param retryStrategy the retry strategy for WASM operations (use {@link NoRetryStrategy} to
* disable retries or {@link ExponentialRetryStrategy} for exponential backoff)
* @since 0.2.4
*/
public OpenFeatureLocalResolveProvider(
ApiSecret apiSecret,
String clientSecret,
StickyResolveStrategy stickyResolveStrategy,
RetryStrategy retryStrategy) {
ApiSecret apiSecret, String clientSecret, StickyResolveStrategy stickyResolveStrategy) {
final var env = System.getenv("LOCAL_RESOLVE_MODE");
if (env != null && env.equals("WASM")) {
this.flagResolverService =
LocalResolverServiceFactory.from(
apiSecret, clientSecret, true, stickyResolveStrategy, retryStrategy);
LocalResolverServiceFactory.from(apiSecret, clientSecret, true, stickyResolveStrategy);
} else if (env != null && env.equals("JAVA")) {
this.flagResolverService =
LocalResolverServiceFactory.from(
apiSecret, clientSecret, false, stickyResolveStrategy, retryStrategy);
LocalResolverServiceFactory.from(apiSecret, clientSecret, false, stickyResolveStrategy);
} else {
this.flagResolverService =
LocalResolverServiceFactory.from(
apiSecret, clientSecret, true, stickyResolveStrategy, retryStrategy);
LocalResolverServiceFactory.from(apiSecret, clientSecret, true, stickyResolveStrategy);
}
this.stickyResolveStrategy = stickyResolveStrategy;
this.clientSecret = clientSecret;
}

/**
* To be used for testing purposes only! This constructor allows to inject flags state for testing
* the WASM resolver (no Java supported) No resolve/assign logging is forwarded to production No
* need to supply ApiSecret
*
* @param accountStateProvider a functional interface that provides AccountState instances
* @param clientSecret the flag client key used to filter the flags
* @since 0.2.4
*/
@VisibleForTesting
public OpenFeatureLocalResolveProvider(
AccountStateProvider accountStateProvider,
String accountId,
String clientSecret,
StickyResolveStrategy stickyResolveStrategy) {
this(
accountStateProvider,
accountId,
clientSecret,
stickyResolveStrategy,
new NoRetryStrategy());
}

/**
* To be used for testing purposes only! This constructor allows to inject flags state for testing
* the WASM resolver with full control over retry strategy.
Expand All @@ -186,21 +134,18 @@ public OpenFeatureLocalResolveProvider(
* @param accountId the account ID
* @param clientSecret the flag client key used to filter the flags
* @param stickyResolveStrategy the strategy to use for handling sticky flag resolution
* @param retryStrategy the retry strategy for WASM operations
* @since 0.2.4
*/
@VisibleForTesting
public OpenFeatureLocalResolveProvider(
AccountStateProvider accountStateProvider,
String accountId,
String clientSecret,
StickyResolveStrategy stickyResolveStrategy,
RetryStrategy retryStrategy) {
StickyResolveStrategy stickyResolveStrategy) {
this.stickyResolveStrategy = stickyResolveStrategy;
this.clientSecret = clientSecret;
this.flagResolverService =
LocalResolverServiceFactory.from(
accountStateProvider, accountId, stickyResolveStrategy, retryStrategy);
LocalResolverServiceFactory.from(accountStateProvider, accountId, stickyResolveStrategy);
}

@Override
Expand Down

This file was deleted.

Loading