#39 reactive programming: completable future - blocking

This commit is contained in:
haerong22
2023-07-17 18:42:04 +09:00
parent ac03b1be8f
commit 61b8775c9e
7 changed files with 226 additions and 0 deletions

View File

@@ -13,6 +13,10 @@ dependencies {
compileOnly 'org.projectlombok:lombok:1.18.28'
annotationProcessor 'org.projectlombok:lombok:1.18.28'
implementation 'org.slf4j:slf4j-api:2.0.7'
implementation 'ch.qos.logback:logback-classic:1.4.8'
implementation 'ch.qos.logback:logback-core:1.4.8'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}

View File

@@ -0,0 +1,47 @@
package org.example.completablefuture.blocking;
import lombok.RequiredArgsConstructor;
import org.example.completablefuture.blocking.repository.ArticleRepository;
import org.example.completablefuture.blocking.repository.FollowRepository;
import org.example.completablefuture.blocking.repository.ImageRepository;
import org.example.completablefuture.blocking.repository.UserRepository;
import org.example.completablefuture.common.Article;
import org.example.completablefuture.common.Image;
import org.example.completablefuture.common.User;
import java.util.Optional;
import java.util.stream.Collectors;
@RequiredArgsConstructor
public class UserBlockingService {
private final UserRepository userRepository;
private final ArticleRepository articleRepository;
private final ImageRepository imageRepository;
private final FollowRepository followRepository;
public Optional<User> getUserById(String id) {
return userRepository.findById(id)
.map(user -> {
var image = imageRepository.findById(user.getProfileImageId())
.map(imageEntity -> {
return new Image(imageEntity.getId(), imageEntity.getName(), imageEntity.getUrl());
});
var articles = articleRepository.findAllByUserId(user.getId())
.stream().map(articleEntity ->
new Article(articleEntity.getId(), articleEntity.getTitle(), articleEntity.getContent()))
.collect(Collectors.toList());
var followCount = followRepository.countByUserId(user.getId());
return new User(
user.getId(),
user.getName(),
user.getAge(),
image,
articles,
followCount
);
});
}
}

View File

@@ -0,0 +1,30 @@
package org.example.completablefuture.blocking.repository;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.example.completablefuture.common.repository.ArticleEntity;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
public class ArticleRepository {
private static List<ArticleEntity> articleEntities;
public ArticleRepository() {
articleEntities = List.of(
new ArticleEntity("1", "소식1", "내용1", "1234"),
new ArticleEntity("2", "소식2", "내용2", "1234"),
new ArticleEntity("3", "소식3", "내용3", "10000")
);
}
@SneakyThrows
public List<ArticleEntity> findAllByUserId(String userId) {
log.info("ArticleRepository.findAllByUserId: {}", userId);
Thread.sleep(1000);
return articleEntities.stream()
.filter(articleEntity -> articleEntity.getUserId().equals(userId))
.collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,22 @@
package org.example.completablefuture.blocking.repository;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
@Slf4j
public class FollowRepository {
private Map<String, Long> userFollowCountMap;
public FollowRepository() {
userFollowCountMap = Map.of("1234", 1000L);
}
@SneakyThrows
public Long countByUserId(String userId) {
log.info("FollowRepository.countByUserId: {}", userId);
Thread.sleep(1000);
return userFollowCountMap.getOrDefault(userId, 0L);
}
}

View File

@@ -0,0 +1,26 @@
package org.example.completablefuture.blocking.repository;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.example.completablefuture.common.repository.ImageEntity;
import java.util.Map;
import java.util.Optional;
@Slf4j
public class ImageRepository {
private final Map<String, ImageEntity> imageMap;
public ImageRepository() {
imageMap = Map.of(
"image#1000", new ImageEntity("image#1000", "profileImage", "https://dailyone.com/images/1000")
);
}
@SneakyThrows
public Optional<ImageEntity> findById(String id) {
log.info("ImageRepository.findById: {}", id);
Thread.sleep(1000);
return Optional.ofNullable(imageMap.get(id));
}
}

View File

@@ -0,0 +1,27 @@
package org.example.completablefuture.blocking.repository;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.example.completablefuture.common.repository.UserEntity;
import java.util.Map;
import java.util.Optional;
@Slf4j
public class UserRepository {
private final Map<String, UserEntity> userMap;
public UserRepository() {
var user = new UserEntity("1234", "taewoo", 32, "image#1000");
userMap = Map.of("1234", user);
}
@SneakyThrows
public Optional<UserEntity> findById(String userId) {
log.info("UserRepository.findById: {}", userId);
Thread.sleep(1000);
var user = userMap.get(userId);
return Optional.ofNullable(user);
}
}

View File

@@ -0,0 +1,70 @@
package org.example.completablefuture.blocking;
import org.example.completablefuture.blocking.repository.ArticleRepository;
import org.example.completablefuture.blocking.repository.FollowRepository;
import org.example.completablefuture.blocking.repository.ImageRepository;
import org.example.completablefuture.blocking.repository.UserRepository;
import org.example.completablefuture.common.User;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
class UserBlockingServiceTest {
UserBlockingService userBlockingService;
UserRepository userRepository;
ArticleRepository articleRepository;
ImageRepository imageRepository;
FollowRepository followRepository;
@BeforeEach
void setUp() {
userRepository = new UserRepository();
articleRepository = new ArticleRepository();
imageRepository = new ImageRepository();
followRepository = new FollowRepository();
userBlockingService = new UserBlockingService(
userRepository, articleRepository, imageRepository, followRepository
);
}
@Test
void getUserEmptyIfInvalidUserIdIsGiven() {
// given
String userId = "invalid_user_id";
// when
Optional<User> user = userBlockingService.getUserById(userId);
// then
assertTrue(user.isEmpty());
}
@Test
void testGetUser() {
// given
String userId = "1234";
// when
Optional<User> optionalUser = userBlockingService.getUserById(userId);
// then
assertFalse(optionalUser.isEmpty());
var user = optionalUser.get();
assertEquals(user.getName(), "taewoo");
assertEquals(user.getAge(), 32);
assertFalse(user.getProfileImage().isEmpty());
var image = user.getProfileImage().get();
assertEquals(image.getId(), "image#1000");
assertEquals(image.getName(), "profileImage");
assertEquals(image.getUrl(), "https://dailyone.com/images/1000");
assertEquals(2, user.getArticleList().size());
assertEquals(1000, user.getFollowCount());
}
}