Skip to content

Commit e572e6a

Browse files
committed
move locks out to wasmresolverapi, remove retry strategy, handle isflushedexception
1 parent 38a21d8 commit e572e6a

File tree

10 files changed

+62
-251
lines changed

10 files changed

+62
-251
lines changed

openfeature-provider-local/src/main/java/com/spotify/confidence/ExponentialRetryStrategy.java

Lines changed: 0 additions & 65 deletions
This file was deleted.

openfeature-provider-local/src/main/java/com/spotify/confidence/LocalResolverServiceFactory.java

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -67,27 +67,22 @@ static FlagResolverService from(
6767
ApiSecret apiSecret,
6868
String clientSecret,
6969
boolean isWasm,
70-
StickyResolveStrategy stickyResolveStrategy,
71-
RetryStrategy retryStrategy) {
72-
return createFlagResolverService(
73-
apiSecret, clientSecret, isWasm, stickyResolveStrategy, retryStrategy);
70+
StickyResolveStrategy stickyResolveStrategy) {
71+
return createFlagResolverService(apiSecret, clientSecret, isWasm, stickyResolveStrategy);
7472
}
7573

7674
static FlagResolverService from(
7775
AccountStateProvider accountStateProvider,
7876
String accountId,
79-
StickyResolveStrategy stickyResolveStrategy,
80-
RetryStrategy retryStrategy) {
81-
return createFlagResolverService(
82-
accountStateProvider, accountId, stickyResolveStrategy, retryStrategy);
77+
StickyResolveStrategy stickyResolveStrategy) {
78+
return createFlagResolverService(accountStateProvider, accountId, stickyResolveStrategy);
8379
}
8480

