Skip to content

Commit 673a92f

Browse files
authored
Merge pull request #116 from Recipe-Project/fix/blog_youtube_recipes
fix: 유튜브/블로그 레시피 조회 시 저장 후 재조회하도록 처리
2 parents 94dca28 + 4ab08e4 commit 673a92f

7 files changed

Lines changed: 22 additions & 166 deletions

File tree

src/main/java/com/recipe/app/src/recipe/application/blog/BlogRecipeClientSearchService.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import lombok.extern.slf4j.Slf4j;
88
import org.springframework.beans.factory.annotation.Value;
99
import org.springframework.stereotype.Service;
10-
import org.springframework.transaction.annotation.Transactional;
1110

1211
import java.util.List;
1312
import java.util.Map;
@@ -38,7 +37,7 @@ public BlogRecipeClientSearchService(BlogRecipeRepository blogRecipeRepository,
3837
}
3938

4039
@CircuitBreaker(name = "recipe-blog-search", fallbackMethod = "fallback")
41-
public List<BlogRecipe> searchNaverBlogRecipes(String keyword, int size) {
40+
public void searchNaverBlogRecipes(String keyword) {
4241

4342
log.info("naver blog search api call");
4443

@@ -52,8 +51,6 @@ public List<BlogRecipe> searchNaverBlogRecipes(String keyword, int size) {
5251
createBlogRecipes(blogRecipes);
5352

5453
blogRecipeThumbnailCrawlingService.saveThumbnails(blogRecipes);
55-
56-
return blogRecipes.subList(0, size);
5754
}
5855

5956
public List<BlogRecipe> fallback(String keyword, int size, Exception e) {
@@ -63,12 +60,11 @@ public List<BlogRecipe> fallback(String keyword, int size, Exception e) {
6360
return blogRecipeRepository.findByKeywordLimit(keyword, size);
6461
}
6562

66-
@Transactional
67-
public void createBlogRecipes(List<BlogRecipe> blogRecipes) {
63+
private void createBlogRecipes(List<BlogRecipe> blogRecipes) {
6864

6965
List<String> blogUrls = blogRecipes.stream().map(BlogRecipe::getBlogUrl).collect(Collectors.toList());
7066
List<BlogRecipe> existBlogRecipes = blogRecipeRepository.findByBlogUrlIn(blogUrls);
71-
Map<String, BlogRecipe> existBlogRecipeMapByBlogUrl = existBlogRecipes.stream().collect(Collectors.toMap(BlogRecipe::getBlogUrl, Function.identity()));
67+
Map<String, BlogRecipe> existBlogRecipeMapByBlogUrl = existBlogRecipes.stream().collect(Collectors.toMap(BlogRecipe::getBlogUrl, Function.identity(), (o1, o2) -> o1));
7268

7369
blogRecipeRepository.saveAll(blogRecipes.stream()
7470
.filter(blogRecipe -> !existBlogRecipeMapByBlogUrl.containsKey(blogRecipe.getBlogUrl()))

src/main/java/com/recipe/app/src/recipe/application/blog/BlogRecipeService.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public BlogRecipeService(BlogRecipeRepository blogRecipeRepository, BlogScrapSer
3333
this.blogRecipeClientSearchService = blogRecipeClientSearchService;
3434
}
3535

36+
@Transactional
3637
public RecipesResponse findBlogRecipesByKeyword(User user, String keyword, long lastBlogRecipeId, int size, String sort) {
3738

3839
badWordFiltering.check(keyword);
@@ -41,19 +42,16 @@ public RecipesResponse findBlogRecipesByKeyword(User user, String keyword, long
4142

4243
List<BlogRecipe> blogRecipes;
4344
if (totalCnt < MIN_RECIPE_CNT) {
44-
45-
blogRecipes = blogRecipeClientSearchService.searchNaverBlogRecipes(keyword, size);
46-
47-
totalCnt = blogRecipeRepository.countByKeyword(keyword);
48-
} else {
49-
blogRecipes = findByKeywordOrderBy(keyword, lastBlogRecipeId, size, sort);
45+
blogRecipeClientSearchService.searchNaverBlogRecipes(keyword);
5046
}
5147

48+
blogRecipes = findByKeywordOrderBy(keyword, lastBlogRecipeId, size, sort);
49+
totalCnt = blogRecipeRepository.countByKeyword(keyword);
50+
5251
return getRecipes(user, totalCnt, new BlogRecipes(blogRecipes));
5352
}
5453

55-
@Transactional(readOnly = true)
56-
public List<BlogRecipe> findByKeywordOrderBy(String keyword, long lastBlogRecipeId, int size, String sort) {
54+
private List<BlogRecipe> findByKeywordOrderBy(String keyword, long lastBlogRecipeId, int size, String sort) {
5755

5856
if (sort.equals("scraps")) {
5957
return findByKeywordOrderByBlogScrapCnt(keyword, lastBlogRecipeId, size);

src/main/java/com/recipe/app/src/recipe/application/blog/BlogRecipeThumbnailCrawlingService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import org.jsoup.select.Elements;
99
import org.springframework.scheduling.annotation.Async;
1010
import org.springframework.stereotype.Service;
11+
import org.springframework.transaction.annotation.Propagation;
12+
import org.springframework.transaction.annotation.Transactional;
1113

1214
import java.net.URL;
1315
import java.util.List;
@@ -22,6 +24,7 @@ public BlogRecipeThumbnailCrawlingService(BlogRecipeRepository blogRecipeReposit
2224
}
2325

2426
@Async
27+
@Transactional(propagation = Propagation.REQUIRES_NEW)
2528
public void saveThumbnails(List<BlogRecipe> blogRecipes) {
2629

2730
System.out.println("thumbnail save");

src/main/java/com/recipe/app/src/recipe/application/youtube/YoutubeRecipeClientSearchService.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import lombok.extern.slf4j.Slf4j;
1616
import org.springframework.beans.factory.annotation.Value;
1717
import org.springframework.stereotype.Service;
18-
import org.springframework.transaction.annotation.Transactional;
1918

2019
import java.io.IOException;
2120
import java.time.Instant;
@@ -24,6 +23,7 @@
2423
import java.util.ArrayList;
2524
import java.util.List;
2625
import java.util.Map;
26+
import java.util.function.Function;
2727
import java.util.stream.Collectors;
2828

2929
@Slf4j
@@ -44,7 +44,7 @@ public YoutubeRecipeClientSearchService(YoutubeRecipeRepository youtubeRecipeRep
4444
}
4545

4646
@CircuitBreaker(name = "recipe-youtube-search", fallbackMethod = "fallback")
47-
public List<YoutubeRecipe> searchYoutube(String keyword, int size) throws IOException {
47+
public void searchYoutube(String keyword) throws IOException {
4848

4949
log.info("youtube search api call");
5050

@@ -80,8 +80,6 @@ public void initialize(HttpRequest request) throws IOException {
8080
}
8181

8282
createYoutubeRecipes(youtubeRecipes);
83-
84-
return youtubeRecipes.subList(0, size);
8583
}
8684

8785
public List<YoutubeRecipe> fallback(String keyword, int size, Exception e) {
@@ -91,12 +89,11 @@ public List<YoutubeRecipe> fallback(String keyword, int size, Exception e) {
9189
return youtubeRecipeRepository.findByKeywordLimit(keyword, size);
9290
}
9391

94-
@Transactional
95-
public void createYoutubeRecipes(List<YoutubeRecipe> youtubeRecipes) {
92+
private void createYoutubeRecipes(List<YoutubeRecipe> youtubeRecipes) {
9693

9794
List<String> youtubeIds = youtubeRecipes.stream().map(YoutubeRecipe::getYoutubeId).collect(Collectors.toList());
9895
List<YoutubeRecipe> existYoutubeRecipes = youtubeRecipeRepository.findByYoutubeIdIn(youtubeIds);
99-
Map<String, YoutubeRecipe> existYoutubeRecipesMapByYoutubeId = existYoutubeRecipes.stream().collect(Collectors.toMap(YoutubeRecipe::getYoutubeId, v -> v));
96+
Map<String, YoutubeRecipe> existYoutubeRecipesMapByYoutubeId = existYoutubeRecipes.stream().collect(Collectors.toMap(YoutubeRecipe::getYoutubeId, Function.identity(), (o1, o2) -> o1));
10097

10198
youtubeRecipeRepository.saveAll(youtubeRecipes.stream()
10299
.filter(youtubeRecipe -> !existYoutubeRecipesMapByYoutubeId.containsKey(youtubeRecipe.getYoutubeId()))

src/main/java/com/recipe/app/src/recipe/application/youtube/YoutubeRecipeService.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public YoutubeRecipeService(YoutubeRecipeRepository youtubeRecipeRepository, You
3232
this.youtubeRecipeClientSearchService = youtubeRecipeClientSearchService;
3333
}
3434

35+
@Transactional
3536
public RecipesResponse findYoutubeRecipesByKeyword(User user, String keyword, long lastYoutubeRecipeId, int size, String sort) throws IOException {
3637

3738
badWordFiltering.check(keyword);
@@ -40,19 +41,16 @@ public RecipesResponse findYoutubeRecipesByKeyword(User user, String keyword, lo
4041

4142
List<YoutubeRecipe> youtubeRecipes;
4243
if (totalCnt < MIN_RECIPE_CNT) {
43-
44-
youtubeRecipes = youtubeRecipeClientSearchService.searchYoutube(keyword, size);
45-
46-
totalCnt = youtubeRecipeRepository.countByKeyword(keyword);
47-
} else {
48-
youtubeRecipes = findByKeywordOrderBy(keyword, lastYoutubeRecipeId, size, sort);
44+
youtubeRecipeClientSearchService.searchYoutube(keyword);
4945
}
5046

47+
youtubeRecipes = findByKeywordOrderBy(keyword, lastYoutubeRecipeId, size, sort);
48+
totalCnt = youtubeRecipeRepository.countByKeyword(keyword);
49+
5150
return getRecipes(user, totalCnt, new YoutubeRecipes(youtubeRecipes));
5251
}
5352

54-
@Transactional(readOnly = true)
55-
public List<YoutubeRecipe> findByKeywordOrderBy(String keyword, long lastYoutubeRecipeId, int size, String sort) {
53+
private List<YoutubeRecipe> findByKeywordOrderBy(String keyword, long lastYoutubeRecipeId, int size, String sort) {
5654

5755
if (sort.equals("scraps")) {
5856
return findByKeywordOrderByYoutubeScrapCnt(keyword, lastYoutubeRecipeId, size);

src/test/groovy/com/recipe/app/src/recipe/application/blog/BlogRecipeServiceTest.groovy

Lines changed: 0 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -230,74 +230,6 @@ class BlogRecipeServiceTest extends Specification {
230230
result.recipes.viewCnt == blogRecipes.viewCnt
231231
}
232232

233-
def "블로그 레시피 검색 - 외부 API 요청"() {
234-
235-
given:
236-
User user = User.builder()
237-
.userId(1)
238-
.socialId("naver_1")
239-
.nickname("테스터1")
240-
.build()
241-
242-
String keyword = "테스트"
243-
long lastBlogRecipeId = 0
244-
int size = 2
245-
String sort = "newest"
246-
247-
blogRecipeRepository.countByKeyword(keyword) >> 5
248-
249-
List<BlogRecipe> blogRecipes = [
250-
BlogRecipe.builder()
251-
.blogRecipeId(1L)
252-
.blogUrl("https://naver.com")
253-
.blogThumbnailImgUrl("")
254-
.title("제목")
255-
.description("설명")
256-
.publishedAt(LocalDate.now())
257-
.blogName("블로그명")
258-
.scrapCnt(1)
259-
.viewCnt(1)
260-
.build(),
261-
BlogRecipe.builder()
262-
.blogRecipeId(2L)
263-
.blogUrl("https://naver.com")
264-
.blogThumbnailImgUrl("")
265-
.title("제목")
266-
.description("설명")
267-
.publishedAt(LocalDate.now())
268-
.blogName("블로그명")
269-
.scrapCnt(1)
270-
.viewCnt(1)
271-
.build(),
272-
]
273-
274-
blogRecipeClientSearchService.searchNaverBlogRecipes(keyword, size) >> blogRecipes
275-
276-
List<BlogScrap> blogScraps = [
277-
BlogScrap.builder()
278-
.blogScrapId(1)
279-
.userId(user.userId)
280-
.blogRecipeId(blogRecipes.get(0).blogRecipeId)
281-
.build()
282-
]
283-
284-
blogScrapService.findByBlogRecipeIds(blogRecipes.blogRecipeId) >> blogScraps
285-
286-
when:
287-
RecipesResponse result = blogRecipeService.findBlogRecipesByKeyword(user, keyword, lastBlogRecipeId, size, sort)
288-
289-
then:
290-
result.totalCnt == 5
291-
result.recipes.recipeId == blogRecipes.blogRecipeId
292-
result.recipes.recipeName == blogRecipes.title
293-
result.recipes.introduction == blogRecipes.description
294-
result.recipes.thumbnailImgUrl == blogRecipes.blogThumbnailImgUrl
295-
result.recipes.postDate == [blogRecipes.get(0).publishedAt.format(DateTimeFormatter.ofPattern("yyyy.M.d")), blogRecipes.get(1).publishedAt.format(DateTimeFormatter.ofPattern("yyyy.M.d"))]
296-
result.recipes.isUserScrap == [true, false]
297-
result.recipes.scrapCnt == blogRecipes.scrapCnt
298-
result.recipes.viewCnt == blogRecipes.viewCnt
299-
}
300-
301233
def "스크랩한 블로그 레시피 목록 조회"() {
302234

303235
given:

src/test/groovy/com/recipe/app/src/recipe/application/youtube/YoutubeRecipeServiceTest.groovy

Lines changed: 0 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -233,74 +233,6 @@ class YoutubeRecipeServiceTest extends Specification {
233233
result.recipes.viewCnt == youtubeRecipes.viewCnt
234234
}
235235

236-
def "유튜브 레시피 검색 - 외부 API 요청"() {
237-
238-
given:
239-
User user = User.builder()
240-
.userId(1)
241-
.socialId("naver_1")
242-
.nickname("테스터1")
243-
.build()
244-
245-
String keyword = "테스트"
246-
long lastYoutubeRecipeId = 0
247-
int size = 2
248-
String sort = "newest"
249-
250-
youtubeRecipeRepository.countByKeyword(keyword) >> 5
251-
252-
List<YoutubeRecipe> youtubeRecipes = [
253-
YoutubeRecipe.builder()
254-
.youtubeRecipeId(1)
255-
.title("제목")
256-
.description("설명")
257-
.thumbnailImgUrl("http://img.jpg")
258-
.postDate(LocalDate.now())
259-
.channelName("채널명")
260-
.youtubeId("abcdef")
261-
.scrapCnt(1)
262-
.viewCnt(1)
263-
.build(),
264-
YoutubeRecipe.builder()
265-
.youtubeRecipeId(2)
266-
.title("제목")
267-
.description("설명")
268-
.thumbnailImgUrl("http://img.jpg")
269-
.postDate(LocalDate.now())
270-
.channelName("채널명")
271-
.youtubeId("abcdef")
272-
.scrapCnt(1)
273-
.viewCnt(1)
274-
.build()
275-
]
276-
277-
youtubeRecipeClientSearchService.searchYoutube(keyword, size) >> youtubeRecipes
278-
279-
List<YoutubeScrap> youtubeScraps = [
280-
YoutubeScrap.builder()
281-
.youtubeScrapId(1)
282-
.userId(user.userId)
283-
.youtubeRecipeId(youtubeRecipes.get(0).youtubeRecipeId)
284-
.build()
285-
]
286-
287-
youtubeScrapService.findByYoutubeRecipeIds(youtubeRecipes.youtubeRecipeId) >> youtubeScraps
288-
289-
when:
290-
RecipesResponse result = youtubeRecipeService.findYoutubeRecipesByKeyword(user, keyword, lastYoutubeRecipeId, size, sort)
291-
292-
then:
293-
result.totalCnt == 5
294-
result.recipes.recipeId == youtubeRecipes.youtubeRecipeId
295-
result.recipes.recipeName == youtubeRecipes.title
296-
result.recipes.introduction == youtubeRecipes.description
297-
result.recipes.thumbnailImgUrl == youtubeRecipes.thumbnailImgUrl
298-
result.recipes.postDate == [youtubeRecipes.get(0).postDate.format(DateTimeFormatter.ofPattern("yyyy.M.d")), youtubeRecipes.get(1).postDate.format(DateTimeFormatter.ofPattern("yyyy.M.d"))]
299-
result.recipes.isUserScrap == [true, false]
300-
result.recipes.scrapCnt == youtubeRecipes.scrapCnt
301-
result.recipes.viewCnt == youtubeRecipes.viewCnt
302-
}
303-
304236
def "스크랩한 유튜브 레시피 목록 조회"() {
305237

306238
given:

0 commit comments

Comments
 (0)