Skip to content

Commit

Permalink
refactor: 행사 참여자 전체 수정 로직 리펙토링 (#644)
Browse files Browse the repository at this point in the history
* refactor: 행사 참여자 전체 수정 로직 리펙토링

* refactor: 메소드 분리

* refactor: UpdatedMembers 로 변경

* refactor: CurrentMember 쿼리 변경

* refactor: 변수명 변경

* test: 예외 메시지 변경

* style: 메소드 명 변경

* refactor: 배치 사이즈 조절

* refactor: Set 으로 변경

* refactor: 메소드 순서 변경

* refactor: 필요없는 객체 제거

* docs: 운영 배포 워크플로 수정

* docs: 도커 이미지 이름 변경
  • Loading branch information
Arachneee authored Sep 26, 2024
1 parent 8605c78 commit 89ed425
Show file tree
Hide file tree
Showing 10 changed files with 251 additions and 131 deletions.
25 changes: 22 additions & 3 deletions .github/workflows/backend-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ jobs:
docker buildx build --platform linux/arm64 -t \
${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_PROD }} --push .
deploy:
deploy-prod-1:
needs: build
runs-on: [ self-hosted, backend-prod ]
runs-on: [ self-hosted, backend-prod-1 ]
steps:
- name: Docker remove
run: |
Expand All @@ -71,4 +71,23 @@ jobs:
run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_PROD }}

- name: Docker run
run: sudo docker run -d -p 8080:8080 -e SPRING_PROFILES_ACTIVE=prod -v log-volume:/app/logs --name haengdong-backend ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_PROD }}
run: sudo docker run -d -p 80:8080 -e SPRING_PROFILES_ACTIVE=prod -v log-volume:/app/logs --name haengdong-backend ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_DEV }}

deploy-prod-2:
needs: build
runs-on: [ self-hosted, backend-prod-2 ]
steps:
- name: Docker remove
run: |
CONTAINER_IDS=$(sudo docker ps -qa)
if [ -n "$CONTAINER_IDS" ]; then
sudo docker rm -f $CONTAINER_IDS
else
echo "No running containers found."
fi
- name: Docker Image pull
run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_PROD }}

- name: Docker run
run: sudo docker run -d -p 80:8080 -e SPRING_PROFILES_ACTIVE=prod -v log-volume:/app/logs --name haengdong-backend ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_DEV }}
117 changes: 26 additions & 91 deletions server/src/main/java/server/haengdong/application/MemberService.java
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
package server.haengdong.application;


import static java.util.stream.Collectors.toMap;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import server.haengdong.application.request.MemberSaveAppRequest;
import server.haengdong.application.request.MemberUpdateAppRequest;
import server.haengdong.application.request.MembersSaveAppRequest;
import server.haengdong.application.request.MembersUpdateAppRequest;
import server.haengdong.application.response.MemberAppResponse;
import server.haengdong.application.response.MembersDepositAppResponse;
import server.haengdong.application.response.MembersSaveAppResponse;
import server.haengdong.domain.bill.Bill;
import server.haengdong.domain.bill.BillDetailRepository;
import server.haengdong.domain.bill.BillRepository;
import server.haengdong.domain.event.Event;
import server.haengdong.domain.event.EventRepository;
import server.haengdong.domain.member.Member;
import server.haengdong.domain.member.MemberRepository;
import server.haengdong.domain.member.UpdatedMembers;
import server.haengdong.exception.HaengdongErrorCode;
import server.haengdong.exception.HaengdongException;

