Skip to content

Commit

Permalink
Merge pull request #198 from EFUB4-Jukebox/develop
Browse files Browse the repository at this point in the history
[Deploy] 배포 v0.6.3 - SSE 알림 헤더 사용하도록 변경, 일부 API에서 handle을 사용하도록 로직 변경 등
  • Loading branch information
seohyun-lee authored Aug 17, 2024
2 parents ec396fa + e53b3ef commit 128685d
Show file tree
Hide file tree
Showing 22 changed files with 109 additions and 83 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/github-actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: CI/CD using GitHub Actions & Docker
# main, deploy 브랜치에 push하면 워크플로우 실행
on:
push:
branches: [ "main", "deploy" ]
branches: [ "main", "deploy", "test-deploy"]

jobs:
deploy:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ public class AlarmController {
private final AlarmService alarmService;

@Operation(summary = "알림 구독", description = "알림을 구독합니다.")
@GetMapping(value = "/subscribe/{memberId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE) // Content-Type 지정
public ResponseEntity<SseEmitter> subscribe(@PathVariable("memberId") final Long memberId) {
return ResponseEntity.ok(emitterService.subscribe(memberId));
@GetMapping(value = "/subscribe", produces = MediaType.TEXT_EVENT_STREAM_VALUE) // Content-Type 지정
public ResponseEntity<SseEmitter> subscribe() {
return ResponseEntity.ok(emitterService.subscribe());
}

@Operation(summary = "알림 목록 조회 및 읽음 처리", description = "알림 목록을 조회하고 읽음 처리합니다.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ public record AlarmUnitDto(
Boolean isRead,
String message,
LocalDateTime createdTime,
Long senderId
String handle
) {
public static AlarmUnitDto from(Alarm alarm, String message) {
return new AlarmUnitDto(
alarm.getIsRead(),
message,
alarm.getCreatedTime(),
alarm.getSender().getMemberId()
alarm.getSender().getHandle()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@ public class EmitterService {
private final AlarmRepository alarmRepository;
private final MemberService memberService;

private static final Long DEFAULT_TIMEOUT = 1L * 60 * 1000; // 1분
private static final Long DEFAULT_TIMEOUT = 5L * 60 * 1000; // 5분

public SseEmitter subscribe(Long memberId) {
SseEmitter emitter = registerEmitter(memberId);
sendToClientIfNewAlarmExists(memberId);
public SseEmitter subscribe() {
Member member = memberService.getCurrentMember();
SseEmitter emitter = registerEmitter(member.getMemberId());
sendToClientIfNewAlarmExists(member);
return emitter;
}

private void sendToClientIfNewAlarmExists(Long memberId) {
Member member = memberService.getActiveMemberById(memberId);
private void sendToClientIfNewAlarmExists(Member member) {
Boolean isMissedAlarms = alarmRepository.existsByReceiverAndIsReadFalse(member);
if (isMissedAlarms.equals(true)) {
sendToClient(member.getMemberId(), AlarmDefaultDataDto.from(true), "new sse alarm exists");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
public record FollowListResponseDto(
Boolean isMe,
String handle,
List<FollowDto> followingList
List<FollowUnitDto> followList
) {
public static FollowListResponseDto from(Boolean isMe, String handle, List<FollowDto> followDtoList) {
public static FollowListResponseDto from(Boolean isMe, String handle, List<FollowUnitDto> followDtoList) {
return new FollowListResponseDto(isMe, handle, followDtoList);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
import sws.songpin.domain.member.entity.Member;
import sws.songpin.domain.member.entity.ProfileImg;

public record FollowDto(
public record FollowUnitDto(
Long memberId,
ProfileImg profileImg,
String nickname,
String handle,
Boolean isFollowing
) {
public static FollowDto from (Member member, Boolean isFollowing) {
return new FollowDto(
public static FollowUnitDto from (Member member, Boolean isFollowing) {
return new FollowUnitDto(
member.getMemberId(),
member.getProfileImg(),
member.getNickname(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import org.springframework.transaction.annotation.Transactional;
import sws.songpin.domain.alarm.service.AlarmService;
import sws.songpin.domain.follow.dto.request.FollowRequestDto;
import sws.songpin.domain.follow.dto.response.FollowDto;
import sws.songpin.domain.follow.dto.response.FollowUnitDto;
import sws.songpin.domain.follow.dto.response.FollowListResponseDto;
import sws.songpin.domain.follow.entity.Follow;
import sws.songpin.domain.follow.repository.FollowRepository;
Expand Down Expand Up @@ -37,7 +37,7 @@ public boolean createOrDeleteFollow(FollowRequestDto requestDto) {
}

Optional<Follow> followOptional = followRepository.findByFollowerAndFollowing(currentMember, targetMember);
if (checkIfFollowExists(targetMember, currentMember)) { // 팔로우가 존재하면 삭제
if (followOptional.isPresent()) { // 팔로우가 존재하면 삭제
followRepository.delete(followOptional.get());
return false;
} else { // 팔로우 추가
Expand Down Expand Up @@ -86,21 +86,21 @@ public Boolean checkIfFollowExists(Member follower, Member following) {
}

// 특정 사용자의 팔로잉/팔로워 목록 조회
public FollowListResponseDto getFollowList(Long memberId, boolean isFollowingList) {
Member targetMember = memberService.getActiveMemberById(memberId);
public FollowListResponseDto getFollowList(String handle, boolean isFollowingList) {
Member targetMember = memberService.getActiveMemberByHandle(handle);
Member currentMember = memberService.getCurrentMember();
Map<Member, Long> currentMemberFollowingCache = getMemberFollowingCache(currentMember);
List<Follow> followList = isFollowingList ? findAllFollowingsOfMember(targetMember) : findAllFollowersOfMember(targetMember);

List<FollowDto> followDtoList = followList.stream()
List<FollowUnitDto> followDtoList = followList.stream()
.map(follow -> {
Member member = isFollowingList ? follow.getFollowing() : follow.getFollower();
// isFollowing: 로그인한 사용자의 member 팔로잉 여부 (null: 자신)
Boolean isFollowing = member.equals(currentMember) ? null : currentMemberFollowingCache.get(member) != null;
return FollowDto.from(member, isFollowing);
return FollowUnitDto.from(member, isFollowing);
})
// 우선순위대로 정렬 (null > true > false)
.sorted(Comparator.comparing(FollowDto::isFollowing, Comparator.nullsFirst(Comparator.reverseOrder())))
.sorted(Comparator.comparing(FollowUnitDto::isFollowing, Comparator.nullsFirst(Comparator.reverseOrder())))
.collect(Collectors.toList());
return FollowListResponseDto.from(targetMember.equals(currentMember), targetMember.getHandle(), followDtoList);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,32 +35,32 @@ public ResponseEntity<?> searchMembers(@RequestParam("keyword") final String key
return ResponseEntity.ok().body(memberService.searchMembers(keyword, pageable));
}
@Operation(summary = "타 유저 정보 조회", description = "memberId으로 해당 유저의 프로필 이미지, 닉네임, 아이디 정보 조회")
@GetMapping("/{memberId}")
public ResponseEntity<?> memberDetails(@PathVariable("memberId") final Long memberId){
return ResponseEntity.ok(profileService.getMemberProfile(memberId));
@GetMapping("/{handle}")
public ResponseEntity<?> memberDetails(@PathVariable final String handle){
return ResponseEntity.ok(profileService.getMemberProfile(handle));
}

@Operation(summary = "타 유저 플레이리스트 목록 조회", description = "타 유저 페이지에서 플레이리스트 목록 조회")
@GetMapping("/{memberId}/playlists")
public ResponseEntity<?> getAllPlaylists(@PathVariable("memberId") final Long memberId){
return ResponseEntity.ok(playlistService.getMemberPlaylists(memberId));
@GetMapping("/{handle}/playlists")
public ResponseEntity<?> getAllPlaylists(@PathVariable final String handle){
return ResponseEntity.ok(playlistService.getMemberPlaylists(handle));
}

@Operation(summary = "타 유저의 핀 피드 조회", description = "타 유저의 핀 피드를 조회합니다.")
@GetMapping("/{memberId}/feed")
public ResponseEntity<?> getMemberFeedPins(@PathVariable("memberId") Long memberId, @PageableDefault(size = 20) Pageable pageable) {
return ResponseEntity.ok(pinService.getMemberPinFeed(memberId, pageable));
@GetMapping("/{handle}/feed")
public ResponseEntity<?> getMemberFeedPins(@PathVariable final String handle, @PageableDefault(size = 20) Pageable pageable) {
return ResponseEntity.ok(pinService.getMemberPinFeed(handle, pageable));
}

@Operation(summary = "유저의 팔로잉 목록 조회", description = "유저의 팔로잉 목록을 불러옵니다.")
@GetMapping("/{memberId}/followings")
public ResponseEntity<?> followingList(@PathVariable final Long memberId) {
return ResponseEntity.ok(followService.getFollowList(memberId, true));
@GetMapping("/{handle}/followings")
public ResponseEntity<?> followingList(@PathVariable final String handle) {
return ResponseEntity.ok(followService.getFollowList(handle, true));
}

@Operation(summary = "유저의 팔로워 목록 조회", description = "유저의 팔로워 목록을 불러옵니다.")
@GetMapping("/{memberId}/followers")
public ResponseEntity<?> followerList(@PathVariable final Long memberId) {
return ResponseEntity.ok(followService.getFollowList(memberId, false));
@GetMapping("/{handle}/followers")
public ResponseEntity<?> followerList(@PathVariable final String handle) {
return ResponseEntity.ok(followService.getFollowList(handle, false));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import sws.songpin.domain.member.entity.ProfileImg;

public record MemberProfileResponseDto(
Long memberId,
ProfileImg profileImg,
String nickname,
String handle,
Expand All @@ -13,6 +14,6 @@ public record MemberProfileResponseDto(
Boolean isFollower
) {
public static MemberProfileResponseDto from(Member member, long followerCount, long followingCount, Boolean isFollowing, Boolean isFollower){
return new MemberProfileResponseDto(member.getProfileImg(), member.getNickname(), member.getHandle(), followerCount, followingCount, isFollowing, isFollower);
return new MemberProfileResponseDto(member.getMemberId(), member.getProfileImg(), member.getNickname(), member.getHandle(), followerCount, followingCount, isFollowing, isFollower);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

public interface MemberRepository extends JpaRepository<Member,Long> {
Optional<Member> findByEmail(String email);
Optional<Member> findByHandle(String handle);
boolean existsByHandle(String handle);
boolean existsByEmail(String email);

// 유저 검색
@Query("SELECT m FROM Member m WHERE (m.handle LIKE %:keyword% OR m.nickname LIKE %:keyword%) AND m.status <> 'DELETED'")
Expand Down
22 changes: 11 additions & 11 deletions src/main/java/sws/songpin/domain/member/service/MemberService.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,30 +59,30 @@ public Member getCurrentMemberOrNull() {
}
}

@Transactional(readOnly = true)
public Member getMemberById(Long memberId){
return memberRepository.findById(memberId)
.orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND));
}

@Transactional(readOnly = true)
public Member getActiveMemberById(Long memberId){
Member member = getMemberById(memberId);
Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND));
if (member.getStatus().equals(Status.DELETED)) {
throw new CustomException(ErrorCode.MEMBER_STATUS_DELETED);
}
return member;
}

@Transactional(readOnly = true)
public Member getMemberByEmail(String email){
return memberRepository.findByEmail(email)
.orElseThrow(()-> new CustomException(ErrorCode.MEMBER_NOT_FOUND));
public Member getActiveMemberByHandle(String handle){
Member member = memberRepository.findByHandle(handle)
.orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND));
if (member.getStatus().equals(Status.DELETED)) {
throw new CustomException(ErrorCode.MEMBER_STATUS_DELETED);
}
return member;
}

@Transactional(readOnly = true)
public Member getActiveMemberByEmail(String email) {
Member member = getMemberByEmail(email);
Member member = memberRepository.findByEmail(email)
.orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND));
if (member.getStatus().equals(Status.DELETED)) {
throw new CustomException(ErrorCode.MEMBER_STATUS_DELETED);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ public class ProfileService {
private final PlaylistService playlistService;

@Transactional(readOnly = true)
public MemberProfileResponseDto getMemberProfile(Long memberId){
Member member = memberService.getActiveMemberById(memberId);
public MemberProfileResponseDto getMemberProfile(String handle){
Member member = memberService.getActiveMemberByHandle(handle);
Member currentMember = memberService.getCurrentMember();

//조회하려는 회원이 본인인 경우 예외 처리
Expand Down Expand Up @@ -100,6 +100,7 @@ public void deactivateProfile(ProfileDeactivateRequestDto requestDto){

//handle 랜덤값 생성
String handle = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 12);

//Status, Nickname, Handle 변경
member.deactivate(handle);
memberService.saveMember(member);
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/sws/songpin/domain/pin/service/PinService.java
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,9 @@ public SongDetailsPinListResponseDto getPinsForSong(Long songId, boolean onlyMyP

// 타 유저 핀피드 조회
@Transactional(readOnly = true)
public PinFeedListResponseDto getMemberPinFeed(Long memberId, Pageable pageable) {
Member targetMember = memberService.getMemberById(memberId);
Page<Object[]> pinFeedPage = pinRepository.findPinFeed(targetMember, pageable);
public PinFeedListResponseDto getMemberPinFeed(String handle, Pageable pageable) {
Member member = memberService.getActiveMemberByHandle(handle);
Page<Object[]> pinFeedPage = pinRepository.findPinFeed(member, pageable);
return getPinFeedResponse(pinFeedPage, false);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ public ResponseEntity<?> getMapPlacesWithinBoundsForCustomPeriod(@RequestBody @V
return ResponseEntity.ok(responseDto);
}

@Operation(summary = "유저가 핀을 등록한 장소 좌표들 가져오기", description = "유저가 핀을 등록한 장소 좌표들을 가져옵니다. (공개여부 무관)")
@GetMapping("/members/{memberId}")
public ResponseEntity<?> getMapPlacesOfMember(@PathVariable final Long memberId) {
MapPlaceFetchResponseDto responseDto = mapService.getMapPlacesOfMember(memberId);
@Operation(summary = "유저가 핀을 등록한 장소 좌표들 가져오기", description = "유저가 핀을 등록한 장소 좌표들을 가져옵니다.")
@GetMapping("/members/{handle}")
public ResponseEntity<?> getMapPlacesOfMember(@PathVariable final String handle) {
MapPlaceFetchResponseDto responseDto = mapService.getMapPlacesOfMember(handle);
return ResponseEntity.ok(responseDto);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sws.songpin.domain.genre.entity.GenreName;
import sws.songpin.domain.member.entity.Member;
import sws.songpin.domain.member.service.MemberService;
import sws.songpin.domain.place.dto.request.MapBoundCoordsDto;
import sws.songpin.domain.place.dto.request.MapFetchEntirePeriodRequestDto;
import sws.songpin.domain.place.dto.request.MapFetchCustomPeriodRequestDto;
Expand All @@ -28,6 +30,7 @@
public class MapService {

private final MapPlaceRepository mapPlaceRepository;
private final MemberService memberService;

// 장소 좌표들 가져오기-전체 기간 & 장르 필터링
public MapPlaceFetchResponseDto getMapPlacesWithinBoundsByEntirePeriod(MapFetchEntirePeriodRequestDto requestDto) {
Expand Down Expand Up @@ -80,7 +83,8 @@ private List<GenreName> getSelectedGenreNames(List<GenreName> genreNameFilters)

//// 유저로 필터링
// 유저가 핀을 등록한 장소 좌표들 가져오기
public MapPlaceFetchResponseDto getMapPlacesOfMember(Long memberId) {
public MapPlaceFetchResponseDto getMapPlacesOfMember(String handle) {
Long memberId = memberService.getActiveMemberByHandle(handle).getMemberId();
Pageable pageable = getCustomPageableForMap();
Slice<MapPlaceProjectionDto> dtoSlice = mapPlaceRepository.findPlacesWithLatestPinsByCreator(memberId, pageable);
return MapPlaceFetchResponseDto.from(dtoSlice);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
public record PlaylistDetailsResponseDto(
Boolean isMine,
String playlistName,
Long creatorId,
String creatorHandle,
String creatorNickname,
int pinCount,
LocalDate updatedDate,
Expand All @@ -22,7 +22,7 @@ public static PlaylistDetailsResponseDto from(Playlist playlist, List<String> im
return new PlaylistDetailsResponseDto(
isMine,
playlist.getPlaylistName(),
playlist.getCreator().getMemberId(),
playlist.getCreator().getHandle(),
playlist.getCreator().getNickname(),
pinList.size(),
playlist.getModifiedTime().toLocalDate(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ public PlaylistListResponseDto getMemberPlaylists(){

// 타 유저 플레이리스트 조회
@Transactional(readOnly = true)
public PlaylistListResponseDto getMemberPlaylists(Long memberId) {
Member creator = memberService.getMemberById(memberId);
public PlaylistListResponseDto getMemberPlaylists(String handle) {
Member creator = memberService.getActiveMemberByHandle(handle);
Member currentMember = memberService.getCurrentMember();
return getMemberPlaylists(creator, currentMember);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

public record SongDetailsPinDto(
Long pinId,
Long creatorId,
String creatorHandle,
String creatorNickname,
Status creatorStatus,
LocalDate listenedDate,
Expand All @@ -22,7 +22,7 @@ public record SongDetailsPinDto(
public static SongDetailsPinDto from(Pin pin, String memo, Boolean isMine) {
return new SongDetailsPinDto(
pin.getPinId(),
pin.getCreator().getMemberId(),
pin.getCreator().getHandle(),
pin.getCreator().getNickname(),
pin.getCreator().getStatus(),
pin.getListenedDate(),
Expand Down
Loading

0 comments on commit 128685d

Please sign in to comment.