Skip to content

Commit f0ba701

Browse files
authored
chore: Parse Last Modified Header (#159)
* Last modified parsing * Last modified parsing
1 parent 6128289 commit f0ba701

File tree

3 files changed

+27
-5
lines changed

3 files changed

+27
-5
lines changed

src/main/java/com/devcycle/sdk/server/common/api/IDevCycleApi.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public interface IDevCycleApi {
6262
*/
6363
@Headers({"Content-Type:application/json"})
6464
@GET("config/v1/server/{sdkToken}.json")
65-
Call<ProjectConfig> getConfig(@Path("sdkToken") String sdkToken, @Header("If-None-Match") String etag);
65+
Call<ProjectConfig> getConfig(@Path("sdkToken") String sdkToken, @Header("If-None-Match") String etag, @Header("If-Modified-Since") String lastModified);
6666

6767
/**
6868
* Post events to DevCycle for user

src/main/java/com/devcycle/sdk/server/local/managers/EnvironmentConfigManager.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import retrofit2.Response;
1717

1818
import java.io.IOException;
19+
import java.time.ZonedDateTime;
20+
import java.time.format.DateTimeFormatter;
1921
import java.util.concurrent.Executors;
2022
import java.util.concurrent.ScheduledExecutorService;
2123
import java.util.concurrent.TimeUnit;
@@ -30,6 +32,7 @@ public final class EnvironmentConfigManager {
3032

3133
private ProjectConfig config;
3234
private String configETag = "";
35+
private String configLastModified = "";
3336

3437
private final String sdkKey;
3538
private final int pollingIntervalMS;
@@ -69,7 +72,7 @@ public boolean isConfigInitialized() {
6972
}
7073

7174
private ProjectConfig getConfig() throws DevCycleException {
72-
Call<ProjectConfig> config = this.configApiClient.getConfig(this.sdkKey, this.configETag);
75+
Call<ProjectConfig> config = this.configApiClient.getConfig(this.sdkKey, this.configETag, this.configLastModified);
7376
this.config = getResponseWithRetries(config, 1);
7477
return this.config;
7578
}
@@ -129,23 +132,42 @@ private ProjectConfig getConfigResponse(Call<ProjectConfig> call) throws DevCycl
129132

130133
if (response.isSuccessful()) {
131134
String currentETag = response.headers().get("ETag");
135+
String headerLastModified = response.headers().get("Last-Modified");
136+
137+
if (!this.configLastModified.isEmpty() && headerLastModified != null && !headerLastModified.isEmpty()) {
138+
ZonedDateTime parsedLastModified = ZonedDateTime.parse(
139+
headerLastModified,
140+
DateTimeFormatter.RFC_1123_DATE_TIME
141+
);
142+
ZonedDateTime configLastModified = ZonedDateTime.parse(
143+
this.configLastModified,
144+
DateTimeFormatter.RFC_1123_DATE_TIME
145+
);
146+
147+
if (parsedLastModified.isBefore(configLastModified)) {
148+
DevCycleLogger.warning("Received a config with last-modified header before the current stored timestamp. Not saving config.");
149+
return this.config;
150+
}
151+
}
152+
132153
ProjectConfig config = response.body();
133154
try {
134155
ObjectMapper mapper = new ObjectMapper();
135156
localBucketing.storeConfig(sdkKey, mapper.writeValueAsString(config));
136157
} catch (JsonProcessingException e) {
137158
if (this.config != null) {
138-
DevCycleLogger.error("Unable to parse config with etag: " + currentETag + ". Using cache, etag " + this.configETag);
159+
DevCycleLogger.error("Unable to parse config with etag: " + currentETag + ". Using cache, etag " + this.configETag + " last-modified: " + this.configLastModified);
139160
return this.config;
140161
} else {
141162
errorResponse.setMessage(e.getMessage());
142163
throw new DevCycleException(HttpResponseCode.SERVER_ERROR, errorResponse);
143164
}
144165
}
145166
this.configETag = currentETag;
167+
this.configLastModified = headerLastModified;
146168
return response.body();
147169
} else if (httpResponseCode == HttpResponseCode.NOT_MODIFIED) {
148-
DevCycleLogger.debug("Config not modified, using cache, etag: " + this.configETag);
170+
DevCycleLogger.debug("Config not modified, using cache, etag: " + this.configETag + " last-modified: " + this.configLastModified);
149171
return this.config;
150172
} else {
151173
if (response.errorBody() != null) {

src/test/java/com/devcycle/sdk/server/common/api/DVCApiMock.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public Call<DevCycleResponse> track(DevCycleUserAndEvents userAndEvents, Boolean
3030
}
3131

3232
@Override
33-
public Call<ProjectConfig> getConfig(String sdkToken, String etag) {
33+
public Call<ProjectConfig> getConfig(String sdkToken, String etag, String lastModified) {
3434
// TODO Auto-generated method stub
3535
return null;
3636
}

0 commit comments

Comments
 (0)