Expand All @@ -35,7 +30,6 @@ public class MemberService {
private final MemberRepository memberRepository;
private final EventRepository eventRepository;
private final BillRepository billRepository;
private final BillDetailRepository billDetailRepository;

@Transactional
public MembersSaveAppResponse saveMembers(String token, MembersSaveAppRequest request) {
Expand All @@ -54,6 +48,21 @@ public MembersSaveAppResponse saveMembers(String token, MembersSaveAppRequest re
return MembersSaveAppResponse.of(savedMembers);
}

private void validateMemberSave(List<String> memberNames, Event event) {
Set<String> uniqueMemberNames = Set.copyOf(memberNames);
if (memberNames.size() != uniqueMemberNames.size()) {
throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_DUPLICATE, memberNames);
}
if (isDuplicatedMemberNames(uniqueMemberNames, event)) {
throw new HaengdongException(HaengdongErrorCode.MEMBER_ALREADY_EXIST);
}
}

private boolean isDuplicatedMemberNames(Set<String> uniqueMemberNames, Event event) {
return memberRepository.findAllByEvent(event).stream()
.anyMatch(member -> uniqueMemberNames.contains(member.getName()));
}

public List<MemberAppResponse> getCurrentMembers(String token) {
Event event = getEvent(token);

Expand All @@ -65,16 +74,6 @@ public List<MemberAppResponse> getCurrentMembers(String token) {
.toList();
}

private void validateMemberSave(List<String> memberNames, Event event) {
if (memberNamesDuplicated(memberNames)) {
throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_DUPLICATE, memberNames);
}
if (memberRepository.findAllByEvent(event).stream()
.anyMatch(member -> memberNames.contains(member.getName()))) {
throw new HaengdongException(HaengdongErrorCode.MEMBER_ALREADY_EXIST);
}
}

public MembersDepositAppResponse findAllMembers(String token) {
Event event = getEvent(token);

Expand All @@ -86,80 +85,11 @@ public MembersDepositAppResponse findAllMembers(String token) {
@Transactional
public void updateMembers(String token, MembersUpdateAppRequest request) {
Event event = getEvent(token);
validateMemberUpdate(request);
UpdatedMembers updatedMembers = new UpdatedMembers(request.toMembers(event));
List<Member> originMembers = memberRepository.findAllByEvent(event);

List<Member> updatedMembers = request.members().stream()
.map(memberRequest -> memberRequest.toMember(event))
.toList();
List<Member> eventMembers = memberRepository.findAllByEvent(event);

validateUpdatedMembersExist(eventMembers, updatedMembers);
validateUpdatedNamesUnique(eventMembers, updatedMembers);
memberRepository.saveAll(updatedMembers);
}

private Event getEvent(String token) {
return eventRepository.findByToken(token)
.orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND));
}

private void validateMemberUpdate(MembersUpdateAppRequest request) {
validateChangedNameUnique(request.members());
validateMemberUnique(request.members());
}

private void validateChangedNameUnique(List<MemberUpdateAppRequest> members) {
List<String> memberNames = members.stream()
.map(MemberUpdateAppRequest::name)
.toList();
if (memberNamesDuplicated(memberNames)) {
throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_CHANGE_DUPLICATE);
}
}

private boolean memberNamesDuplicated(List<String> memberNames) {
return memberNames.size() != Set.copyOf(memberNames).size();
}

private void validateMemberUnique(List<MemberUpdateAppRequest> members) {
List<Long> memberIds = members.stream()
.map(MemberUpdateAppRequest::id)
.distinct()
.toList();
if (members.size() != memberIds.size()) {
throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_CHANGE_DUPLICATE);
}
}

private void validateUpdatedMembersExist(List<Member> eventMembers, List<Member> updatedMembers) {
if (updatedMembers.size() != eventMembers.size()) {
throw new HaengdongException(HaengdongErrorCode.MEMBER_UPDATE_MISMATCH);
}
Set<Member> members = new HashSet<>(eventMembers);

if (!members.containsAll(updatedMembers)) {
throw new HaengdongException(HaengdongErrorCode.MEMBER_UPDATE_MISMATCH);
}
}

private void validateUpdatedNamesUnique(List<Member> eventMembers, List<Member> updatedMembers) {
Map<Long, String> eventMemberNames = eventMembers.stream()
.collect(toMap(Member::getId, Member::getName));
Set<String> existNames = new HashSet<>(eventMemberNames.values());

boolean memberNameDuplicated = updatedMembers.stream()
.filter(updatedMember -> isMemberNameUpdated(eventMemberNames, updatedMember))
.map(Member::getName)
.anyMatch(existNames::contains);

if (memberNameDuplicated) {
throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_DUPLICATE);
}
}

