Skip to content

Commit

Permalink
Merge pull request #69 from europeana/EA-3969-track-cache-usage
Browse files Browse the repository at this point in the history
track cache usage
  • Loading branch information
gsergiu authored Dec 16, 2024
2 parents 1cca450 + b666698 commit f5e8368
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 38 deletions.
3 changes: 3 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@
<aggregate.report.xml>translation-tests/target/site/jacoco-aggregate/jacoco.xml</aggregate.report.xml>
<sonar.coverage.jacoco.xmlReportPaths>${aggregate.report.xml}</sonar.coverage.jacoco.xmlReportPaths>

<!-- test dependencies -->
<version.testcontainers>1.19.7</version.testcontainers>

</properties>

<dependencyManagement>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package eu.europeana.api.translation.definitions.model;

/**
* The class for storing the translation and caching statistics
*/
public class TranslationCachingStats {

private int numLinesCached;
private int numCharsCached;
private int numLinesToBeTranslated;
private int numCharsToBeTranslated;

public int getNumLinesCached() {
return numLinesCached;
}
public void setNumLinesCached(int numLinesCached) {
this.numLinesCached = numLinesCached;
}
public int getNumCharsCached() {
return numCharsCached;
}
public void setNumCharsCached(int numCharsCached) {
this.numCharsCached = numCharsCached;
}
public int getNumLinesToBeTranslated() {
return numLinesToBeTranslated;
}
public void setNumLinesToBeTranslated(int numLinesToBeTranslated) {
this.numLinesToBeTranslated = numLinesToBeTranslated;
}
public int getNumCharsToBeTranslated() {
return numCharsToBeTranslated;
}
public void setNumCharsToBeTranslated(int numCharsToBeTranslated) {
this.numCharsToBeTranslated = numCharsToBeTranslated;
}

}
12 changes: 12 additions & 0 deletions translation-tests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@
</exclusions>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>${version.testcontainers}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.DockerImageName;
import eu.europeana.api.translation.TranslationApp;
import eu.europeana.api.translation.config.TranslationServiceProvider;
import eu.europeana.api.translation.service.etranslation.ETranslationTranslationService;
Expand All @@ -39,7 +41,7 @@
public abstract class BaseTranslationTest extends IntegrationTestUtils {

protected MockMvc mockMvc;
protected final static int redisPort=6370;

protected static final Logger LOG = LogManager.getLogger(BaseTranslationTest.class);

@Autowired
Expand All @@ -51,6 +53,17 @@ public abstract class BaseTranslationTest extends IntegrationTestUtils {
/** Maps Metis dereferenciation URIs to mocked XML responses */
public static final Map<String, String> LANG_DETECT_RESPONSE_MAP = initLanguageDetectMap();
public static final Map<String, String> TRANSLATION_RESPONSE_MAP = initTranslationMap();

//start redis test container
protected final static int redisContainerPort=6379;
private static GenericContainer<?> redis_container = startRedisTestContainer();
private static GenericContainer<?> startRedisTestContainer() {
@SuppressWarnings("resource")
GenericContainer<?> redis =
new GenericContainer<>(DockerImageName.parse("redis:5.0.3-alpine")).withExposedPorts(redisContainerPort);
redis.start();
return redis;
}

/** MockWebServer needs to be static, so we can inject its port into the Spring context. */
private static MockWebServer mockPangeanic = startPangeanicMockServer();
Expand Down Expand Up @@ -130,7 +143,7 @@ static void setProperties(DynamicPropertyRegistry registry) {

registry.add("translation.google.projectId", () -> "project-id-test");
registry.add("translation.google.usehttpclient", () -> "true");
registry.add("redis.connection.url", () -> "redis://localhost:" + redisPort + "/");
registry.add("redis.connection.url", () -> "redis://"+ redis_container.getHost() + ":" + redis_container.getMappedPort(redisContainerPort).toString() + "/");
registry.add("translation.eTranslation.baseUrl", () -> ETranslationTranslationService.FAKE_BASE_URL_FOR_TESTING);
registry.add("translation.eTranslation.credentials", () -> "");
registry.add("translation.eTranslation.truncate", () -> false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import java.util.List;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
Expand All @@ -37,7 +36,6 @@
import eu.europeana.api.translation.tests.web.mock.MockGClient;
import eu.europeana.api.translation.tests.web.mock.MockGServiceStub;
import eu.europeana.api.translation.web.service.RedisCacheService;
import redis.embedded.RedisServer;

@SpringBootTest
@AutoConfigureMockMvc
Expand All @@ -49,9 +47,7 @@ public class TranslationRestIT extends BaseTranslationTest {

@Autowired
RedisCacheService redisCacheService;

private static RedisServer redisServer = startRedisService();


public static final String LANGUAGE_EN = "en";


Expand All @@ -65,21 +61,7 @@ void startMockServers() throws IOException {
clientWrapper.setClient(googleClient);
googleTranslationService.init(clientWrapper);
}

static RedisServer startRedisService() {
//start redis server
RedisServer redisServer = new RedisServer(redisPort);
redisServer.start();
return redisServer;
}

@AfterAll void stopRedis() {
if(redisServer != null) {
redisServer.stop();
}
}



@Test
void translationGoogle() throws Exception {
String requestJson = getJsonStringInput(TRANSLATION_REQUEST);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

import java.util.List;
import javax.validation.constraints.NotNull;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import eu.europeana.api.translation.definitions.model.TranslationCachingStats;
import eu.europeana.api.translation.definitions.model.TranslationObj;
import eu.europeana.api.translation.service.AbstractTranslationService;
import eu.europeana.api.translation.service.TranslationService;
import eu.europeana.api.translation.service.exception.TranslationException;

public class CachedTranslationService extends AbstractTranslationService {
private final Logger logger = LogManager.getLogger(CachedTranslationService.class);
private final RedisCacheService redisCacheService;
private final TranslationService translationService;

Expand Down Expand Up @@ -36,33 +40,59 @@ public boolean isSupported(String srcLang, String trgLang) {
return true;
}

private TranslationCachingStats computeTranslationCachingStats(List<TranslationObj> allTranslObjs) {
int numLinesCached=0;
int numCharsCached=0;
int numLinesToBeTranslated=0;
int numCharsToBeTranslated=0;
for(TranslationObj translObj : allTranslObjs) {
if(translObj.isRetrievedFromCache()) {
numLinesCached += 1;
numCharsCached += translObj.getTranslation().length();
}
if(translObj.getTranslation() == null) {
//objects sent for translation
numLinesToBeTranslated += 1;
numCharsToBeTranslated += translObj.getText().length();
}
}

TranslationCachingStats stats = new TranslationCachingStats();
stats.setNumLinesCached(numLinesCached);
stats.setNumCharsCached(numCharsCached);
stats.setNumLinesToBeTranslated(numLinesToBeTranslated);
stats.setNumCharsToBeTranslated(numCharsToBeTranslated);
return stats;
}

@Override
public void translate(List<TranslationObj> translationObjs) throws TranslationException {
//fill the non translatable texts, e.g. empty Strings
processNonTranslatable(translationObjs);


fillTranslationForSameLanguage(translationObjs);

processNonTranslatable(translationObjs);

if(isCachingEnabled()) {
redisCacheService.fillWithCachedTranslations(translationObjs);
}

List<TranslationObj> toTranslate = translationObjs.stream().filter(
t -> t.getTranslation() == null).toList();

if(toTranslate.isEmpty()) {
//all entries retrieved from cache, processing complete
return;
//logging the number of translated/cached lines and chars
if(logger.isInfoEnabled()) {
TranslationCachingStats stats = computeTranslationCachingStats(translationObjs);
logger.info("Tracking cache usage: numLinesCached={}, numCharsCached={}, numLinesToBeTranslated={}, "
+ "numCharsToBeTranslated={}", stats.getNumLinesCached(), stats.getNumCharsCached(),
stats.getNumLinesToBeTranslated(), stats.getNumCharsToBeTranslated());
}

translationService.translate(toTranslate);

if(isCachingEnabled()) {
//save result in the redis cache
redisCacheService.store(toTranslate);
List<TranslationObj> toTranslate = translationObjs.stream().filter(
t -> t.getTranslation() == null).toList();

if(!toTranslate.isEmpty()) {
translationService.translate(toTranslate);
if(isCachingEnabled()) {
//save result in the redis cache
redisCacheService.store(toTranslate);
}
}

}


Expand Down

0 comments on commit f5e8368

Please sign in to comment.