Skip to content

Commit

Permalink
Renamed cache-experation to refresh-interval for clarification of the…
Browse files Browse the repository at this point in the history
… feature. Moved Feature Flag refresh interval to under monitor (#22296)
  • Loading branch information
mrm9084 authored Jun 16, 2021
1 parent 79a063d commit 1a92fbe
Show file tree
Hide file tree
Showing 13 changed files with 73 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public AppConfigurationBusRefreshEventListener(AppConfigurationRefresh appConfig
@Override
public void onApplicationEvent(AppConfigurationBusRefreshEvent event) {
try {
appConfigurationRefresh.resetCache(event.getEndpoint());
appConfigurationRefresh.expireRefreshInterval(event.getEndpoint());
} catch (Exception e) {
LOGGER.error("Refresh failed with unexpected exception.", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public AppConfigurationRefreshEventListener(AppConfigurationRefresh appConfigura
@Override
public void onApplicationEvent(AppConfigurationRefreshEvent event) {
try {
appConfigurationRefresh.resetCache(event.getEndpoint());
appConfigurationRefresh.expireRefreshInterval(event.getEndpoint());
} catch (Exception e) {
LOGGER.error("Refresh failed with unexpected exception.", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,11 @@ private List<AppConfigurationPropertySource> create(String context, ConfigStore
watchKey.setKey(store.getFeatureFlags().getKeyFilter());
watchKeysFeatures.add(watchKey);
StateHolder.setStateFeatureFlag(store.getEndpoint(), watchKeysFeatures,
store.getFeatureFlags().getCacheExpiration());
store.getMonitoring().getFeatureFlagRefreshInterval());
StateHolder.setLoadStateFeatureFlag(store.getEndpoint(), true);
}

StateHolder.setState(store.getEndpoint(), watchKeysSettings, store.getMonitoring().getCacheExpiration());
StateHolder.setState(store.getEndpoint(), watchKeysSettings, store.getMonitoring().getRefreshInterval());
StateHolder.setLoadState(store.getEndpoint(), true);
} catch (RuntimeException e) {
delayException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public void setApplicationEventPublisher(ApplicationEventPublisher applicationEv
}

/**
* Checks configurations to see if they are no longer cached. If they are no longer cached they are updated.
* Checks configurations to see if configurations should be reloaded. If the refresh interval has passed and a trigger has been updated configuration are reloaded.
*
* @return Future with a boolean of if a RefreshEvent was published. If refreshConfigurations is currently being run
* elsewhere this method will return right away as <b>false</b>.
Expand All @@ -64,10 +64,10 @@ public Future<Boolean> refreshConfigurations() {
return new AsyncResult<>(refreshStores());
}

public void resetCache(String endpoint) {
public void expireRefreshInterval(String endpoint) {
for (ConfigStore configStore : configStores) {
if (configStore.getEndpoint().equals(endpoint)) {
LOGGER.debug("Expiring Cache for " + configStore.getEndpoint());
LOGGER.debug("Expiring refresh interval for " + configStore.getEndpoint());
StateHolder.expireState(configStore.getEndpoint());
break;
}
Expand All @@ -90,7 +90,7 @@ private boolean refreshStores() {
AppConfigurationStoreMonitoring monitor = configStore.getMonitoring();

if (StateHolder.getLoadState(endpoint) && monitor.isEnabled()
&& refresh(StateHolder.getState(endpoint), endpoint, monitor.getCacheExpiration())) {
&& refresh(StateHolder.getState(endpoint), endpoint, monitor.getRefreshInterval())) {
didRefresh = true;
break;
} else {
Expand All @@ -100,7 +100,7 @@ && refresh(StateHolder.getState(endpoint), endpoint, monitor.getCacheExpiration(
FeatureFlagStore featureStore = configStore.getFeatureFlags();

if (featureStore.getEnabled() && StateHolder.getLoadStateFeatureFlag(endpoint) && refresh(
StateHolder.getStateFeatureFlag(endpoint), endpoint, featureStore.getCacheExpiration())) {
StateHolder.getStateFeatureFlag(endpoint), endpoint, monitor.getFeatureFlagRefreshInterval())) {
didRefresh = true;
break;
} else {
Expand All @@ -117,16 +117,16 @@ && refresh(StateHolder.getState(endpoint), endpoint, monitor.getCacheExpiration(
}

/**
* Checks un-cached items for etag changes. If they have changed a RefreshEventData is published.
* Checks refresh trigger for etag changes. If they have changed a RefreshEventData is published.
*
* @param state The refresh state of the endpoint being checked.
* @param endpoint The App Config Endpoint being checked for refresh.
* @param cacheTime Amount of time to wait until next check of this endpoint.
* @param refreshInterval Amount of time to wait until next check of this endpoint.
* @return Refresh event was triggered. No other sources need to be checked.
*/
private boolean refresh(State state, String endpoint, Duration cacheTime) {
private boolean refresh(State state, String endpoint, Duration refreshInterval) {
Date date = new Date();
if (date.after(state.getNotCachedTime())) {
if (date.after(state.getNextRefreshCheck())) {
for (ConfigurationSetting watchKey : state.getWatchKeys()) {
SettingSelector settingSelector = new SettingSelector().setKeyFilter(watchKey.getKey())
.setLabelFilter(watchKey.getLabel());
Expand Down Expand Up @@ -158,7 +158,7 @@ private boolean refresh(State state, String endpoint, Duration cacheTime) {
return true;
}
}
StateHolder.setState(endpoint, state.getWatchKeys(), cacheTime);
StateHolder.setState(endpoint, state.getWatchKeys(), refreshInterval);
}

return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ class State {

private final List<ConfigurationSetting> watchKeys;

private final Date notCachedTime;
private final Date nextRefreshCheck;

State(List<ConfigurationSetting> watchKeys, int cacheExpirationTime) {
State(List<ConfigurationSetting> watchKeys, int refreshInterval) {
this.watchKeys = watchKeys;
notCachedTime = DateUtils.addSeconds(new Date(), cacheExpirationTime);
nextRefreshCheck = DateUtils.addSeconds(new Date(), refreshInterval);
}

/**
Expand All @@ -28,10 +28,10 @@ public List<ConfigurationSetting> getWatchKeys() {
}

/**
* @return the notCachedTime
* @return the nextRefreshCheck
*/
public Date getNotCachedTime() {
return notCachedTime;
public Date getNextRefreshCheck() {
return nextRefreshCheck;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ static void expireState(String endpoint) {
State oldState = STATE.get(key);
SecureRandom random = new SecureRandom();
long wait = (long) (random.nextDouble() * MAX_JITTER);
long timeLeft = (int) ((oldState.getNotCachedTime().getTime() - (new Date().getTime())) / 1000);
long timeLeft = (int) ((oldState.getNextRefreshCheck().getTime() - (new Date().getTime())) / 1000);
if (wait < timeLeft) {
STATE.put(key, new State(oldState.getWatchKeys(), (int) wait));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ public class AppConfigurationStoreMonitoring {

private boolean enabled = false;

private Duration cacheExpiration = Duration.ofSeconds(30);
private Duration refreshInterval = Duration.ofSeconds(30);

private Duration featureFlagRefreshInterval = Duration.ofSeconds(30);

private List<AppConfigurationStoreTrigger> triggers = new ArrayList<>();

Expand All @@ -38,19 +40,34 @@ public void setEnabled(boolean enabled) {
}

/**
* @return the cacheExpiration
* @return the refreshInterval
*/
public Duration getCacheExpiration() {
return cacheExpiration;
public Duration getRefreshInterval() {
return refreshInterval;
}

/**
* The minimum time between checks. The minimum valid cache time is 1s. The default cache time is 30s.
* The minimum time between checks. The minimum valid time is 1s. The default refresh interval is 30s.
*
* @param cacheExpiration minimum time between refresh checks
* @param refreshInterval minimum time between refresh checks
*/
public void setRefreshInterval(Duration refreshInterval) {
this.refreshInterval = refreshInterval;
}

/**
* @return the featureFlagRefreshInterval
*/
public Duration getFeatureFlagRefreshInterval() {
return featureFlagRefreshInterval;
}

/**
* The minimum time between checks of feature flags. The minimum valid time is 1s. The default refresh interval is 30s.
* @param featureFlagRefreshInterval minimum time between refresh checks for feature flags
*/
public void setCacheExpiration(Duration cacheExpiration) {
this.cacheExpiration = cacheExpiration;
public void setFeatureFlagRefreshInterval(Duration featureFlagRefreshInterval) {
this.featureFlagRefreshInterval = featureFlagRefreshInterval;
}

/**
Expand Down Expand Up @@ -89,7 +106,8 @@ public void validateAndInit() {
trigger.validateAndInit();
}
}
Assert.isTrue(cacheExpiration.getSeconds() >= 1, "Minimum Watch time is 1 Second.");
Assert.isTrue(refreshInterval.getSeconds() >= 1, "Minimum refresh interval time is 1 Second.");
Assert.isTrue(featureFlagRefreshInterval.getSeconds() >= 1, "Minimum Feature Flag refresh interval time is 1 Second.");
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// Licensed under the MIT License.
package com.azure.spring.cloud.config.properties;

import java.time.Duration;

/**
* Properties for what needs to be requested from Azure App Configuration for Feature Flags.
*/
Expand All @@ -17,8 +15,6 @@ public class FeatureFlagStore {

private String labelFilter = EMPTY_LABEL;

private Duration cacheExpiration = Duration.ofSeconds(30);

public Boolean getEnabled() {
return enabled;
}
Expand All @@ -39,12 +35,4 @@ public void setLabelFilter(String labelFilter) {
this.labelFilter = labelFilter;
}

public Duration getCacheExpiration() {
return cacheExpiration;
}

public void setCacheExpiration(Duration cacheExpiration) {
this.cacheExpiration = cacheExpiration;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Licensed under the MIT License.
package com.azure.spring.cloud.config;

import static com.azure.spring.cloud.config.TestConstants.CACHE_EXPIRATION_PROP;
import static com.azure.spring.cloud.config.TestConstants.REFRESH_INTERVAL_PROP;
import static com.azure.spring.cloud.config.TestConstants.CONN_STRING_PROP;
import static com.azure.spring.cloud.config.TestConstants.CONN_STRING_PROP_NEW;
import static com.azure.spring.cloud.config.TestConstants.DEFAULT_CONTEXT_PROP;
Expand Down Expand Up @@ -169,7 +169,7 @@ public void duplicateConnectionStringIsNotAllowed() {
public void minValidWatchTime() {
this.contextRunner
.withPropertyValues(propPair(CONN_STRING_PROP, TEST_CONN_STRING))
.withPropertyValues(propPair(CACHE_EXPIRATION_PROP, "1s"))
.withPropertyValues(propPair(REFRESH_INTERVAL_PROP, "1s"))
.run(context -> assertThat(context).hasSingleBean(AppConfigurationProperties.class));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public void setup() {
List<AppConfigurationStoreTrigger> triggers = new ArrayList<AppConfigurationStoreTrigger>();
triggers.add(trigger);
monitoring.setTriggers(triggers);
monitoring.setCacheExpiration(Duration.ofMinutes(-60));
monitoring.setRefreshInterval(Duration.ofMinutes(-60));
monitoring.setEnabled(true);
store.setMonitoring(monitoring);

Expand Down Expand Up @@ -100,14 +100,14 @@ public void setup() {

@After
public void cleanupMethod() {
StateHolder.setState(TEST_STORE_NAME, new ArrayList<ConfigurationSetting>(), monitoring.getCacheExpiration());
StateHolder.setState(TEST_STORE_NAME, new ArrayList<ConfigurationSetting>(), monitoring.getRefreshInterval());
}

@Test
public void nonUpdatedEtagShouldntPublishEvent() throws Exception {
List<ConfigurationSetting> watchKeys = new ArrayList<ConfigurationSetting>();
watchKeys.add(initialResponse());
StateHolder.setState(TEST_STORE_NAME, watchKeys, monitoring.getCacheExpiration());
StateHolder.setState(TEST_STORE_NAME, watchKeys, monitoring.getRefreshInterval());

configRefresh.setApplicationEventPublisher(eventPublisher);

Expand All @@ -121,7 +121,7 @@ public void nonUpdatedEtagShouldntPublishEvent() throws Exception {
public void updatedEtagShouldPublishEvent() throws Exception {
List<ConfigurationSetting> watchKeys = new ArrayList<ConfigurationSetting>();
watchKeys.add(initialResponse());
StateHolder.setState(TEST_STORE_NAME, watchKeys, monitoring.getCacheExpiration());
StateHolder.setState(TEST_STORE_NAME, watchKeys, monitoring.getRefreshInterval());

when(clientStoreMock.getWatchKey(Mockito.any(), Mockito.anyString())).thenReturn(initialResponse());
configRefresh.setApplicationEventPublisher(eventPublisher);
Expand All @@ -138,7 +138,7 @@ public void updatedEtagShouldPublishEvent() throws Exception {

watchKeys = new ArrayList<ConfigurationSetting>();
watchKeys.add(updatedResponse());
StateHolder.setState(TEST_STORE_NAME, watchKeys, monitoring.getCacheExpiration());
StateHolder.setState(TEST_STORE_NAME, watchKeys, monitoring.getRefreshInterval());

HashMap<String, String> map = new HashMap<String, String>();
map.put("store1_configuration", "fake-etag-updated");
Expand All @@ -148,7 +148,7 @@ public void updatedEtagShouldPublishEvent() throws Exception {
updated.setETag("fake-etag-updated");
watchKeys = new ArrayList<ConfigurationSetting>();
watchKeys.add(updated);
StateHolder.setState(TEST_STORE_NAME, watchKeys, monitoring.getCacheExpiration());
StateHolder.setState(TEST_STORE_NAME, watchKeys, monitoring.getRefreshInterval());

// If there is no change it shouldn't update
assertFalse(configRefresh.refreshConfigurations().get());
Expand All @@ -161,7 +161,7 @@ public void updatedFeatureFlagEtagShouldPublishEvent() throws Exception {
featureFlagStore.setEnabled(true);
List<ConfigurationSetting> watchKeys = new ArrayList<ConfigurationSetting>();
watchKeys.add(initialResponse());
StateHolder.setStateFeatureFlag(TEST_STORE_NAME, watchKeys, monitoring.getCacheExpiration());
StateHolder.setStateFeatureFlag(TEST_STORE_NAME, watchKeys, monitoring.getRefreshInterval());

when(clientStoreMock.getWatchKey(Mockito.any(), Mockito.anyString())).thenReturn(initialResponse());
configRefresh.setApplicationEventPublisher(eventPublisher);
Expand All @@ -178,7 +178,7 @@ public void updatedFeatureFlagEtagShouldPublishEvent() throws Exception {

watchKeys = new ArrayList<ConfigurationSetting>();
watchKeys.add(updatedResponse());
StateHolder.setStateFeatureFlag(TEST_STORE_NAME, watchKeys, monitoring.getCacheExpiration());
StateHolder.setStateFeatureFlag(TEST_STORE_NAME, watchKeys, monitoring.getRefreshInterval());

HashMap<String, String> map = new HashMap<String, String>();
map.put("store1_configuration", "fake-etag-updated");
Expand All @@ -188,7 +188,7 @@ public void updatedFeatureFlagEtagShouldPublishEvent() throws Exception {
updated.setETag("fake-etag-updated");
watchKeys = new ArrayList<ConfigurationSetting>();
watchKeys.add(updated);
StateHolder.setStateFeatureFlag(TEST_STORE_NAME, watchKeys, monitoring.getCacheExpiration());
StateHolder.setStateFeatureFlag(TEST_STORE_NAME, watchKeys, monitoring.getRefreshInterval());

// If there is no change it shouldn't update
assertFalse(configRefresh.refreshConfigurations().get());
Expand All @@ -199,7 +199,7 @@ public void updatedFeatureFlagEtagShouldPublishEvent() throws Exception {
public void noEtagReturned() throws Exception {
List<ConfigurationSetting> watchKeys = new ArrayList<ConfigurationSetting>();
watchKeys.add(initialResponse());
StateHolder.setState(TEST_STORE_NAME, watchKeys, monitoring.getCacheExpiration());
StateHolder.setState(TEST_STORE_NAME, watchKeys, monitoring.getRefreshInterval());

when(clientStoreMock.getWatchKey(Mockito.any(), Mockito.anyString()))
.thenReturn(null);
Expand All @@ -214,7 +214,7 @@ public void noEtagReturned() throws Exception {
public void nullItemsReturned() throws Exception {
List<ConfigurationSetting> watchKeys = new ArrayList<ConfigurationSetting>();
watchKeys.add(initialResponse());
StateHolder.setState(TEST_STORE_NAME, watchKeys, monitoring.getCacheExpiration());
StateHolder.setState(TEST_STORE_NAME, watchKeys, monitoring.getRefreshInterval());

when(clientStoreMock.getWatchKey(Mockito.any(), Mockito.anyString())).thenReturn(null);
configRefresh.setApplicationEventPublisher(eventPublisher);
Expand All @@ -238,7 +238,7 @@ public void noInitialStateNoEtag() throws Exception {
List<AppConfigurationStoreTrigger> triggers = new ArrayList<AppConfigurationStoreTrigger>();
triggers.add(trigger);
monitoring.setTriggers(triggers);
monitoring.setCacheExpiration(Duration.ofMinutes(-60));
monitoring.setRefreshInterval(Duration.ofMinutes(-60));
store.setMonitoring(monitoring);

AppConfigurationProperties propertiesLost = new AppConfigurationProperties();
Expand All @@ -259,7 +259,7 @@ public void noInitialStateNoEtag() throws Exception {
public void notRefreshTime() throws Exception {
List<ConfigurationSetting> watchKeys = new ArrayList<ConfigurationSetting>();
watchKeys.add(initialResponse());
StateHolder.setState(TEST_STORE_NAME, watchKeys, monitoring.getCacheExpiration());
StateHolder.setState(TEST_STORE_NAME, watchKeys, monitoring.getRefreshInterval());

ConfigStore store = new ConfigStore();
store.setEndpoint(TEST_STORE_NAME);
Expand All @@ -273,7 +273,7 @@ public void notRefreshTime() throws Exception {
List<AppConfigurationStoreTrigger> triggers = new ArrayList<AppConfigurationStoreTrigger>();
triggers.add(trigger);
monitoring.setTriggers(triggers);
monitoring.setCacheExpiration(Duration.ofMinutes(60));
monitoring.setRefreshInterval(Duration.ofMinutes(60));
store.setMonitoring(monitoring);

AppConfigurationProperties properties = new AppConfigurationProperties();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public void expireState() {
List<ConfigurationSetting> watchKeys = new ArrayList<ConfigurationSetting>();

AppConfigurationStoreMonitoring monitoring = new AppConfigurationStoreMonitoring();
StateHolder.setState(endpoint, watchKeys, monitoring.getCacheExpiration());
StateHolder.setState(endpoint, watchKeys, monitoring.getRefreshInterval());
State state = StateHolder.getState(endpoint);
StateHolder.expireState(endpoint);
State currentState = StateHolder.getState(endpoint);
Expand All @@ -36,8 +36,8 @@ public void notExpireState() {
List<ConfigurationSetting> watchKeys = new ArrayList<ConfigurationSetting>();

AppConfigurationStoreMonitoring monitoring = new AppConfigurationStoreMonitoring();
monitoring.setCacheExpiration(Duration.ofSeconds(-30));
StateHolder.setState(endpoint, watchKeys, monitoring.getCacheExpiration());
monitoring.setRefreshInterval(Duration.ofSeconds(-30));
StateHolder.setState(endpoint, watchKeys, monitoring.getRefreshInterval());
State state = StateHolder.getState(endpoint);
StateHolder.expireState(endpoint);
State currentState = StateHolder.getState(endpoint);
Expand Down
Loading

0 comments on commit 1a92fbe

Please sign in to comment.