-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from OpenConext/develop
Prepare release 2.2.0
- Loading branch information
Showing
15 changed files
with
403 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/service/CacheHashService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package nl.kennisnet.services.web.service; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.core.ParameterizedTypeReference; | ||
import org.springframework.http.HttpEntity; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.HttpMethod; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.web.client.HttpStatusCodeException; | ||
import org.springframework.web.client.RestClientException; | ||
import org.springframework.web.client.RestTemplate; | ||
|
||
@Service | ||
public class CacheHashService { | ||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(CacheHashService.class); | ||
|
||
@Value("${api.key.header.key}") | ||
private String API_KEY_HEADER; | ||
|
||
@Value("${api.key.header.value}") | ||
private String apiKeyHeaderValue; | ||
|
||
@Value("${api.endpoint.url.cacheHash:#{null}}") | ||
private String url; | ||
|
||
private final RestTemplate restTemplate; | ||
|
||
public CacheHashService(RestTemplate restTemplate) { | ||
this.restTemplate = restTemplate; | ||
} | ||
|
||
public String fetchCacheHash() { | ||
if (null == url) { | ||
LOGGER.info("Cache hash endpoint not set, returning empty hash"); | ||
return ""; | ||
} | ||
|
||
HttpHeaders requestHeaders = new HttpHeaders(); | ||
requestHeaders.add(API_KEY_HEADER, apiKeyHeaderValue); | ||
|
||
HttpEntity<?> httpEntity = new HttpEntity<>(requestHeaders); | ||
|
||
try { | ||
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, httpEntity, | ||
new ParameterizedTypeReference<>() {}); | ||
|
||
String result = response.getBody(); | ||
if (null == result) { | ||
LOGGER.warn("Received null from data-services cache-hash, returning empty hash"); | ||
return ""; | ||
} | ||
|
||
return result; | ||
} catch (HttpStatusCodeException htsce) { | ||
LOGGER.error("Unexpected response received, returning empty hash. Error message: {}", htsce.getMessage()); | ||
return ""; | ||
} catch (RestClientException rce) { | ||
LOGGER.error("Communication error occurred, returning empty hash. Error message: {} ", rce.getMessage()); | ||
return ""; | ||
} | ||
} | ||
|
||
} |
75 changes: 75 additions & 0 deletions
75
...icatie/src/main/java/nl/kennisnet/services/web/service/jobs/DataServicesUpdateRunner.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package nl.kennisnet.services.web.service.jobs; | ||
|
||
import nl.kennisnet.services.web.config.CacheConfig; | ||
import nl.kennisnet.services.web.service.CacheHashService; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.scheduling.annotation.Scheduled; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.util.concurrent.locks.Lock; | ||
import java.util.concurrent.locks.ReentrantLock; | ||
|
||
@Component | ||
public class DataServicesUpdateRunner implements Runnable { | ||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(DataServicesUpdateRunner.class); | ||
|
||
private static final String ALREADY_RUNNING = "DataServicesUpdateRunner is already running"; | ||
|
||
private static final String UPDATE_FAILED = "Cache evicts failed: {}"; | ||
|
||
private static final String UPDATE_FINISHED = "Cache evicts finished"; | ||
|
||
private static final Lock execLock = new ReentrantLock(); | ||
|
||
private static boolean running = false; | ||
|
||
private static String lastDataServicesCacheHash = ""; | ||
|
||
private final CacheHashService cacheHashService; | ||
|
||
private final CacheConfig cacheConfig; | ||
|
||
public DataServicesUpdateRunner(CacheHashService cacheHashService, CacheConfig cacheConfig) { | ||
this.cacheHashService = cacheHashService; | ||
this.cacheConfig = cacheConfig; | ||
} | ||
|
||
@Override | ||
@Scheduled(cron = "${dataservices.fetchCacheHash.cronSchedule:-}") | ||
public void run() { | ||
if (running || !execLock.tryLock()) { | ||
LOGGER.warn(ALREADY_RUNNING); | ||
return; | ||
} | ||
|
||
// Set the lock and execute the reaper | ||
running = true; | ||
// General exception to ensure that we do not create a deadlock for the scheduled runner | ||
try { | ||
execute(); | ||
} catch (Error | Exception e) { | ||
LOGGER.error(UPDATE_FAILED, e.getMessage()); | ||
} | ||
|
||
// Release the lock | ||
running = false; | ||
execLock.unlock(); | ||
} | ||
|
||
private void execute() { | ||
String dataServicesCacheHash = cacheHashService.fetchCacheHash(); | ||
if (dataServicesCacheHash.equals(lastDataServicesCacheHash) | ||
|| (!lastDataServicesCacheHash.isEmpty() && dataServicesCacheHash.isEmpty())) { | ||
return; | ||
} | ||
|
||
LOGGER.info("Changes since last update detected, evicting caches"); | ||
cacheConfig.cacheEvict(); | ||
lastDataServicesCacheHash = dataServicesCacheHash; | ||
|
||
LOGGER.info(UPDATE_FINISHED); | ||
} | ||
|
||
} |
89 changes: 89 additions & 0 deletions
89
oc-sso-notificatie/src/test/java/nl/kennisnet/services/web/CacheHashServiceTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package nl.kennisnet.services.web; | ||
|
||
import nl.kennisnet.services.web.service.CacheHashService; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
import org.mockito.InjectMocks; | ||
import org.mockito.Mock; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
import org.springframework.core.ParameterizedTypeReference; | ||
import org.springframework.http.HttpEntity; | ||
import org.springframework.http.HttpMethod; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.test.util.ReflectionTestUtils; | ||
import org.springframework.web.client.HttpClientErrorException; | ||
import org.springframework.web.client.RestClientException; | ||
import org.springframework.web.client.RestTemplate; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.mockito.Mockito.*; | ||
|
||
@SpringBootTest | ||
public class CacheHashServiceTest { | ||
|
||
@Mock | ||
RestTemplate restTemplate; | ||
|
||
@InjectMocks | ||
CacheHashService cacheHashService; | ||
|
||
@BeforeEach | ||
void setUp() { | ||
ReflectionTestUtils.setField(cacheHashService, "url", "sso-notification-url"); | ||
ReflectionTestUtils.setField(cacheHashService, "API_KEY_HEADER", "api-key"); | ||
} | ||
|
||
@Test | ||
void fetchCacheHashTest() { | ||
when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), | ||
any(ParameterizedTypeReference.class))).thenReturn(new ResponseEntity<>("HASH", HttpStatus.OK)); | ||
|
||
String result = cacheHashService.fetchCacheHash(); | ||
|
||
assertEquals("HASH", result); | ||
} | ||
|
||
@Test | ||
void fetchCacheNullReturnTest() { | ||
when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), | ||
any(ParameterizedTypeReference.class))).thenReturn(new ResponseEntity<>(null, HttpStatus.OK)); | ||
|
||
String result = cacheHashService.fetchCacheHash(); | ||
|
||
assertEquals("", result); | ||
} | ||
|
||
@Test | ||
void fetchCacheNullUrlTest() { | ||
ReflectionTestUtils.setField(cacheHashService, "url", null); | ||
|
||
when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), | ||
any(ParameterizedTypeReference.class))).thenReturn(new ResponseEntity<>(null, HttpStatus.OK)); | ||
|
||
String result = cacheHashService.fetchCacheHash(); | ||
|
||
assertEquals("", result); | ||
} | ||
|
||
@Test | ||
void fetchCacheHashHttpExceptionTest() { | ||
when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), | ||
any(ParameterizedTypeReference.class))).thenThrow(new HttpClientErrorException(HttpStatus.FORBIDDEN)); | ||
|
||
String result = cacheHashService.fetchCacheHash(); | ||
|
||
assertEquals("", result); | ||
} | ||
|
||
@Test | ||
void fetchCacheRestClientExceptionTest() { | ||
when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), | ||
any(ParameterizedTypeReference.class))).thenThrow(new RestClientException("ERROR")); | ||
|
||
String result = cacheHashService.fetchCacheHash(); | ||
|
||
assertEquals("", result); | ||
} | ||
|
||
} |
74 changes: 74 additions & 0 deletions
74
...otificatie/src/test/java/nl/kennisnet/services/web/jobs/DataServicesUpdateRunnerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package nl.kennisnet.services.web.jobs; | ||
|
||
import nl.kennisnet.services.web.config.CacheConfig; | ||
import nl.kennisnet.services.web.service.CacheHashService; | ||
import nl.kennisnet.services.web.service.jobs.DataServicesUpdateRunner; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
import org.mockito.InjectMocks; | ||
import org.mockito.Mock; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
import org.springframework.test.util.ReflectionTestUtils; | ||
|
||
import static org.mockito.Mockito.*; | ||
|
||
@SpringBootTest | ||
public class DataServicesUpdateRunnerTest { | ||
|
||
@Mock | ||
CacheHashService cacheHashService; | ||
|
||
@Mock | ||
CacheConfig cacheConfig; | ||
|
||
@InjectMocks | ||
DataServicesUpdateRunner dataServicesUpdateRunner; | ||
|
||
@BeforeEach | ||
void setup() { | ||
ReflectionTestUtils.setField(dataServicesUpdateRunner, "lastDataServicesCacheHash", "HASH"); | ||
} | ||
|
||
@Test | ||
void runTest() { | ||
ReflectionTestUtils.setField(dataServicesUpdateRunner, "running", false); | ||
|
||
when(cacheHashService.fetchCacheHash()).thenReturn("NEW_HASH"); | ||
|
||
dataServicesUpdateRunner.run(); | ||
|
||
verify(cacheConfig, times(1)).cacheEvict(); | ||
} | ||
|
||
@Test | ||
void runSameHashTest() { | ||
ReflectionTestUtils.setField(dataServicesUpdateRunner, "running", false); | ||
|
||
when(cacheHashService.fetchCacheHash()).thenReturn("HASH"); | ||
|
||
dataServicesUpdateRunner.run(); | ||
|
||
verify(cacheConfig, times(0)).cacheEvict(); | ||
} | ||
|
||
@Test | ||
void runEmptyHashTest() { | ||
ReflectionTestUtils.setField(dataServicesUpdateRunner, "running", false); | ||
|
||
when(cacheHashService.fetchCacheHash()).thenReturn(""); | ||
|
||
dataServicesUpdateRunner.run(); | ||
|
||
verify(cacheConfig, times(0)).cacheEvict(); | ||
} | ||
|
||
@Test | ||
void canNotRunDouble() { | ||
ReflectionTestUtils.setField(dataServicesUpdateRunner, "running", true); | ||
|
||
dataServicesUpdateRunner.run(); | ||
|
||
verify(cacheConfig, times(0)).cacheEvict(); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.