Skip to content

Commit 1cc8d3e

Browse files
authored
Merge pull request #227 from 9uttery/feat/create-joy-v2-#221
[Feature] Phase 3.0 앨범/소확행 관련 API 구현
2 parents 9725439 + a881288 commit 1cc8d3e

File tree

1 file changed

+78
-15
lines changed

1 file changed

+78
-15
lines changed

src/main/java/com/guttery/madii/domain/albums/application/service/AlbumService.java

Lines changed: 78 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525
import org.springframework.data.domain.Pageable;
2626
import org.springframework.data.domain.Slice;
2727
import org.springframework.data.domain.SliceImpl;
28+
import org.springframework.data.redis.core.Cursor;
2829
import org.springframework.data.redis.core.ListOperations;
2930
import org.springframework.data.redis.core.RedisTemplate;
31+
import org.springframework.data.redis.core.ScanOptions;
3032
import org.springframework.stereotype.Service;
3133
import org.springframework.transaction.annotation.Transactional;
3234

@@ -360,19 +362,68 @@ public void deleteAlbum(Long albumId, UserPrincipal userPrincipal) {
360362
savingJoyRepository.deleteByAlbumAlbumId(albumId);
361363
albumRepository.deleteById(albumId);
362364
}
365+
//
366+
// public void deleteAlbums(List<Long> albumIds, UserPrincipal userPrincipal) {
367+
// final User user = UserServiceHelper.findExistingUser(userRepository, userPrincipal);
368+
//
369+
// Set<String> keys = redisTemplate.keys(KEY_PREFIX + "*");
370+
// ListOperations<String, String> listOps = redisTemplate.opsForList();
371+
//
372+
// // 실패한 albumId와 예외 메시지를 저장
373+
// Map<Long, String> failedAlbumMap = new HashMap<>();
374+
//
375+
// // 먼저 모든 유효성 및 권한 체크를 먼저 한 후, 삭제는 그 다음에 수행
376+
// List<Album> albumsToDelete = new ArrayList<>();
377+
//
378+
// for (Long albumId : albumIds) {
379+
// try {
380+
// Album album = albumRepository.findById(albumId)
381+
// .orElseThrow(() -> CustomException.of(ErrorDetails.ALBUM_NOT_FOUND));
382+
//
383+
// if (!album.getUser().getUserId().equals(user.getUserId())) {
384+
// throw CustomException.of(ErrorDetails.NOT_MY_ALBUM);
385+
// }
386+
//
387+
// albumsToDelete.add(album);
388+
// } catch (Exception e) {
389+
// failedAlbumMap.put(albumId, e.getMessage());
390+
// }
391+
// }
392+
//
393+
// // 하나라도 실패한 경우 전체 중단 및 rollback
394+
// if (!failedAlbumMap.isEmpty()) {
395+
// for (Map.Entry<Long, String> entry : failedAlbumMap.entrySet()) {
396+
// log.warn("앨범 삭제 실패 - albumId: {}, 이유: {}", entry.getKey(), entry.getValue());
397+
// }
398+
// throw CustomException.of(ErrorDetails.DELETE_ALBUM_FAILED); // 커스텀 예외 처리
399+
// }
400+
//
401+
// // 실제 삭제 (캐시, 연관 엔티티, 앨범)
402+
// for (Album album : albumsToDelete) {
403+
// Long albumId = album.getAlbumId();
404+
//
405+
// for (String key : keys) {
406+
// List<String> cachedAlbumIds = listOps.range(key, 0, -1);
407+
// if (cachedAlbumIds != null && cachedAlbumIds.contains("albumId:" + albumId)) {
408+
// listOps.remove(key, 0, "albumId:" + albumId);
409+
// }
410+
// }
411+
//
412+
// savingAlbumRepository.deleteByAlbumAlbumId(albumId);
413+
// savingJoyRepository.deleteByAlbumAlbumId(albumId);
414+
// albumRepository.deleteById(albumId);
415+
// }
416+
// }
363417

364418
public void deleteAlbums(List<Long> albumIds, UserPrincipal userPrincipal) {
365419
final User user = UserServiceHelper.findExistingUser(userRepository, userPrincipal);
366420

367-
Set<String> keys = redisTemplate.keys(KEY_PREFIX + "*");
368-
ListOperations<String, String> listOps = redisTemplate.opsForList();
421+
// 먼저 모든 유효성 및 권한 체크를 먼저 한 후, 삭제는 그 다음에 수행
422+
List<Album> albumsToDelete = new ArrayList<>();
369423

370424
// 실패한 albumId와 예외 메시지를 저장
371425
Map<Long, String> failedAlbumMap = new HashMap<>();
372426

373-
// 먼저 모든 유효성 및 권한 체크를 먼저 한 후, 삭제는 그 다음에 수행
374-
List<Album> albumsToDelete = new ArrayList<>();
375-
376427
for (Long albumId : albumIds) {
377428
try {
378429
Album album = albumRepository.findById(albumId)
@@ -396,23 +447,35 @@ public void deleteAlbums(List<Long> albumIds, UserPrincipal userPrincipal) {
396447
throw CustomException.of(ErrorDetails.DELETE_ALBUM_FAILED); // 커스텀 예외 처리
397448
}
398449

399-
// 실제 삭제 (캐시, 연관 엔티티, 앨범)
400-
for (Album album : albumsToDelete) {
401-
Long albumId = album.getAlbumId();
450+
// Redis 삭제 (SCAN 사용)
451+
try (Cursor<byte[]> cursor = redisTemplate.getConnectionFactory()
452+
.getConnection()
453+
.scan(ScanOptions.scanOptions().match(KEY_PREFIX + "*").count(100).build())) {
454+
455+
ListOperations<String, String> listOps = redisTemplate.opsForList();
402456

403-
for (String key : keys) {
404-
List<String> cachedAlbumIds = listOps.range(key, 0, -1);
405-
if (cachedAlbumIds != null && cachedAlbumIds.contains("albumId:" + albumId)) {
406-
listOps.remove(key, 0, "albumId:" + albumId);
457+
while (cursor.hasNext()) {
458+
String key = new String(cursor.next());
459+
for (Album album : albumsToDelete) {
460+
String target = "albumId:" + album.getAlbumId();
461+
listOps.remove(key, 0, target);
407462
}
408463
}
409464

410-
savingAlbumRepository.deleteByAlbumAlbumId(albumId);
411-
savingJoyRepository.deleteByAlbumAlbumId(albumId);
412-
albumRepository.deleteById(albumId);
465+
} catch (Exception e) {
466+
log.error("Redis 삭제 중 오류 발생", e);
467+
// 필요 시 fallback 로직 추가
468+
}
469+
470+
// DB 삭제 (트랜잭션 보장)
471+
for (Album album : albumsToDelete) {
472+
savingAlbumRepository.deleteByAlbumAlbumId(album.getAlbumId());
473+
savingJoyRepository.deleteByAlbumAlbumId(album.getAlbumId());
474+
albumRepository.deleteById(album.getAlbumId());
413475
}
414476
}
415477

478+
416479
public List<AlbumGetCreatedResponse> getCreatedAlbums(UserPrincipal userPrincipal) {
417480
final User user = UserServiceHelper.findExistingUser(userRepository, userPrincipal);
418481

0 commit comments

Comments
 (0)