Skip to content

Commit 03a0a2d

Browse files
authored
Merge pull request #238 from dnd-side-project/dev
feat(Playlist): ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ ๋กœ์ง ๋ณ€๊ฒฝ
2 parents f454e83 + 820fc13 commit 03a0a2d

File tree

9 files changed

+312
-35
lines changed

9 files changed

+312
-35
lines changed

โ€Žcommon/src/main/java/com/example/common/error/code/PlaylistErrorCode.javaโ€Ž

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
public enum PlaylistErrorCode implements ErrorCode {
66

7-
PLAYLIST_NOT_FOUND(HttpStatus.NOT_FOUND, "PLAYLIST-404", "ํ•ด๋‹น ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
7+
PLAYLIST_NOT_FOUND(HttpStatus.NOT_FOUND, "PLAYLIST-404", "ํ•ด๋‹น ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."),
8+
PLAYLIST_DRAFT_ERROR(HttpStatus.CONFLICT, "PLAYLIST-409", "์ž„์‹œ ์ €์žฅ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๊ฑฐ๋‚˜ ๋งŒ๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.");
89

910
private final HttpStatus status;
1011
private final String code;

โ€Žmain-server/src/main/java/com/example/demo/domain/playlist/controller/PlaylistController.javaโ€Ž

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
import com.example.demo.domain.playlist.dto.EditFinalPlaylistRequest;
44
import com.example.demo.domain.playlist.dto.FinalPlaylistRequest;
5+
import com.example.demo.domain.playlist.dto.PlaylistDraft;
56
import com.example.demo.domain.playlist.dto.playlistdto.MainPlaylistDetailResponse;
6-
import com.example.demo.domain.playlist.dto.playlistdto.PlaylistCreateRequest;
7+
import com.example.demo.domain.playlist.dto.playlistdto.SavePlaylistRequest;
78
import com.example.demo.domain.playlist.dto.playlistdto.PlaylistWithSongsResponse;
89
import com.example.demo.domain.playlist.service.PlaylistService;
910
import com.example.demo.global.security.filter.CustomUserDetails;
@@ -21,8 +22,6 @@
2122
import org.springframework.security.core.annotation.AuthenticationPrincipal;
2223
import org.springframework.web.bind.annotation.*;
2324

24-
import java.util.Arrays;
25-
2625

2726
@Slf4j
2827
@RestController
@@ -82,9 +81,9 @@ public ResponseEntity<MainPlaylistDetailResponse> getPlaylistDetail(
8281
public ResponseEntity<Void> saveTempPlaylist(
8382
@io.swagger.v3.oas.annotations.parameters.RequestBody(
8483
required = true,
85-
content = @Content(schema = @Schema(implementation = PlaylistCreateRequest.class))
84+
content = @Content(schema = @Schema(implementation = SavePlaylistRequest.class))
8685
)
87-
@RequestBody @Valid PlaylistCreateRequest request,
86+
@RequestBody @Valid SavePlaylistRequest request,
8887
HttpSession session
8988
) {
9089
log.info("[/temp] SESSION ID = {}", session.getId());
@@ -94,6 +93,65 @@ public ResponseEntity<Void> saveTempPlaylist(
9493
return ResponseEntity.ok().build();
9594
}
9695

96+
@Operation(
97+
summary = "ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ ์ž„์‹œ ์ €์žฅ",
98+
description = "ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๋ฅผ ์ž„์‹œ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค"
99+
)
100+
@ApiResponse(responseCode = "200", description = "์ž„์‹œ ์ €์žฅ ์™„๋ฃŒ")
101+
@PostMapping("/v2/temp")
102+
public ResponseEntity<String> createDraftPlaylist(
103+
@io.swagger.v3.oas.annotations.parameters.RequestBody(
104+
required = true,
105+
content = @Content(schema = @Schema(implementation = PlaylistDraft.class))
106+
)
107+
@RequestBody @Valid PlaylistDraft playlistDraft
108+
) {
109+
String draftId = playlistService.saveDraftPlaylist(playlistDraft);
110+
return ResponseEntity.ok(draftId);
111+
}
112+
113+
@Operation(
114+
summary = "ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ ์ €์žฅ",
115+
description = "ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๋ฅผ ์ตœ์ข… ์ €์žฅํ•ฉ๋‹ˆ๋‹ค."
116+
)
117+
@ApiResponse(
118+
responseCode = "200",
119+
description = "์ƒ์„ฑ๋œ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ ์ƒ์„ธ",
120+
content = @Content(schema = @Schema(implementation = PlaylistWithSongsResponse.class))
121+
)
122+
@ApiResponse(responseCode = "409", description = "์ž„์‹œ ์ €์žฅ๋ณธ ์—†์Œ")
123+
@PostMapping("/v2/final/{draftId}")
124+
public ResponseEntity<PlaylistWithSongsResponse> saveDraftPlaylist(
125+
@Parameter(hidden = true)
126+
@AuthenticationPrincipal CustomUserDetails user,
127+
@PathVariable String draftId
128+
) {
129+
PlaylistWithSongsResponse response = playlistService.saveFinalPlaylist(user.getId(), draftId);
130+
return ResponseEntity.ok(response);
131+
}
132+
133+
@Operation(
134+
summary = "ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ ์ˆ˜์ • ์ €์žฅ",
135+
description = "์„ธ์…˜์— ์ €์žฅ๋œ ์ž„์‹œ๋ณธ๊ณผ CD ์š”์ฒญ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค"
136+
)
137+
@ApiResponse(
138+
responseCode = "200",
139+
description = "์ƒ์„ฑ๋œ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ ์ƒ์„ธ",
140+
content = @Content(schema = @Schema(implementation = PlaylistWithSongsResponse.class))
141+
)
142+
@ApiResponse(responseCode = "409", description = "์ž„์‹œ ์ €์žฅ๋ณธ ์—†์Œ")
143+
@PatchMapping("/v2/final/playlist/{playlistId}/draft/{draftId}")
144+
public ResponseEntity<PlaylistWithSongsResponse> editFinalPlaylist(
145+
@Parameter(hidden = true)
146+
@AuthenticationPrincipal CustomUserDetails user,
147+
@PathVariable Long playlistId, @PathVariable String draftId
148+
) {
149+
PlaylistWithSongsResponse response = playlistService.editFinalPlaylist(user.getId(),
150+
playlistId, draftId);
151+
152+
return ResponseEntity.ok(response);
153+
}
154+
97155
@Operation(
98156
summary = "ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ(์„ธ์…˜ ์ž„์‹œ๋ณธ ์‚ฌ์šฉ + Cd ์š”์ฒญ)",
99157
description = "์„ธ์…˜์— ์ €์žฅ๋œ ์ž„์‹œ๋ณธ๊ณผ CD ์š”์ฒญ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์ œ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค."
@@ -113,12 +171,12 @@ public ResponseEntity<PlaylistWithSongsResponse> savePlaylist(
113171
) {
114172
log.info("[/final] SESSION ID = {}", session.getId());
115173

116-
PlaylistCreateRequest request = (PlaylistCreateRequest) session.getAttribute("tempPlaylist");
174+
SavePlaylistRequest request = (SavePlaylistRequest) session.getAttribute("tempPlaylist");
117175
if (request == null) {
118176
throw new IllegalStateException("์„ธ์…˜์— ์ž„์‹œ ์ €์žฅ๋œ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.");
119177
}
120178

121-
PlaylistWithSongsResponse response = playlistService.saveFinalPlaylistWithSongsAndCd(user.getId(), request, finalPlaylistRequest.saveCdRequest().cdItems());
179+
PlaylistWithSongsResponse response = playlistService.saveFinalPlaylistWithSongsAndCd(user.getId(), request, finalPlaylistRequest);
122180

123181
session.removeAttribute("tempPlaylist");
124182
return ResponseEntity.ok(response);
@@ -141,13 +199,13 @@ public ResponseEntity<PlaylistWithSongsResponse> editPlaylist(
141199
@RequestBody EditFinalPlaylistRequest editFinalPlaylistRequest,
142200
HttpSession session
143201
) {
144-
PlaylistCreateRequest request = (PlaylistCreateRequest) session.getAttribute("tempPlaylist");
202+
SavePlaylistRequest request = (SavePlaylistRequest) session.getAttribute("tempPlaylist");
145203
if (request == null) {
146204
throw new IllegalStateException("์„ธ์…˜์— ์ž„์‹œ ์ €์žฅ๋œ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.");
147205
}
148206

149-
PlaylistWithSongsResponse response = playlistService.editFinalPlaylistWithSongsAndCd(user.getId(), editFinalPlaylistRequest.playlistId(),
150-
request, editFinalPlaylistRequest.saveCdRequest().cdItems());
207+
PlaylistWithSongsResponse response = playlistService.editFinalPlaylistWithSongsAndCd(user.getId(),
208+
request, editFinalPlaylistRequest);
151209

152210
session.removeAttribute("tempPlaylist");
153211
return ResponseEntity.ok(response);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.example.demo.domain.playlist.dto;
2+
3+
import com.example.demo.domain.cd.dto.request.SaveCdRequest;
4+
import com.example.demo.domain.playlist.dto.playlistdto.SavePlaylistRequest;
5+
import jakarta.validation.Valid;
6+
7+
public record PlaylistDraft(@Valid SavePlaylistRequest savePlaylistRequest,
8+
SaveCdRequest saveCdRequest) {
9+
}

โ€Žmain-server/src/main/java/com/example/demo/domain/playlist/dto/PlaylistMapper.javaโ€Ž

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package com.example.demo.domain.playlist.dto;
22

3-
import com.example.demo.domain.playlist.dto.playlistdto.PlaylistCreateRequest;
3+
import com.example.demo.domain.playlist.dto.playlistdto.SavePlaylistRequest;
44
import com.example.demo.domain.playlist.entity.Playlist;
55
import com.example.demo.domain.user.entity.Users;
66

77
public class PlaylistMapper {
88

9-
public static Playlist toEntity(PlaylistCreateRequest request, Users users) {
9+
public static Playlist toEntity(SavePlaylistRequest request, Users users) {
1010
return Playlist.builder()
1111
.name(request.name())
1212
.genre(request.genre())

main-server/src/main/java/com/example/demo/domain/playlist/dto/playlistdto/PlaylistCreateRequest.java renamed to main-server/src/main/java/com/example/demo/domain/playlist/dto/playlistdto/SavePlaylistRequest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
import jakarta.validation.constraints.NotNull;
99
import java.util.List;
1010

11-
@Schema(description = "ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ ์š”์ฒญ DTO")
12-
public record PlaylistCreateRequest(
11+
@Schema(description = "ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ ์ €์žฅ ์š”์ฒญ DTO")
12+
public record SavePlaylistRequest(
1313

1414
@Schema(description = "ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ ์ด๋ฆ„", example = "๋น„ ์˜ค๋Š” ๋‚  ์ง‘์ค‘์šฉ")
1515
@NotBlank

โ€Žmain-server/src/main/java/com/example/demo/domain/playlist/service/PlaylistSaveService.javaโ€Ž

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
import com.example.common.error.code.UserErrorCode;
55
import com.example.common.error.exception.PlaylistException;
66
import com.example.common.error.exception.UserException;
7+
import com.example.demo.domain.cd.dto.request.SaveCdRequest;
8+
import com.example.demo.domain.playlist.dto.PlaylistDraft;
79
import com.example.demo.domain.playlist.dto.PlaylistMapper;
8-
import com.example.demo.domain.playlist.dto.playlistdto.PlaylistCreateRequest;
10+
import com.example.demo.domain.playlist.dto.playlistdto.SavePlaylistRequest;
911
import com.example.demo.domain.playlist.dto.playlistdto.PlaylistWithSongsResponse;
1012
import com.example.demo.domain.playlist.entity.Playlist;
1113
import com.example.demo.domain.playlist.repository.PlaylistRepository;
@@ -17,10 +19,14 @@
1719
import com.example.demo.domain.user.entity.Users;
1820
import com.example.demo.domain.user.repository.UsersRepository;
1921

22+
import java.time.Duration;
2023
import java.util.*;
2124

25+
import com.fasterxml.jackson.core.JsonProcessingException;
26+
import com.fasterxml.jackson.databind.ObjectMapper;
2227
import lombok.RequiredArgsConstructor;
2328
import lombok.extern.slf4j.Slf4j;
29+
import org.springframework.data.redis.core.StringRedisTemplate;
2430
import org.springframework.stereotype.Service;
2531
import org.springframework.transaction.annotation.Transactional;
2632

@@ -32,9 +38,53 @@ public class PlaylistSaveService {
3238
private final PlaylistRepository playlistRepository;
3339
private final SongRepository songRepository;
3440
private final UsersRepository usersRepository;
41+
private final StringRedisTemplate stringRedisTemplate;
42+
private final ObjectMapper objectMapper;
43+
44+
private static final String PREFIX = "playlist:draft:";
45+
46+
public String createDraft(SavePlaylistRequest savePlaylistRequest,
47+
SaveCdRequest saveCdRequest) {
48+
String draftId = UUID.randomUUID().toString();
49+
PlaylistDraft draft = new PlaylistDraft(
50+
savePlaylistRequest,
51+
saveCdRequest
52+
);
53+
saveDraft(draftId, draft);
54+
return draftId;
55+
}
56+
57+
public PlaylistDraft loadDraft(String draftId) {
58+
String key = PREFIX + draftId;
59+
String json = stringRedisTemplate.opsForValue().get(key);
60+
61+
log.info("loadDraft key={}, json={}", key, json);
62+
63+
if (json == null) throw new PlaylistException(PlaylistErrorCode.PLAYLIST_DRAFT_ERROR);
64+
65+
try {
66+
return objectMapper.readValue(json, PlaylistDraft.class);
67+
} catch (JsonProcessingException e) {
68+
log.warn("parse fail draftId={}, json={}", draftId, json, e);
69+
throw new PlaylistException(PlaylistErrorCode.PLAYLIST_DRAFT_ERROR);
70+
}
71+
}
72+
73+
private void saveDraft(String draftId, PlaylistDraft draft) {
74+
try {
75+
String json = objectMapper.writeValueAsString(draft);
76+
stringRedisTemplate.opsForValue().set(PREFIX + draftId, json, Duration.ofHours(1));
77+
} catch (JsonProcessingException e) {
78+
throw new PlaylistException(PlaylistErrorCode.PLAYLIST_DRAFT_ERROR);
79+
}
80+
}
81+
82+
public void deleteDraft(String draftId) {
83+
stringRedisTemplate.delete(PREFIX + draftId);
84+
}
3585

3686
@Transactional
37-
public PlaylistWithSongsResponse savePlaylistWithSongs(String usersId, PlaylistCreateRequest request) {
87+
public PlaylistWithSongsResponse savePlaylistWithSongs(String usersId, SavePlaylistRequest request) {
3888

3989
Playlist savedPlaylist = savePlaylist(usersId, request);
4090

@@ -53,7 +103,7 @@ public PlaylistWithSongsResponse savePlaylistWithSongs(String usersId, PlaylistC
53103
}
54104

55105
@Transactional
56-
public Playlist savePlaylist(String usersId, PlaylistCreateRequest request) {
106+
public Playlist savePlaylist(String usersId, SavePlaylistRequest request) {
57107

58108
Users users = usersRepository.findById(usersId)
59109
.orElseThrow(() -> new UserException(UserErrorCode.USER_NOT_FOUND));
@@ -65,7 +115,7 @@ public Playlist savePlaylist(String usersId, PlaylistCreateRequest request) {
65115

66116
@Transactional
67117
public PlaylistWithSongsResponse editPlaylistWithSongs(
68-
String usersId, Long playlistId, PlaylistCreateRequest request) {
118+
String usersId, Long playlistId, SavePlaylistRequest request) {
69119

70120
Users users = usersRepository.findById(usersId)
71121
.orElseThrow(() -> new UserException(UserErrorCode.USER_NOT_FOUND));

โ€Žmain-server/src/main/java/com/example/demo/domain/playlist/service/PlaylistService.javaโ€Ž

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,29 @@
11
package com.example.demo.domain.playlist.service;
22

3-
import com.example.demo.domain.cd.dto.request.CdItemRequest;
3+
import com.example.demo.domain.playlist.dto.EditFinalPlaylistRequest;
4+
import com.example.demo.domain.playlist.dto.FinalPlaylistRequest;
5+
import com.example.demo.domain.playlist.dto.PlaylistDraft;
46
import com.example.demo.domain.playlist.dto.playlistdto.MainPlaylistDetailResponse;
5-
import com.example.demo.domain.playlist.dto.playlistdto.PlaylistCreateRequest;
7+
import com.example.demo.domain.playlist.dto.playlistdto.SavePlaylistRequest;
68
import com.example.demo.domain.playlist.dto.playlistdto.PlaylistWithSongsResponse;
79

8-
import java.util.List;
9-
1010
public interface PlaylistService {
1111

1212
MainPlaylistDetailResponse playPlaylist(Long playlistId, String userId);
1313

1414
MainPlaylistDetailResponse getPlaylistDetail(Long playlistId, String userId);
1515

16-
PlaylistWithSongsResponse saveFinalPlaylistWithSongsAndCd(String usersId, PlaylistCreateRequest request, List<CdItemRequest> cdItemRequestList);
16+
PlaylistWithSongsResponse saveFinalPlaylist(String usersId, String draftId);
17+
18+
PlaylistWithSongsResponse editFinalPlaylist(String usersId, Long playlistId ,String draftId);
19+
20+
String saveDraftPlaylist(PlaylistDraft playlistDraft);
21+
22+
PlaylistWithSongsResponse saveFinalPlaylistWithSongsAndCd(String usersId, SavePlaylistRequest savePlaylistRequest,
23+
FinalPlaylistRequest finalPlaylistRequest);
1724

18-
PlaylistWithSongsResponse editFinalPlaylistWithSongsAndCd(String usersId, Long playlistId, PlaylistCreateRequest request,
19-
List<CdItemRequest> cdItemRequestList);
25+
PlaylistWithSongsResponse editFinalPlaylistWithSongsAndCd(String usersId, SavePlaylistRequest savePlaylistRequest,
26+
EditFinalPlaylistRequest editFinalPlaylistRequest);
2027

2128
void deletePlaylist(String userId, Long playlistId);
2229

0 commit comments

Comments
ย (0)