Skip to content
Snippets Groups Projects
Commit 1e549469 authored by Riabokon Stanislav(EPAM)[GCP]'s avatar Riabokon Stanislav(EPAM)[GCP]
Browse files

Add cache to fetch Legal_COO.json from blob storage (GONRG-10325)

parent 68188f0a
No related branches found
No related tags found
1 merge request!632Add cache to fetch Legal_COO.json from blob storage (GONRG-10325)
/* /*
* Copyright 2020-2023 Google LLC * Copyright 2020-2024 Google LLC
* Copyright 2020-2023 EPAM Systems, Inc * Copyright 2020-2024 EPAM Systems, Inc
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
package org.opengroup.osdu.legal.config; package org.opengroup.osdu.legal.config;
import lombok.RequiredArgsConstructor;
import org.opengroup.osdu.core.common.cache.ICache; import org.opengroup.osdu.core.common.cache.ICache;
import org.opengroup.osdu.core.common.cache.VmCache; import org.opengroup.osdu.core.common.cache.VmCache;
import org.opengroup.osdu.core.common.partition.PartitionInfo; import org.opengroup.osdu.core.common.partition.PartitionInfo;
...@@ -25,8 +24,7 @@ import org.springframework.context.annotation.Bean; ...@@ -25,8 +24,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@Configuration @Configuration
@RequiredArgsConstructor public class CorePlusCacheConfig {
public class CacheConfig {
@Bean @Bean
public ICache<String, PartitionInfo> partitionInfoCache() { public ICache<String, PartitionInfo> partitionInfoCache() {
......
/* /*
* Copyright 2020-2023 Google LLC * Copyright 2020-2024 Google LLC
* Copyright 2020-2023 EPAM Systems, Inc * Copyright 2020-2024 EPAM Systems, Inc
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
package org.opengroup.osdu.legal.countries; package org.opengroup.osdu.legal.countries;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.opengroup.osdu.core.common.cache.ICache;
import org.opengroup.osdu.core.common.model.tenant.TenantInfo; import org.opengroup.osdu.core.common.model.tenant.TenantInfo;
import org.opengroup.osdu.core.common.partition.PartitionPropertyResolver; import org.opengroup.osdu.core.common.partition.PartitionPropertyResolver;
import org.opengroup.osdu.core.obm.core.Driver; import org.opengroup.osdu.core.obm.core.Driver;
...@@ -30,14 +31,13 @@ import org.springframework.stereotype.Component; ...@@ -30,14 +31,13 @@ import org.springframework.stereotype.Component;
public class StorageReaderFactoryImpl implements IStorageReaderFactory { public class StorageReaderFactoryImpl implements IStorageReaderFactory {
private final Driver storage; private final Driver storage;
private final PartitionPropertyResolver partitionPropertyResolver; private final PartitionPropertyResolver partitionPropertyResolver;
private final PartitionPropertyNames partitionPropertyNames; private final PartitionPropertyNames partitionPropertyNames;
private final ICache<String, byte[]> legalCOOCache;
@Override @Override
public IStorageReader getReader(TenantInfo tenant, String projectRegion) { public IStorageReader getReader(TenantInfo tenant, String projectRegion) {
return new StorageReaderImpl( return new StorageReaderImpl(
tenant, storage, partitionPropertyResolver, partitionPropertyNames); tenant, storage, partitionPropertyResolver, partitionPropertyNames, legalCOOCache);
} }
} }
/* /*
* Copyright 2020-2023 Google LLC * Copyright 2020-2024 Google LLC
* Copyright 2020-2023 EPAM Systems, Inc * Copyright 2020-2024 EPAM Systems, Inc
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -17,8 +17,10 @@ ...@@ -17,8 +17,10 @@
package org.opengroup.osdu.legal.countries; package org.opengroup.osdu.legal.countries;
import java.util.Objects;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.opengroup.osdu.core.common.cache.ICache;
import org.opengroup.osdu.core.common.model.tenant.TenantInfo; import org.opengroup.osdu.core.common.model.tenant.TenantInfo;
import org.opengroup.osdu.core.common.partition.PartitionPropertyResolver; import org.opengroup.osdu.core.common.partition.PartitionPropertyResolver;
import org.opengroup.osdu.core.obm.core.Driver; import org.opengroup.osdu.core.obm.core.Driver;
...@@ -28,31 +30,31 @@ import org.opengroup.osdu.core.obm.core.persistence.ObmDestination; ...@@ -28,31 +30,31 @@ import org.opengroup.osdu.core.obm.core.persistence.ObmDestination;
import org.opengroup.osdu.legal.config.PartitionPropertyNames; import org.opengroup.osdu.legal.config.PartitionPropertyNames;
import org.opengroup.osdu.legal.provider.interfaces.IStorageReader; import org.opengroup.osdu.legal.provider.interfaces.IStorageReader;
import java.util.Objects;
@RequiredArgsConstructor @RequiredArgsConstructor
@Slf4j @Slf4j
public class StorageReaderImpl implements IStorageReader { public class StorageReaderImpl implements IStorageReader {
private static final String SEPARATOR = "-";
private static final String FILE_NAME = "Legal_COO.json";
protected static final String BUCKET_NAME = "legal-config";
private PartitionPropertyResolver partitionPropertyResolver; private PartitionPropertyResolver partitionPropertyResolver;
private PartitionPropertyNames partitionPropertyNames; private PartitionPropertyNames partitionPropertyNames;
private TenantInfo tenantInfo; private TenantInfo tenantInfo;
private Driver storage; private Driver storage;
private ICache<String, byte[]> legalCOOCache;
protected static final String BUCKET_NAME = "legal-config";
private static final String FILE_NAME = "Legal_COO.json";
private boolean isFullBucketName = false;
public StorageReaderImpl( public StorageReaderImpl(
TenantInfo tenantInfo, TenantInfo tenantInfo,
Driver storage, Driver storage,
PartitionPropertyResolver partitionPropertyResolver, PartitionPropertyResolver partitionPropertyResolver,
PartitionPropertyNames partitionPropertyNames) { PartitionPropertyNames partitionPropertyNames,
ICache<String, byte[]> legalCOOCache) {
this.tenantInfo = tenantInfo; this.tenantInfo = tenantInfo;
this.storage = storage; this.storage = storage;
this.partitionPropertyResolver = partitionPropertyResolver; this.partitionPropertyResolver = partitionPropertyResolver;
this.partitionPropertyNames = partitionPropertyNames; this.partitionPropertyNames = partitionPropertyNames;
this.legalCOOCache = legalCOOCache;
} }
@Override @Override
...@@ -66,12 +68,17 @@ public class StorageReaderImpl implements IStorageReader { ...@@ -66,12 +68,17 @@ public class StorageReaderImpl implements IStorageReader {
log.warn("Bucket %s is not existing.".formatted(tenantBucketName)); log.warn("Bucket %s is not existing.".formatted(tenantBucketName));
return new byte[0]; return new byte[0];
} }
String dataPartitionId = tenantInfo.getDataPartitionId();
Blob blob = storage.getBlob(tenantBucketName, FILE_NAME, destination); if (Objects.isNull(legalCOOCache.get(dataPartitionId))) {
if (Objects.isNull(blob)) { Blob blob = storage.getBlob(tenantBucketName, FILE_NAME, destination);
log.warn("File %s in bucket %s is not existing.".formatted(FILE_NAME, tenantBucketName)); if (Objects.isNull(blob)) {
log.warn("File %s in bucket %s is not existing.".formatted(FILE_NAME, tenantBucketName));
} else {
content = storage.getBlobContent(getTenantBucketName(), FILE_NAME, getDestination());
legalCOOCache.put(dataPartitionId, content);
}
} else { } else {
content = storage.getBlobContent(getTenantBucketName(), FILE_NAME, getDestination()); content = legalCOOCache.get(dataPartitionId);
} }
} catch (ObmDriverRuntimeException e) { } catch (ObmDriverRuntimeException e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
...@@ -86,9 +93,9 @@ public class StorageReaderImpl implements IStorageReader { ...@@ -86,9 +93,9 @@ public class StorageReaderImpl implements IStorageReader {
.orElseGet( .orElseGet(
() -> () ->
this.tenantInfo.getProjectId() this.tenantInfo.getProjectId()
+ "-" + SEPARATOR
+ this.tenantInfo.getName() + this.tenantInfo.getName()
+ "-" + SEPARATOR
+ BUCKET_NAME); + BUCKET_NAME);
} }
......
...@@ -17,13 +17,20 @@ ...@@ -17,13 +17,20 @@
package org.opengroup.osdu.legal.countries; package org.opengroup.osdu.legal.countries;
import org.junit.Before; import static org.junit.Assert.*;
import static org.powermock.api.mockito.PowerMockito.when;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import org.junit.Test; import org.junit.Test;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.InjectMocks; import org.mockito.InjectMocks;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.MockitoJUnitRunner;
import org.opengroup.osdu.core.common.cache.ICache;
import org.opengroup.osdu.core.common.model.tenant.TenantInfo; import org.opengroup.osdu.core.common.model.tenant.TenantInfo;
import org.opengroup.osdu.core.common.partition.PartitionPropertyResolver; import org.opengroup.osdu.core.common.partition.PartitionPropertyResolver;
import org.opengroup.osdu.core.obm.core.Driver; import org.opengroup.osdu.core.obm.core.Driver;
...@@ -32,32 +39,52 @@ import org.opengroup.osdu.core.obm.core.model.Bucket; ...@@ -32,32 +39,52 @@ import org.opengroup.osdu.core.obm.core.model.Bucket;
import org.opengroup.osdu.core.obm.core.persistence.ObmDestination; import org.opengroup.osdu.core.obm.core.persistence.ObmDestination;
import org.opengroup.osdu.legal.config.PartitionPropertyNames; import org.opengroup.osdu.legal.config.PartitionPropertyNames;
import java.util.Optional;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.powermock.api.mockito.PowerMockito.when;
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class StorageReaderImplTests { public class StorageReaderImplTests {
private static final String TENANT_1 = "tenant1"; private static final String TENANT_1 = "tenant1";
private static final String FILE_NAME = "Legal_COO.json"; private static final String FILE_NAME = "Legal_COO.json";
private static final String BUCKET_FULL_NAME = "tenant1-tenant1-legal-config"; private static final String BUCKET_FULL_NAME = "tenant1-tenant1-legal-config";
private static final String CONTENT =
"""
[{
"name": "Malaysia",
"alpha2": "MY",
"numeric": 458,
"residencyRisk": "Client consent required"
}]""";
private static final String PARTITION_BUCKET_NAME = "partition-bucket-name";
@Mock
private TenantInfo tenantInfo;
@Mock
private Driver storage;
@Mock private TenantInfo tenantInfo; @Mock
private PartitionPropertyNames partitionPropertyNames;
@Mock private Driver storage; @Mock
private PartitionPropertyResolver partitionPropertyResolver;
@Mock private PartitionPropertyNames partitionPropertyNames; @Mock
private ICache<String, byte[]> legalCOOCache;
@Mock private PartitionPropertyResolver partitionPropertyResolver; @InjectMocks
private StorageReaderImpl sut;
@InjectMocks private StorageReaderImpl sut; private AutoCloseable mocks;
@Before @BeforeEach
public void setup() { void setup() {
MockitoAnnotations.initMocks(this); mocks = MockitoAnnotations.openMocks(this);
}
@AfterEach
void tearDown() throws Exception {
if (mocks != null) {
mocks.close();
}
} }
@Test @Test
...@@ -68,11 +95,12 @@ public class StorageReaderImplTests { ...@@ -68,11 +95,12 @@ public class StorageReaderImplTests {
when(storage.getBucket(BUCKET_FULL_NAME, getDestination())).thenReturn(new Bucket(TENANT_1)); when(storage.getBucket(BUCKET_FULL_NAME, getDestination())).thenReturn(new Bucket(TENANT_1));
when(storage.getBlob(BUCKET_FULL_NAME, FILE_NAME, getDestination())) when(storage.getBlob(BUCKET_FULL_NAME, FILE_NAME, getDestination()))
.thenReturn(Blob.builder().build()); .thenReturn(Blob.builder().build());
byte[] expectedBytes = "test".getBytes(); byte[] expectedBytes = CONTENT.getBytes();
when(storage.getBlobContent(BUCKET_FULL_NAME, FILE_NAME, getDestination())) when(storage.getBlobContent(BUCKET_FULL_NAME, FILE_NAME, getDestination()))
.thenReturn(expectedBytes); .thenReturn(expectedBytes);
byte[] bytes = sut.readAllBytes(); byte[] bytes = sut.readAllBytes();
assertEquals(expectedBytes, bytes); assertEquals(expectedBytes, bytes);
} }
...@@ -83,7 +111,8 @@ public class StorageReaderImplTests { ...@@ -83,7 +111,8 @@ public class StorageReaderImplTests {
when(tenantInfo.getProjectId()).thenReturn(TENANT_1); when(tenantInfo.getProjectId()).thenReturn(TENANT_1);
byte[] bytes = sut.readAllBytes(); byte[] bytes = sut.readAllBytes();
assertTrue(bytes.length == 0);
assertEquals(0, bytes.length);
} }
@Test @Test
...@@ -97,21 +126,40 @@ public class StorageReaderImplTests { ...@@ -97,21 +126,40 @@ public class StorageReaderImplTests {
when(storage.getBlobContent(BUCKET_FULL_NAME, FILE_NAME, getDestination())).thenReturn(null); when(storage.getBlobContent(BUCKET_FULL_NAME, FILE_NAME, getDestination())).thenReturn(null);
byte[] bytes = sut.readAllBytes(); byte[] bytes = sut.readAllBytes();
assertTrue(bytes.length == 0);
assertEquals(0, bytes.length);
} }
@Test @Test
public void should_returnBucketName_fromPartition() { public void should_returnBucketName_fromPartition() {
when(partitionPropertyNames.getLegalBucketName()).thenReturn("partition-bucket-name"); when(partitionPropertyNames.getLegalBucketName()).thenReturn(PARTITION_BUCKET_NAME);
when(partitionPropertyResolver.getOptionalPropertyValue( when(partitionPropertyResolver.getOptionalPropertyValue(
partitionPropertyNames.getLegalBucketName(), tenantInfo.getDataPartitionId())) partitionPropertyNames.getLegalBucketName(), tenantInfo.getDataPartitionId()))
.thenReturn(Optional.of("partition-bucket-name")); .thenReturn(Optional.of(PARTITION_BUCKET_NAME));
StorageReaderImpl storageReader = StorageReaderImpl storageReader =
new StorageReaderImpl( new StorageReaderImpl(
tenantInfo, storage, partitionPropertyResolver, partitionPropertyNames); tenantInfo, storage, partitionPropertyResolver, partitionPropertyNames, legalCOOCache);
String resultBucketName = storageReader.getTenantBucketName(); String resultBucketName = storageReader.getTenantBucketName();
assertEquals("partition-bucket-name", resultBucketName);
assertEquals(PARTITION_BUCKET_NAME, resultBucketName);
}
@Test
public void shouldReturnContentAsBytes_whenCacheEntryFound() {
byte[] expected = CONTENT.getBytes(StandardCharsets.UTF_8);
when(tenantInfo.getName()).thenReturn(TENANT_1);
when(tenantInfo.getDataPartitionId()).thenReturn(TENANT_1);
when(tenantInfo.getProjectId()).thenReturn(TENANT_1);
when(storage.getBucket(BUCKET_FULL_NAME, getDestination())).thenReturn(new Bucket(TENANT_1));
when(legalCOOCache.get(tenantInfo.getDataPartitionId())).thenReturn(expected);
StorageReaderImpl storageReader =
new StorageReaderImpl(
tenantInfo, storage, partitionPropertyResolver, partitionPropertyNames, legalCOOCache);
byte[] actual = storageReader.readAllBytes();
assertArrayEquals(expected, actual);
} }
private ObmDestination getDestination() { private ObmDestination getDestination() {
......
package org.opengroup.osdu.legal.countries; package org.opengroup.osdu.legal.countries;
import jakarta.inject.Inject;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import lombok.extern.java.Log;
import org.apache.commons.lang3.StringUtils;
import org.opengroup.osdu.core.common.model.http.AppException;
import org.opengroup.osdu.core.common.model.http.DpsHeaders; import org.opengroup.osdu.core.common.model.http.DpsHeaders;
import org.opengroup.osdu.core.common.model.tenant.TenantInfo; import org.opengroup.osdu.core.common.model.tenant.TenantInfo;
import org.opengroup.osdu.core.common.model.http.AppException;
import org.opengroup.osdu.legal.provider.interfaces.IStorageReader; import org.opengroup.osdu.legal.provider.interfaces.IStorageReader;
import org.opengroup.osdu.legal.provider.interfaces.IStorageReaderFactory; import org.opengroup.osdu.legal.provider.interfaces.IStorageReaderFactory;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import lombok.extern.java.Log;
import org.apache.commons.lang3.StringUtils;
import java.util.HashMap;
import java.util.Map;
import jakarta.inject.Inject;
@Repository @Repository
@Log @Log
public class LegalTagCountriesTenantRepositories { public class LegalTagCountriesTenantRepositories {
...@@ -22,7 +19,7 @@ public class LegalTagCountriesTenantRepositories { ...@@ -22,7 +19,7 @@ public class LegalTagCountriesTenantRepositories {
@Inject @Inject
private IStorageReaderFactory storageReaderFactory; private IStorageReaderFactory storageReaderFactory;
private final Map<String, LegalTagCountriesRepository> countriesTenantRepositories = new HashMap<>(); private final Map<String, LegalTagCountriesRepository> countriesTenantRepositories = new ConcurrentHashMap<>();
LegalTagCountriesRepository get(TenantInfo tenant, String projectRegion){ LegalTagCountriesRepository get(TenantInfo tenant, String projectRegion){
String tenantName = tenant.getName(); String tenantName = tenant.getName();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment