отделили реализацию minio в отлдельный модуль

This commit is contained in:
2022-05-09 19:14:23 +03:00
parent 8e05d49198
commit f476c81f4e
18 changed files with 187 additions and 109 deletions

35
mirror-minio/build.gradle Normal file
View File

@@ -0,0 +1,35 @@
apply plugin: 'java-library'
apply plugin: 'idea'
configurations {
integrationTestImplementation {
extendsFrom(testImplementation)
}
integrationTestRuntimeOnly {
extendsFrom(testRuntimeOnly)
}
}
sourceSets {
integrationTest {
java {
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
srcDir file('src/integrationTest/java')
}
resources {
srcDir file('src/integrationTest/resources')
}
}
}
idea.module {
testSourceDirs += sourceSets.integrationTest.java.srcDirs
testResourceDirs += sourceSets.integrationTest.resources.srcDirs
}
dependencies {
implementation(project(':mirror-core'))
api("io.minio:minio:${minioVersion}")
}

View File

@@ -0,0 +1,69 @@
package ru.di9.mirror.core.service;
import io.minio.MinioClient;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import ru.di9.mirror.core.domain.FileItem;
import ru.di9.mirror.minio.service.MinioRepository;
import java.io.InputStream;
import java.util.List;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
class MinioServiceIntTest {
static final String url = "http://dev.di9.ru:9000";
static final String accessKey = "mirror";
static final String secretKey = "mirror123";
static final String bucket = "mirror";
static MinioClient minioClient;
MinioRepository minioService;
@BeforeAll
static void beforeAll() {
minioClient = MinioClient.builder()
.endpoint(url)
.credentials(accessKey, secretKey)
.build();
}
@BeforeEach
void setUp() {
minioService = new MinioRepository(minioClient, bucket);
}
@Test
void list() {
List<FileItem> list = minioService.list("/local/ghast/ghast-tools/");
assertNotNull(list);
assertFalse(list.isEmpty());
assertTrue(list.stream()
.anyMatch(itemRecord2 -> itemRecord2.name().equals("maven-metadata.xml")
&& !itemRecord2.isDir()
&& itemRecord2.size() == 320));
assertTrue(list.stream()
.anyMatch(itemRecord2 -> itemRecord2.name().equals("1.13")
&& itemRecord2.isDir()
&& itemRecord2.size() == 0));
}
@Test
void notExists() {
Optional<InputStream> optional = minioService.findByName("/not/exists/path/to/object");
assertNotNull(optional);
assertTrue(optional.isEmpty());
}
@Test
void exists() {
Optional<InputStream> optional = minioService.findByName("/local/ghast/ghast-tools/maven-metadata.xml");
assertNotNull(optional);
assertTrue(optional.isPresent());
}
}

View File

@@ -0,0 +1,51 @@
package ru.di9.mirror.minio.domain;
import io.minio.Result;
import io.minio.messages.Item;
import lombok.RequiredArgsConstructor;
import ru.di9.mirror.core.domain.FileItem;
import ru.di9.mirror.minio.exception.MinioException;
@RequiredArgsConstructor
public class MinioFileItem implements FileItem {
private final Result<Item> itemResult;
private final String prefix;
@Override
public boolean isDir() {
try {
return itemResult.get().isDir();
} catch (Exception e) {
throw createException(e);
}
}
@Override
public String name() {
try {
String objectName = itemResult.get().objectName();
if (isDir()) {
return objectName.substring(prefix.length() - 1, objectName.length() - 1);
} else {
return objectName.substring(prefix.length() - 1);
}
} catch (MinioException e) {
throw e;
} catch (Exception e) {
throw createException(e);
}
}
@Override
public long size() {
try {
return itemResult.get().size();
} catch (Exception e) {
throw createException(e);
}
}
private MinioException createException(Exception e) {
return new MinioException("Error get result item", e);
}
}

View File

@@ -0,0 +1,7 @@
package ru.di9.mirror.minio.exception;
public class MinioException extends RuntimeException {
public MinioException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,74 @@
package ru.di9.mirror.minio.service;
import io.minio.*;
import io.minio.errors.ErrorResponseException;
import io.minio.messages.Item;
import lombok.RequiredArgsConstructor;
import ru.di9.mirror.core.domain.FileItem;
import ru.di9.mirror.core.repository.FileStorageRepository;
import ru.di9.mirror.minio.domain.MinioFileItem;
import ru.di9.mirror.minio.exception.MinioException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@RequiredArgsConstructor
public class MinioRepository implements FileStorageRepository {
private static final long UNKNOWN_SIZE = -1L;
private static final long PART_SIZE = (5 * 1024 * 1024); // 5 MB
private final MinioClient minioClient;
private final String bucket;
@Override
public void save(String name, InputStream inputStream) {
try {
minioClient.putObject(PutObjectArgs.builder()
.bucket(bucket)
.object(name)
.stream(inputStream, UNKNOWN_SIZE, PART_SIZE)
.build());
} catch (Exception e) {
throw new MinioException("Error put file", e);
}
}
@Override
public Optional<InputStream> findByName(String name) {
try {
return Optional.of(minioClient.getObject(GetObjectArgs.builder()
.bucket(bucket)
.object(name)
.build()));
} catch (ErrorResponseException e) {
if (e.errorResponse().code().equalsIgnoreCase("NoSuchKey")) {
return Optional.empty();
} else {
throw new MinioException("Error get file", e);
}
} catch (Exception e) {
throw new MinioException("Error get file", e);
}
}
@Override
public List<FileItem> list(String prefix) {
if (!prefix.endsWith("/")) {
prefix = prefix + "/";
}
Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder()
.bucket(bucket)
.prefix(prefix)
.build());
List<FileItem> list = new ArrayList<>();
for (Result<Item> result : results) {
list.add(new MinioFileItem(result, prefix));
}
return list;
}
}

View File

@@ -0,0 +1,64 @@
package ru.di9.mirror.core.service;
import io.minio.ListObjectsArgs;
import io.minio.MinioClient;
import io.minio.Result;
import io.minio.messages.Item;
import lombok.SneakyThrows;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import ru.di9.mirror.core.domain.FileItem;
import ru.di9.mirror.minio.service.MinioRepository;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
class MinioServiceTest {
static final String bucket = "mirror";
static MinioClient mockMinioClient;
@BeforeAll
static void beforeAll() {
mockMinioClient = mock(MinioClient.class);
Iterable<Result<Item>> listObjects = List.of(
mockResult("ghast/ghast-tools/maven-metadata.xml", 320, false),
mockResult("ghast/ghast-tools/1.13/", 0, true)
);
when(mockMinioClient.listObjects(any(ListObjectsArgs.class))).thenReturn(listObjects);
}
@Test
void list() {
MinioRepository minioService = new MinioRepository(mockMinioClient, bucket);
List<FileItem> list = minioService.list("/ghast/ghast-tools/");
assertNotNull(list);
assertFalse(list.isEmpty());
assertTrue(list.stream()
.anyMatch(itemRecord2 -> itemRecord2.name().equals("maven-metadata.xml")
&& !itemRecord2.isDir()
&& itemRecord2.size() == 320));
assertTrue(list.stream()
.anyMatch(itemRecord2 -> itemRecord2.name().equals("1.13")
&& itemRecord2.isDir()
&& itemRecord2.size() == 0));
}
@SuppressWarnings("unchecked")
@SneakyThrows
private static Result<Item> mockResult(String name, long size, boolean isDir) {
Item item = mock(Item.class);
when(item.objectName()).thenReturn(name);
when(item.size()).thenReturn(size);
when(item.isDir()).thenReturn(isDir);
Result<Item> result = mock(Result.class);
when(result.get()).thenReturn(item);
return result;
}
}