Skip to content

Commit c6c85a4

Browse files
authored
fix: wait saveConfiguration futures (#46)
wait for saveConfig futures, include empty config static string.
1 parent 6fc6b4b commit c6c85a4

File tree

3 files changed

+41
-35
lines changed

3 files changed

+41
-35
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ plugins {
66
}
77

88
group = 'cloud.eppo'
9-
version = '3.3.0-SNAPSHOT'
9+
version = '3.3.1-SNAPSHOT'
1010
ext.isReleaseVersion = !version.endsWith("SNAPSHOT")
1111

1212
java {

src/main/java/cloud/eppo/ConfigurationRequestor.java

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import cloud.eppo.api.Configuration;
44
import java.util.concurrent.CompletableFuture;
5-
import java.util.concurrent.CompletionException;
65
import java.util.concurrent.ExecutionException;
76
import org.jetbrains.annotations.NotNull;
87
import org.slf4j.Logger;
@@ -39,12 +38,8 @@ public void setInitialConfiguration(@NotNull Configuration configuration) {
3938
throw new IllegalStateException("Initial configuration has already been set");
4039
}
4140

42-
try {
43-
configurationStore.saveConfiguration(configuration).join();
44-
initialConfigSet = true;
45-
} catch (CompletionException e) {
46-
log.error("Error setting initial configuration", e);
47-
}
41+
initialConfigSet =
42+
configurationStore.saveConfiguration(configuration).thenApply(v -> true).join();
4843
}
4944

5045
// Asynchronously sets the initial configuration.
@@ -54,23 +49,32 @@ public CompletableFuture<Void> setInitialConfiguration(
5449
throw new IllegalStateException("Configuration future has already been set");
5550
}
5651
this.configurationFuture =
57-
configurationFuture.thenAccept(
58-
(config) -> {
59-
synchronized (configurationStore) {
60-
if (config == null) {
61-
log.debug("Initial configuration future returned null");
62-
} else if (remoteFetchFuture != null
63-
&& remoteFetchFuture.isDone()
64-
&& !remoteFetchFuture.isCompletedExceptionally()) {
65-
// Don't clobber a successful fetch.
66-
log.debug("Fetch successfully beat the initial config; not clobbering");
67-
} else {
68-
log.debug("saving initial configuration");
69-
configurationStore.saveConfiguration(config);
70-
initialConfigSet = true;
71-
}
72-
}
73-
});
52+
configurationFuture
53+
.thenAccept(
54+
(config) -> {
55+
synchronized (configurationStore) {
56+
if (config == null || config.isEmpty()) {
57+
log.debug("Initial configuration future returned empty/null");
58+
} else if (remoteFetchFuture != null
59+
&& remoteFetchFuture.isDone()
60+
&& !remoteFetchFuture.isCompletedExceptionally()) {
61+
// Don't clobber a successful fetch.
62+
log.debug("Fetch has completed; ignoring initial config load.");
63+
} else {
64+
log.debug("saving initial configuration");
65+
initialConfigSet =
66+
configurationStore
67+
.saveConfiguration(config)
68+
.thenApply((s) -> true)
69+
.join();
70+
}
71+
}
72+
})
73+
.exceptionally(
74+
(e) -> {
75+
log.error("Error setting initial config", e);
76+
return null;
77+
});
7478
return this.configurationFuture;
7579
}
7680

@@ -91,7 +95,7 @@ void fetchAndSaveFromRemote() {
9195
configBuilder.banditParameters(banditParametersJsonBytes);
9296
}
9397

94-
configurationStore.saveConfiguration(configBuilder.build());
98+
configurationStore.saveConfiguration(configBuilder.build()).join();
9599
}
96100

97101
/** Loads configuration asynchronously from the API server, off-thread. */
@@ -128,15 +132,9 @@ CompletableFuture<Void> fetchAndSaveFromRemoteAsync() {
128132
configBuilder.banditParameters(banditParametersJsonBytes);
129133
}
130134
}
131-
return configBuilder.build();
132-
}
133-
})
134-
.thenApply(
135-
configuration -> {
136-
synchronized (configurationStore) {
137-
configurationStore.saveConfiguration(configuration);
135+
136+
return configurationStore.saveConfiguration(configBuilder.build()).join();
138137
}
139-
return null;
140138
});
141139
return remoteFetchFuture;
142140
}

src/main/java/cloud/eppo/api/Configuration.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ public class Configuration {
5252
private static final ObjectMapper mapper =
5353
new ObjectMapper().registerModule(EppoModule.eppoModule());
5454

55+
private static final byte[] emptyFlagsBytes =
56+
"{ \"flags\": {}, \"format\": \"SERVER\" }".getBytes();
57+
5558
private static final Logger log = LoggerFactory.getLogger(Configuration.class);
5659
private final Map<String, BanditReference> banditReferences;
5760
private final Map<String, FlagConfig> flags;
@@ -95,7 +98,12 @@ private Configuration(
9598

9699
public static Configuration emptyConfig() {
97100
return new Configuration(
98-
Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap(), false, null, null);
101+
Collections.emptyMap(),
102+
Collections.emptyMap(),
103+
Collections.emptyMap(),
104+
false,
105+
emptyFlagsBytes,
106+
null);
99107
}
100108

101109
public FlagConfig getFlag(String flagKey) {

0 commit comments

Comments
 (0)