Skip to content

Commit

Permalink
Merge ac0cb08 into cf21771
Browse files Browse the repository at this point in the history
  • Loading branch information
allanmckenzie authored Nov 4, 2020
2 parents cf21771 + ac0cb08 commit 94a52ba
Show file tree
Hide file tree
Showing 9 changed files with 303 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,29 @@
import uk.gov.justice.services.core.featurecontrol.domain.Feature;
import uk.gov.justice.services.core.featurecontrol.local.LocalFeatureStore;
import uk.gov.justice.services.core.featurecontrol.lookup.FeatureStore;
import uk.gov.justice.services.core.featurecontrol.remote.FeatureStoreTimerBean;

import java.util.Optional;

import javax.inject.Inject;

public class DefaultFeatureStore implements FeatureStore {
public class FeatureStoreFacade implements FeatureStore {

@Inject
private LocalFeatureStore localFeatureStore;

@Inject
private FeatureStoreTimerBean featureStoreTimerBean;

@Override
public Optional<Feature> lookup(final String featureName) {
return localFeatureStore.lookup(featureName);

final Optional<Feature> feature = localFeatureStore.lookup(featureName);;

if (feature.isPresent()) {
return feature;
}

return featureStoreTimerBean.lookup(featureName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package uk.gov.justice.services.core.featurecontrol.remote;

import static java.lang.Boolean.parseBoolean;
import static java.lang.Long.parseLong;

import uk.gov.justice.services.common.configuration.GlobalValue;

import javax.inject.Inject;

public class FeatureRefreshTimerConfig {

private final String TEN_MINUTES_IN_MILLISECONDS = 10 * 60 * 1000 + "";

@Inject
@GlobalValue(key = "feature-refresh-rate.timer.start.wait.milliseconds", defaultValue = "0")
private String timerStartWaitMilliseconds;

@Inject
@GlobalValue(key = "feature-refresh-rate.timer.interval.milliseconds", defaultValue = TEN_MINUTES_IN_MILLISECONDS)
private String timerIntervalMilliseconds;

public long getTimerStartWaitMilliseconds() {
return parseLong(timerStartWaitMilliseconds);
}

public long getTimerIntervalMilliseconds() {
return parseLong(timerIntervalMilliseconds);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package uk.gov.justice.services.core.featurecontrol.remote;

import static java.util.Optional.ofNullable;

import uk.gov.justice.services.core.featurecontrol.FeatureFetcher;
import uk.gov.justice.services.core.featurecontrol.domain.Feature;
import uk.gov.justice.services.ejb.timer.TimerServiceManager;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.Timeout;
import javax.ejb.TimerService;
import javax.inject.Inject;

@Singleton
@Startup
public class FeatureStoreTimerBean {

private static final String TIMER_JOB_NAME = "framework.feature-store-refresh.job";

private AtomicReference<Map<String, Feature>> atomicFeatureMapReference = new AtomicReference<>(new HashMap<>());

@Inject
private FeatureFetcher featureFetcher;

@Inject
private TimerServiceManager timerServiceManager;

@Resource
private TimerService timerService;

@Inject
private FeatureRefreshTimerConfig featureRefreshTimerConfig;

@PostConstruct
public void startTimerService() {

timerServiceManager.createIntervalTimer(
TIMER_JOB_NAME,
featureRefreshTimerConfig.getTimerStartWaitMilliseconds(),
featureRefreshTimerConfig.getTimerIntervalMilliseconds(),
timerService);
}

@Timeout
public void reloadFeatures() {

final Map<String, Feature> featureMap = new HashMap<>();

featureFetcher
.fetchFeatures()
.forEach(feature -> featureMap.put(feature.getFeatureName(), feature));

atomicFeatureMapReference.set(featureMap);
}

public Optional<Feature> lookup(final String featureName) {
return ofNullable(atomicFeatureMapReference.get().get(featureName));
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package uk.gov.justice.services.core.featurecontrol;

import static java.util.Optional.empty;
import static java.util.Optional.of;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

import uk.gov.justice.services.core.featurecontrol.domain.Feature;
import uk.gov.justice.services.core.featurecontrol.local.LocalFeatureStore;
import uk.gov.justice.services.core.featurecontrol.remote.FeatureStoreTimerBean;

import java.util.Optional;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class FeatureStoreFacadeTest {

@Mock
private LocalFeatureStore localFeatureStore;

@Mock
private FeatureStoreTimerBean featureStoreTimerBean;

@InjectMocks
private FeatureStoreFacade featureStoreFacade;

@Test
public void shouldLookupFeaturesInTheFeatureStoreTimerBean() throws Exception {

final String featureName = "some-feature";

final Feature feature = mock(Feature.class);

when(localFeatureStore.lookup(featureName)).thenReturn(empty());
when(featureStoreTimerBean.lookup(featureName)).thenReturn(of(feature));

assertThat(featureStoreFacade.lookup(featureName), is(of(feature)));
}

@Test
public void shouldReturnEmptyIfTheFeatureCannotBeFound() throws Exception {

final String unknownFeatureName = "some-unknown-feature";

when(localFeatureStore.lookup(unknownFeatureName)).thenReturn(empty());
when(featureStoreTimerBean.lookup(unknownFeatureName)).thenReturn(empty());

assertThat(featureStoreFacade.lookup(unknownFeatureName).isPresent(), is(false));
}

@Test
public void shouldOverrideTheFeatureWithALocalOneIfFound() throws Exception {

final String featureName = "some-feature";

final Feature feature = mock(Feature.class);

when(localFeatureStore.lookup(featureName)).thenReturn(of(feature));

assertThat(featureStoreFacade.lookup(featureName), is(of(feature)));

verifyZeroInteractions(featureStoreTimerBean);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package uk.gov.justice.services.core.featurecontrol.remote;

import org.junit.runner.RunWith;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.verify;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package uk.gov.justice.services.core.featurecontrol.remote;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static uk.gov.justice.services.test.utils.core.reflection.ReflectionUtil.setField;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class FeatureRefreshTimerConfigTest {

@InjectMocks
private FeatureRefreshTimerConfig featureRefreshTimerConfig;

@Test
public void shouldGetTheFeatureRefreshTimerStartWaitInMilliseconds() throws Exception {

final long timerStartWait = 98234L;

setField(featureRefreshTimerConfig, "timerStartWaitMilliseconds", timerStartWait + "");

assertThat(featureRefreshTimerConfig.getTimerStartWaitMilliseconds(), is(timerStartWait));
}

@Test
public void shouldGetTheFeatureRefreshTimerIntervalInMilliseconds() throws Exception {

final long timerInterval = 98234L;

setField(featureRefreshTimerConfig, "timerIntervalMilliseconds", timerInterval + "");

assertThat(featureRefreshTimerConfig.getTimerIntervalMilliseconds(), is(timerInterval));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package uk.gov.justice.services.core.featurecontrol.remote;

import static java.util.Arrays.asList;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import uk.gov.justice.services.core.featurecontrol.FeatureFetcher;
import uk.gov.justice.services.core.featurecontrol.domain.Feature;
import uk.gov.justice.services.ejb.timer.TimerServiceManager;

import javax.ejb.TimerService;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;


@RunWith(MockitoJUnitRunner.class)
public class FeatureStoreTimerBeanTest {

@Mock
private FeatureFetcher featureFetcher;

@Mock
private TimerServiceManager timerServiceManager;

@Mock
private TimerService timerService;

@Mock
private FeatureRefreshTimerConfig featureRefreshTimerConfig;

@InjectMocks
private FeatureStoreTimerBean featureStoreTimerBean;

@Test
public void shouldStartTheTimerServiceOnStartup() throws Exception {

final long timerStartWaitMilliseconds = 934L;
final long timerIntervalMilliseconds = 987234L;

when(featureRefreshTimerConfig.getTimerStartWaitMilliseconds()).thenReturn(timerStartWaitMilliseconds);
when(featureRefreshTimerConfig.getTimerIntervalMilliseconds()).thenReturn(timerIntervalMilliseconds);

featureStoreTimerBean.startTimerService();

verify(timerServiceManager).createIntervalTimer(
"framework.feature-store-refresh.job",
timerStartWaitMilliseconds,
timerIntervalMilliseconds,
timerService);
}

@Test
public void shouldFetchFeaturesAndStore() throws Exception {

final Feature feature_1 = new Feature("some-feature-1", "some-description-1", true);
final Feature feature_2 = new Feature("some-feature-2", "some-description-2", true);
final Feature feature_3 = new Feature("some-feature-3", "some-description-3", true);

assertThat(featureStoreTimerBean.lookup(feature_1.getFeatureName()).isPresent(), is(false));
assertThat(featureStoreTimerBean.lookup(feature_2.getFeatureName()).isPresent(), is(false));
assertThat(featureStoreTimerBean.lookup(feature_3.getFeatureName()).isPresent(), is(false));

when(featureFetcher.fetchFeatures()).thenReturn(asList(feature_1, feature_2, feature_3));
featureStoreTimerBean.reloadFeatures();

final Feature foundFeature_1 = featureStoreTimerBean.lookup(feature_1.getFeatureName())
.orElseThrow(AssertionError::new);
final Feature foundFeature_2 = featureStoreTimerBean.lookup(feature_2.getFeatureName())
.orElseThrow(AssertionError::new);
final Feature foundFeature_3 = featureStoreTimerBean.lookup(feature_3.getFeatureName())
.orElseThrow(AssertionError::new);

assertThat(foundFeature_1, is(feature_1));
assertThat(foundFeature_2, is(feature_2));
assertThat(foundFeature_3, is(feature_3));
}
}
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@

<properties>
<cpp.repo.name>microservice_framework</cpp.repo.name>
<framework-libraries.version>7.2.0-M2</framework-libraries.version>
<framework-libraries.version>7.2.0-M3</framework-libraries.version>
</properties>

<dependencyManagement>
Expand Down

0 comments on commit 94a52ba

Please sign in to comment.