Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat]: survey에 북마크 취소기능 개발 #388

Merged
merged 16 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
8ba484d
feat: survey에 북마크 취소기능을 개발한다
devxb Mar 6, 2024
b9c9e1a
test: 북마크 취소 e2e 테스트의 호스트를 nalab-server로 변경한다
devxb Mar 6, 2024
e5bc334
refactor: 북마크 취소 응답으로 필요없는 필드를 삭제한다
devxb Mar 7, 2024
24e8bf1
refactor: Long타입 응답을 String으로 변경한다
devxb Mar 7, 2024
650a15f
[fix] : gallery 조회 job -> BOOKMARK 및 조회 인자 uppercase로 변경 (#392)
devxb Mar 7, 2024
9bd2b3f
refactor: 북마크 취소 api가 응답 바디를 갖지 않도록 수정한다
devxb Mar 7, 2024
a9bfa86
refactor: setBookmarkedCount를 increase, decrease로 분리한다
devxb Mar 7, 2024
071915a
[refactor] : survey bookmark api가 응답바디를 내려주지 않도록 수정 (#394)
devxb Mar 7, 2024
569ef8e
feat: survey에 북마크 취소기능을 개발한다
devxb Mar 6, 2024
3d52a4d
test: 북마크 취소 e2e 테스트의 호스트를 nalab-server로 변경한다
devxb Mar 6, 2024
08e99fb
refactor: 북마크 취소 응답으로 필요없는 필드를 삭제한다
devxb Mar 7, 2024
2e6872b
refactor: Long타입 응답을 String으로 변경한다
devxb Mar 7, 2024
a4ecfd4
refactor: 북마크 취소 api가 응답 바디를 갖지 않도록 수정한다
devxb Mar 7, 2024
9436f7a
refactor: setBookmarkedCount를 increase, decrease로 분리한다
devxb Mar 7, 2024
d839f00
test: test에서 북마크 검증 필드를 수정한다
devxb Mar 7, 2024
152bfa8
refactor: remove unused import
devxb Mar 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,7 @@ public static void assertIsSurveyDoesNotExists(ResultActions resultActions) thro
}

public static void assertIsBookmarked(ResultActions resultActions) throws Exception {
resultActions.andExpectAll(
status().isOk(),
content().contentType(MediaType.APPLICATION_JSON),
jsonPath("$.target_id").isString(),
jsonPath("$.survey_id").isString(),
jsonPath("$.nickname").isString(),
jsonPath("$.position").doesNotExist(),
jsonPath("$.image_url").doesNotExist()
);
resultActions.andExpectAll(status().isOk());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class JwtDecryptInterceptorConfigurer implements WebMvcConfigurer {
"/v1/users",
"/v1/gallerys/previews",
"/v1/surveys/*/bookmarks",
"/v1/surveys/*/bookmarks/cancels",
"/v1/gallerys/logins",
"/v1/gallerys",
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ class GalleryGetApp(
}

private fun getPage(page: Int, count: Int, orderType: String): Pageable {
return when (orderType.lowercase()) {
"update" -> PageRequest.of(page, count, Sort.by("updateOrder").descending())
"job" -> PageRequest.of(page, count, Sort.by("survey.bookmarkedCount").descending())
return when (orderType.uppercase()) {
"UPDATE" -> PageRequest.of(page, count, Sort.by("updateOrder").descending())
"BOOKMARK" -> PageRequest.of(page, count, Sort.by("survey.bookmarkedCount").descending())
else -> throw IllegalArgumentException("orderType 은 update와 bookmark중 하나여야 합니다. 현재 orderType \"$orderType\"")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ class GalleryController(
@GetMapping
@ResponseStatus(HttpStatus.OK)
fun getGalleries(
@RequestParam(name = "job", defaultValue = "all") job: String,
@RequestParam(name = "job", defaultValue = "ALL") job: String,
@RequestParam(name = "page", defaultValue = "0") page: Int,
@RequestParam(name = "count", defaultValue = "5") count: Int,
@RequestParam(name = "order-type", defaultValue = "update") orderType: String
@RequestParam(name = "order-type", defaultValue = "UPDATE") orderType: String
): GalleriesDto {
return galleryGetApp.getGalleries(job, page, count, orderType)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,13 @@ class Gallery(

fun getBookmarkedCount(): Int = survey.bookmarkedCount

fun increaseBookmarkedCount() {
fun increaseBookmarkCount() {
survey.bookmarkedCount++
}

fun decreaseBookmarkCount() {
survey.bookmarkedCount--
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,17 @@ class GalleryService(

@Transactional
fun increaseBookmarkCount(targetId: Long) {
galleryRepository.findByTargetIdOrNull(targetId)?.increaseBookmarkedCount()
galleryRepository.findByTargetIdOrNull(targetId)?.increaseBookmarkCount()
}

@Transactional
fun decreaseBookmarkCount(targetId: Long) {
galleryRepository.findByTargetIdOrNull(targetId)?.decreaseBookmarkCount()
}

fun getGalleries(job: String, pageable: Pageable): Page<Gallery> {
val jobs = when (job) {
"all" -> Job.entries.toList()
val jobs = when (job.uppercase()) {
"ALL" -> Job.entries.toList()
else -> listOf(Job.valueOf(job.uppercase()))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,38 @@ class SurveyBookmarkedListener(
) : SurveyBookmarkListenPort {

@Async
override fun listenBookmarked(targetId: Long) {
override fun increaseBookmarked(targetId: Long) {
runCatching {
galleryService.increaseBookmarkCount(targetId)
}.recoverCatching {
when (it is OptimisticLockingFailureException) {
true -> {
waitJitter()
listenBookmarked(targetId)
increaseBookmarked(targetId)
}

false -> throw it
}
}
}

@Async
override fun decreaseBookmarked(targetId: Long) {
runCatching {
galleryService.decreaseBookmarkCount(targetId)
}.recoverCatching {
when (it is OptimisticLockingFailureException) {
true -> {
waitJitter()
decreaseBookmarked(targetId)
}

false -> throw it
}
}
}


private fun waitJitter() {
Thread.sleep(Random.nextLong(500, 1000))
}
Expand Down
5 changes: 0 additions & 5 deletions support/e2e/v1_10_get_logined_gallery.hurl
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,6 @@ Authorization: {{ token_type }} {{ auth_token }}

HTTP 200
[Asserts]
header "Content-type" == "application/json"

jsonpath "$.target_id" == {{ target_id }}
jsonpath "$.survey_id" == {{ survey_id }}
jsonpath "$.nickname" == "logined_gallery"

##########

Expand Down
116 changes: 116 additions & 0 deletions support/e2e/v1_11_cancel_bookmark_survey.hurl
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
POST http://nalab-server:8080/v1/oauth/default # Default provider를 통해서 로그인 진행
{
"nickname": "cancel_bookmark_survey",
"email": "cancel_bookmark_survey@123456"
}

HTTP 200
[Asserts]
header "Content-type" == "application/json"

jsonpath "$.access_token" exists
jsonpath "$.token_type" exists

[Captures]
token_type: jsonpath "$.token_type"
auth_token: jsonpath "$.access_token"

##########

POST http://nalab-server:8080/v1/surveys # 발급받은 토큰으로 survey를 생성한다.
Authorization: {{ token_type }} {{ auth_token }}
{
"question_count": 2,
"question": [
{
"type": "choice",
"form_type": "tendency",
"title": "저는 UI, UI, GUI 중에 어떤 분야를 가장 잘하는 것 같나요?",
"choices": [
{
"content": "UI",
"order": 1
},
{
"content": "UX",
"order": 2
},
{
"content": "GUI",
"order": 3
}
],
"max_selectable_count": 1,
"order": 1
},
{
"type": "short",
"form_type": "strength",
"title": "저는 UX, UI, GUI 중에 어떤 분야에 더 강점이 있나요?",
"order": 2
}
]
}

HTTP 201
[Asserts]
header "Content-type" == "application/json"

jsonpath "$.survey_id" exists

[Captures]
survey_id: jsonpath "$.survey_id"

##########

GET http://nalab-server:8080/v1/surveys/{{ survey_id }} # 생성된 survey를 조회한다.

HTTP 200
[Asserts]
header "Content-type" == "application/json"

jsonpath "$.survey_id" exists

jsonpath "$.target.id" exists
jsonpath "$.target.nickname" == "cancel_bookmark_survey"

jsonpath "$.question_count" == 2
jsonpath "$.question.[0].question_id" exists
jsonpath "$.question.[0].type" == "choice"
jsonpath "$.question.[0].form_type" == "tendency"
jsonpath "$.question.[0].title" == "저는 UI, UI, GUI 중에 어떤 분야를 가장 잘하는 것 같나요?"
jsonpath "$.question.[0].order" == 1
jsonpath "$.question.[0].max_selectable_count" == 1
jsonpath "$.question.[0].choices.[0].choice_id" exists
jsonpath "$.question.[0].choices.[0].content" == "UI"
jsonpath "$.question.[0].choices.[0].order" == 1
jsonpath "$.question.[0].choices.[1].choice_id" exists
jsonpath "$.question.[0].choices.[1].content" == "UX"
jsonpath "$.question.[0].choices.[1].order" == 2
jsonpath "$.question.[0].choices.[2].choice_id" exists
jsonpath "$.question.[0].choices.[2].content" == "GUI"
jsonpath "$.question.[0].choices.[2].order" == 3
jsonpath "$.question.[1].question_id" exists
jsonpath "$.question.[1].type" == "short"
jsonpath "$.question.[1].form_type" == "strength"
jsonpath "$.question.[1].title" == "저는 UX, UI, GUI 중에 어떤 분야에 더 강점이 있나요?"
jsonpath "$.question.[1].order" == 2

[Captures]
target_id: jsonpath "$.target.id"

##########

POST http://nalab-server:8080/v1/surveys/{{ survey_id }}/bookmarks
Authorization: {{ token_type }} {{ auth_token }}

HTTP 200
[Asserts]

##########

POST http://nalab-server:8080/v1/surveys/{{ survey_id }}/bookmarks/cancels
Authorization: {{ token_type }} {{ auth_token }}

HTTP 200
[Asserts]
5 changes: 0 additions & 5 deletions support/e2e/v1_7_bookmark_survey.hurl
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,3 @@ Authorization: {{ token_type }} {{ auth_token }}

HTTP 200
[Asserts]
header "Content-type" == "application/json"

jsonpath "$.target_id" == {{ target_id }}
jsonpath "$.survey_id" == {{ survey_id }}
jsonpath "$.nickname" == "bookmark_survey"
5 changes: 0 additions & 5 deletions support/e2e/v1_9_register_gallery.hurl
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,6 @@ Authorization: {{ token_type }} {{ auth_token }}

HTTP 200
[Asserts]
header "Content-type" == "application/json"

jsonpath "$.target_id" == {{ target_id }}
jsonpath "$.survey_id" == {{ survey_id }}
jsonpath "$.nickname" == "register_gallery"

##########

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package me.nalab.survey.application.port.in.web.bookmark;

import me.nalab.survey.application.common.survey.dto.SurveyBookmarkDto;

public interface SurveyBookmarkUseCase {

/**
* targetId에 해당하는 유저에게 survey를 북마크합니다.
* 이미 북마크되어있다면 북마크를 취소합니다.
*/
SurveyBookmarkDto bookmark(Long targetId, Long surveyId);
void bookmark(Long targetId, Long surveyId);

/**
* targetId에 해당하는 유저에게 survey를 북마크 취소합니다. 북마크 되어있지 않다면, 아무동작도 하지 않습니다.
*/
void cancelBookmark(Long targetId, Long surveyId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@

public interface SurveyBookmarkListenPort {

void listenBookmarked(Long targetId);
void increaseBookmarked(Long targetId);

void decreaseBookmarked(Long targetId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

public interface SurveyBookmarkPort {

void bookmark(Target target);
void updateBookmark(Target target);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package me.nalab.survey.application.service.bookmark;

import lombok.RequiredArgsConstructor;
import me.nalab.survey.application.common.survey.dto.SurveyBookmarkDto;
import me.nalab.survey.application.exception.SurveyDoesNotExistException;
import me.nalab.survey.application.port.in.web.bookmark.SurveyBookmarkUseCase;
import me.nalab.survey.application.port.out.persistence.bookmark.SurveyBookmarkListenPort;
Expand All @@ -22,18 +21,31 @@ public class SurveyBookmarkService implements SurveyBookmarkUseCase {

@Override
@Transactional
public SurveyBookmarkDto bookmark(Long targetId, Long surveyId) {
public void bookmark(Long targetId, Long surveyId) {
var target = targetFindPort.getTargetById(targetId);

if (!surveyExistCheckPort.isExistSurveyBySurveyId(surveyId)) {
throw new SurveyDoesNotExistException(surveyId);
}

target.bookmark(surveyId);
surveyBookmarkPort.bookmark(target);
surveyBookmarkPort.updateBookmark(target);

surveyBookmarkListener.listenBookmarked(targetId);
surveyBookmarkListener.increaseBookmarked(targetId);
}

@Override
@Transactional
public void cancelBookmark(Long targetId, Long surveyId) {
var target = targetFindPort.getTargetById(targetId);

if (!surveyExistCheckPort.isExistSurveyBySurveyId(surveyId)) {
throw new SurveyDoesNotExistException(surveyId);
}

target.cancelBookmark(surveyId);
surveyBookmarkPort.updateBookmark(target);

return SurveyBookmarkDto.from(surveyId, target);
surveyBookmarkListener.decreaseBookmarked(targetId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.LongSupplier;
import lombok.Builder;
Expand Down Expand Up @@ -45,4 +46,11 @@ public void bookmark(Long surveyId) {
var bookmark = new SurveyBookmark(surveyId);
bookmarkedSurveys.add(bookmark);
}

public void cancelBookmark(Long surveyId) {
bookmarkedSurveys.stream()
.filter(surveyBookmark -> Objects.equals(surveyBookmark.surveyId(), surveyId))
.findFirst()
.ifPresent(bookmarkedSurveys::remove);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class SurveyBookmarkAdaptor implements SurveyBookmarkPort {
private final TargetFindRepository targetFindRepository;

@Override
public void bookmark(Target target) {
public void updateBookmark(Target target) {
var savedTarget = targetFindRepository.findById(target.getId())
.orElseThrow(() -> new TargetDoesNotExistException(target.getId()));

Expand Down
Loading
Loading