private boolean isMemberNameUpdated(Map<Long, String> eventMemberNames, Member updatedMember) {
String prevMemberName = eventMemberNames.get(updatedMember.getId());
return !updatedMember.hasName(prevMemberName);
updatedMembers.validateUpdatable(originMembers);
memberRepository.saveAll(updatedMembers.getMembers());
}

@Transactional
Expand All @@ -177,7 +107,12 @@ private void deleteMember(String token, Member member) {
billRepository.findAllByEvent(event).stream()
.filter(bill -> bill.containMember(member))
.forEach(bill -> bill.removeMemberBillDetail(member));
billDetailRepository.deleteAllByMember(member);
billRepository.flush();
memberRepository.delete(member);
}

private Event getEvent(String token) {
return eventRepository.findByToken(token)
.orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
package server.haengdong.application.request;

import java.util.List;
import server.haengdong.domain.event.Event;
import server.haengdong.domain.member.Member;

public record MembersUpdateAppRequest(List<MemberUpdateAppRequest> members) {

public List<Member> toMembers(Event event) {
return members.stream()
.map(memberRequest -> memberRequest.toMember(event))
.toList();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,5 @@ public interface BillRepository extends JpaRepository<Bill, Long> {
""")
List<Bill> findAllByEvent(Event event);

@Query("""
select b
from Bill b
join fetch b.billDetails bd
join fetch bd.member
where b.event = :event
order by b.id desc
limit 1
""")
Optional<Bill> findFirstByEventOrderByIdDesc(Event event);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package server.haengdong.domain.member;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import server.haengdong.exception.HaengdongErrorCode;
import server.haengdong.exception.HaengdongException;

public class UpdatedMembers {

private final Set<Member> members;

public UpdatedMembers(List<Member> members) {
validateMemberUnique(members);
validateNameUnique(members);
this.members = new HashSet<>(members);
}

private void validateMemberUnique(List<Member> members) {
if (members.size() != Set.copyOf(members).size()) {
throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_CHANGE_DUPLICATE);
}
}

private void validateNameUnique(List<Member> members) {
Set<String> uniqueNames = members.stream()
.map(Member::getName)
.collect(Collectors.toSet());
if (members.size() != uniqueNames.size()) {
throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_CHANGE_DUPLICATE);
}
}

public void validateUpdatable(List<Member> originMembers) {
Set<Member> uniqueMembers = Set.copyOf(originMembers);
validateUpdatedMembersExist(uniqueMembers);
validateUpdatedNamesUnique(uniqueMembers);
}

private void validateUpdatedMembersExist(Set<Member> originMembers) {
if (!this.members.equals(originMembers)) {
throw new HaengdongException(HaengdongErrorCode.MEMBER_UPDATE_MISMATCH);
}
}

private void validateUpdatedNamesUnique(Set<Member> originMembers) {
boolean duplicated = originMembers.stream()
.anyMatch(this::isMemberNameUpdated);

if (duplicated) {
throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_DUPLICATE);
}
}

private boolean isMemberNameUpdated(Member originMembers) {
return this.members.stream()
.filter(member -> !member.getId().equals(originMembers.getId()))
.anyMatch(member -> member.hasName(originMembers.getName()));
}

public List<Member> getMembers() {
return members.stream().toList();
}
}


1 change: 1 addition & 0 deletions server/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ spring:
ddl-auto: create
properties:
hibernate:
default_batch_fetch_size: 30
format_sql: true
jdbc.time_zone: Asia/Seoul
show-sql: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import server.haengdong.application.response.StepAppResponse;
import server.haengdong.domain.bill.Bill;
import server.haengdong.domain.bill.BillDetail;
import server.haengdong.domain.bill.BillDetailRepository;
import server.haengdong.domain.bill.BillRepository;
import server.haengdong.domain.event.Event;
import server.haengdong.domain.event.EventRepository;
Expand All @@ -40,9 +39,6 @@ class BillServiceTest extends ServiceTestSupport {
@Autowired
private BillRepository billRepository;

@Autowired
private BillDetailRepository billDetailRepository;

@Autowired
private MemberRepository memberRepository;

Expand Down
Loading

0 comments on commit 89ed425

Please sign in to comment.