8581
private static FlagResolverService createFlagResolverService(
8682
ApiSecret apiSecret,
8783
String clientSecret,
8884
boolean isWasm,
89-
StickyResolveStrategy stickyResolveStrategy,
90-
RetryStrategy retryStrategy) {
85+
StickyResolveStrategy stickyResolveStrategy) {
9186
final var channel = createConfidenceChannel();
9287
final AuthServiceBlockingStub authService = AuthServiceGrpc.newBlockingStub(channel);
9388
final TokenHolder tokenHolder =
@@ -116,8 +111,7 @@ private static FlagResolverService createFlagResolverService(
116111
wasmFlagLogger,
117112
sidecarFlagsAdminFetcher.rawStateHolder().get().toByteArray(),
118113
sidecarFlagsAdminFetcher.accountId,
119-
stickyResolveStrategy,
120-
retryStrategy);
114+
stickyResolveStrategy);
121115
flagsFetcherExecutor.scheduleAtFixedRate(
122116
sidecarFlagsAdminFetcher::reload,
123117
pollIntervalSeconds,
@@ -173,8 +167,7 @@ private static boolean getFailFast(StickyResolveStrategy stickyResolveStrategy)
173167
private static FlagResolverService createFlagResolverService(
174168
AccountStateProvider accountStateProvider,
175169
String accountId,
176-
StickyResolveStrategy stickyResolveStrategy,
177-
RetryStrategy retryStrategy) {
170+
StickyResolveStrategy stickyResolveStrategy) {
178171
final var mode = System.getenv("LOCAL_RESOLVE_MODE");
179172
if (!(mode == null || mode.equals("WASM"))) {
180173
throw new RuntimeException("Only WASM mode supported with AccountStateProvider");
@@ -187,7 +180,7 @@ private static FlagResolverService createFlagResolverService(
187180
final WasmFlagLogger flagLogger = request -> WriteFlagLogsResponse.getDefaultInstance();
188181
final ResolverApi wasmResolverApi =
189182
new ThreadLocalSwapWasmResolverApi(
190-
flagLogger, resolverStateProtobuf, accountId, stickyResolveStrategy, retryStrategy);
183+
flagLogger, resolverStateProtobuf, accountId, stickyResolveStrategy);
191184
flagsFetcherExecutor.scheduleAtFixedRate(
192185
() -> {
193186
wasmResolverApi.updateStateAndFlushLogs(accountStateProvider.provide(), accountId);

openfeature-provider-local/src/main/java/com/spotify/confidence/NoRetryStrategy.java

Lines changed: 0 additions & 11 deletions
This file was deleted.

openfeature-provider-local/src/main/java/com/spotify/confidence/OpenFeatureLocalResolveProvider.java

Lines changed: 7 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -90,28 +90,7 @@ public class OpenFeatureLocalResolveProvider implements FeatureProvider {
9090
* @since 0.2.4
9191
*/
9292
public OpenFeatureLocalResolveProvider(ApiSecret apiSecret, String clientSecret) {
93-
this(apiSecret, clientSecret, new RemoteResolverFallback(), new NoRetryStrategy());
94-
}
95-
96-
/**
97-
* Creates a new OpenFeature provider for local flag resolution with configurable sticky resolve
98-
* strategy and no retry.
99-
*
100-
* <p>The provider will automatically determine the resolution mode (WASM or Java) based on the
101-
* {@code LOCAL_RESOLVE_MODE} environment variable, defaulting to WASM mode.
102-
*
103-
* @param apiSecret the API credentials containing client ID and client secret for authenticating
104-
* with the Confidence service. Create using {@code new ApiSecret("client-id",
105-
* "client-secret")}
106-
* @param clientSecret the client secret for your application, used for flag resolution
107-
* authentication. This is different from the API secret and is specific to your application
108-
* configuration
109-
* @param stickyResolveStrategy the strategy to use for handling sticky flag resolution
110-
* @since 0.2.4
111-
*/
112-
public OpenFeatureLocalResolveProvider(
113-
ApiSecret apiSecret, String clientSecret, StickyResolveStrategy stickyResolveStrategy) {
114-
this(apiSecret, clientSecret, stickyResolveStrategy, new NoRetryStrategy());
93+
this(apiSecret, clientSecret, new RemoteResolverFallback());
11594
}
11695

11796
/**
@@ -128,56 +107,25 @@ public OpenFeatureLocalResolveProvider(
128107
* authentication. This is different from the API secret and is specific to your application
129108
* configuration
130109
* @param stickyResolveStrategy the strategy to use for handling sticky flag resolution
131-
* @param retryStrategy the retry strategy for WASM operations (use {@link NoRetryStrategy} to
132-
* disable retries or {@link ExponentialRetryStrategy} for exponential backoff)
133110
* @since 0.2.4
134111
*/
135112
public OpenFeatureLocalResolveProvider(
136-
ApiSecret apiSecret,
137-
String clientSecret,
138-
StickyResolveStrategy stickyResolveStrategy,
139-
RetryStrategy retryStrategy) {
113+
ApiSecret apiSecret, String clientSecret, StickyResolveStrategy stickyResolveStrategy) {
140114
final var env = System.getenv("LOCAL_RESOLVE_MODE");
141115
if (env != null && env.equals("WASM")) {
142116
this.flagResolverService =
143-
LocalResolverServiceFactory.from(
144-
apiSecret, clientSecret, true, stickyResolveStrategy, retryStrategy);
117+
LocalResolverServiceFactory.from(apiSecret, clientSecret, true, stickyResolveStrategy);
145118
} else if (env != null && env.equals("JAVA")) {
146119
this.flagResolverService =
147-
LocalResolverServiceFactory.from(
148-
apiSecret, clientSecret, false, stickyResolveStrategy, retryStrategy);
120+
LocalResolverServiceFactory.from(apiSecret, clientSecret, false, stickyResolveStrategy);
149121
} else {
150122
this.flagResolverService =
151-
LocalResolverServiceFactory.from(
152-
apiSecret, clientSecret, true, stickyResolveStrategy, retryStrategy);
123+
LocalResolverServiceFactory.from(apiSecret, clientSecret, true, stickyResolveStrategy);
153124
}
154125
this.stickyResolveStrategy = stickyResolveStrategy;
155126
this.clientSecret = clientSecret;
156127
}
157128

158-
/**
159-
* To be used for testing purposes only! This constructor allows to inject flags state for testing
160-
* the WASM resolver (no Java supported) No resolve/assign logging is forwarded to production No
161-
* need to supply ApiSecret
162-
*
163-
* @param accountStateProvider a functional interface that provides AccountState instances
164-
* @param clientSecret the flag client key used to filter the flags
165-
* @since 0.2.4
166-
*/
167-
@VisibleForTesting
168-
public OpenFeatureLocalResolveProvider(
169-
AccountStateProvider accountStateProvider,
170-
String accountId,
171-
String clientSecret,
172-
StickyResolveStrategy stickyResolveStrategy) {
173-
this(
174-
accountStateProvider,
175-
accountId,
176-
clientSecret,
177-
stickyResolveStrategy,
178-
new NoRetryStrategy());
179-
}
180-
181129
/**
182130
* To be used for testing purposes only! This constructor allows to inject flags state for testing
183131
* the WASM resolver with full control over retry strategy.
@@ -186,21 +134,18 @@ public OpenFeatureLocalResolveProvider(
186134
* @param accountId the account ID
187135
* @param clientSecret the flag client key used to filter the flags
188136
* @param stickyResolveStrategy the strategy to use for handling sticky flag resolution
189-
* @param retryStrategy the retry strategy for WASM operations
190137
* @since 0.2.4
191138
*/
192139
@VisibleForTesting
193140
public OpenFeatureLocalResolveProvider(
194141
AccountStateProvider accountStateProvider,
195142
String accountId,
196143
String clientSecret,
197-
StickyResolveStrategy stickyResolveStrategy,
198-
RetryStrategy retryStrategy) {
144+
StickyResolveStrategy stickyResolveStrategy) {
199145
this.stickyResolveStrategy = stickyResolveStrategy;
200146
this.clientSecret = clientSecret;
201147
this.flagResolverService =
202-
LocalResolverServiceFactory.from(
203-
accountStateProvider, accountId, stickyResolveStrategy, retryStrategy);
148+
LocalResolverServiceFactory.from(accountStateProvider, accountId, stickyResolveStrategy);
204149
}
205150

206151
@Override

openfeature-provider-local/src/main/java/com/spotify/confidence/RetryStrategy.java

Lines changed: 0 additions & 17 deletions
This file was deleted.

openfeature-provider-local/src/main/java/com/spotify/confidence/SwapWasmResolverApi.java

Lines changed: 15 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,72 +11,53 @@
1111
import java.util.concurrent.CompletableFuture;
1212
import java.util.concurrent.ExecutionException;
1313
import java.util.concurrent.atomic.AtomicReference;
14-
import java.util.concurrent.locks.ReentrantLock;
1514
import java.util.stream.Collectors;
1615

1716
class SwapWasmResolverApi implements ResolverApi {
1817
private final AtomicReference<WasmResolveApi> wasmResolverApiRef = new AtomicReference<>();
1918
private final StickyResolveStrategy stickyResolveStrategy;
2019
private final WasmFlagLogger flagLogger;
21-
private final RetryStrategy retryStrategy;
2220

2321
public SwapWasmResolverApi(
2422
WasmFlagLogger flagLogger,
2523
byte[] initialState,
2624
String accountId,
27-
StickyResolveStrategy stickyResolveStrategy,
28-
RetryStrategy retryStrategy) {
25+
StickyResolveStrategy stickyResolveStrategy) {
2926
this.stickyResolveStrategy = stickyResolveStrategy;
3027
this.flagLogger = flagLogger;
31-
this.retryStrategy = retryStrategy;
3228

3329
// Create initial instance
34-
final WasmResolveApi initialInstance = new WasmResolveApi(flagLogger, retryStrategy);
30+
final WasmResolveApi initialInstance = new WasmResolveApi(flagLogger);
3531
initialInstance.setResolverState(initialState, accountId);
3632
this.wasmResolverApiRef.set(initialInstance);
3733
}
3834

3935
@Override
4036
public void updateStateAndFlushLogs(byte[] state, String accountId) {
41-
logResolveLock.lock();
4237
// Create new instance with updated state
43-
final WasmResolveApi newInstance = new WasmResolveApi(flagLogger, retryStrategy);
38+
final WasmResolveApi newInstance = new WasmResolveApi(flagLogger);
4439
newInstance.setResolverState(state, accountId);
4540

4641
// Get current instance before switching
4742
final WasmResolveApi oldInstance = wasmResolverApiRef.getAndSet(newInstance);
48-
4943
if (oldInstance != null) {
5044
oldInstance.flushLogs();
51-
oldInstance.isIsFlushed(true);
5245
}
53-
logResolveLock.unlock();
5446
}
5547

5648
@Override
57-
public void close() {
58-
final WasmResolveApi currentInstance = wasmResolverApiRef.get();
59-
if (currentInstance != null) {
60-
// Note: WasmResolveApi doesn't have a close method, so this is a no-op for now
61-
// but the instance will be GC'd naturally
62-
}
63-
}
64-
65-
private final ReentrantLock logResolveLock = new ReentrantLock();
49+
public void close() {}
6650

6751
@Override
6852
public CompletableFuture<ResolveFlagsResponse> resolveWithSticky(
6953
ResolveWithStickyRequest request) {
70-
logResolveLock.lock();
71-
final var response = resolveWithStickyInternal(request);
72-
logResolveLock.unlock();
73-
return response;
74-
}
75-
76-
private CompletableFuture<ResolveFlagsResponse> resolveWithStickyInternal(
77-
ResolveWithStickyRequest request) {
7854
final var instance = wasmResolverApiRef.get();
79-
final var response = instance.resolveWithSticky(request);
55+
final ResolveWithStickyResponse response;
56+
try {
57+
response = instance.resolveWithSticky(request);
58+
} catch (IsFlushedException e) {
59+
return resolveWithSticky(request);
60+
}
8061

8162
switch (response.getResolveResultCase()) {
8263
case SUCCESS -> {
@@ -85,9 +66,6 @@ private CompletableFuture<ResolveFlagsResponse> resolveWithStickyInternal(
8566
if (!success.getUpdatesList().isEmpty()) {
8667
storeUpdates(success.getUpdatesList());
8768
}
88-
if (instance.isFlushed()) {
89-
CompletableFuture.runAsync(instance::flushLogs);
90-
}
9169
return CompletableFuture.completedFuture(success.getResponse());
9270
}
9371
case MISSING_MATERIALIZATIONS -> {
@@ -103,7 +81,7 @@ private CompletableFuture<ResolveFlagsResponse> resolveWithStickyInternal(
10381
final var currentRequest =
10482
handleMissingMaterializations(
10583
request, missingMaterializations.getItemsList(), repository);
106-
return resolveWithStickyInternal(currentRequest);
84+
return resolveWithSticky(currentRequest);
10785
}
10886

10987
throw new RuntimeException(
@@ -208,13 +186,11 @@ private ResolveWithStickyRequest handleMissingMaterializations(
208186

209187
@Override
210188
public ResolveFlagsResponse resolve(ResolveFlagsRequest request) {
211-
logResolveLock.lock();
212189
final var instance = wasmResolverApiRef.get();
213-
final var response = instance.resolve(request);
214-
if (instance.isFlushed()) {
215-
CompletableFuture.runAsync(instance::flushLogs);
190+
try {
191+
return instance.resolve(request);
192+
} catch (IsFlushedException e) {
193+
return resolve(request);
216194
}
217-
logResolveLock.unlock();
218-
return response;
219195
}
220196
}

0 commit comments

Comments
 (0)