From dc735631f84a8266faf2f520bf1b6b1f0d2a8999 Mon Sep 17 00:00:00 2001 From: Eunsol Kim <61370551+Cyma-s@users.noreply.github.com> Date: Fri, 15 Dec 2023 16:38:32 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20synchronized=20=EB=A1=9C=20?= =?UTF-8?q?=EB=8F=99=EC=8B=9C=EC=84=B1=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/InMemorySongsScheduler.java | 1 + .../killingpart/KillingPartLikeService.java | 1 + .../shook/song/domain/InMemorySongs.java | 36 ++++++++++--------- .../KillingPartLikeServiceTest.java | 17 +++------ .../shook/song/domain/InMemorySongsTest.java | 4 --- .../shook/song/ui/MyPageControllerTest.java | 6 ++++ 6 files changed, 32 insertions(+), 33 deletions(-) diff --git a/backend/src/main/java/shook/shook/song/application/InMemorySongsScheduler.java b/backend/src/main/java/shook/shook/song/application/InMemorySongsScheduler.java index 67c9344e..41355176 100644 --- a/backend/src/main/java/shook/shook/song/application/InMemorySongsScheduler.java +++ b/backend/src/main/java/shook/shook/song/application/InMemorySongsScheduler.java @@ -53,5 +53,6 @@ public void updateCachedSong() { .flatMap(song -> song.getKillingParts().stream()) .toList(); killingParts.forEach(entityManager::merge); + recreateCachedSong(); } } diff --git a/backend/src/main/java/shook/shook/song/application/killingpart/KillingPartLikeService.java b/backend/src/main/java/shook/shook/song/application/killingpart/KillingPartLikeService.java index 2399e648..0146323d 100644 --- a/backend/src/main/java/shook/shook/song/application/killingpart/KillingPartLikeService.java +++ b/backend/src/main/java/shook/shook/song/application/killingpart/KillingPartLikeService.java @@ -57,6 +57,7 @@ private void create(final KillingPart killingPart, final Member member) { .orElseGet(() -> createNewLike(killingPart, member)); if (likeOnKillingPart.isDeleted()) { inMemorySongs.like(killingPart, likeOnKillingPart); + likeRepository.pressLike(likeOnKillingPart.getId()); } } diff --git a/backend/src/main/java/shook/shook/song/domain/InMemorySongs.java b/backend/src/main/java/shook/shook/song/domain/InMemorySongs.java index a3783b7a..83d69779 100644 --- a/backend/src/main/java/shook/shook/song/domain/InMemorySongs.java +++ b/backend/src/main/java/shook/shook/song/domain/InMemorySongs.java @@ -25,7 +25,7 @@ public class InMemorySongs { private Map songs = new HashMap<>(); private List sortedSongIds = new ArrayList<>(); - public void refreshSongs(final List songs) { + public synchronized void refreshSongs(final List songs) { this.songs = songs.stream() .collect(Collectors.toMap(Song::getId, song -> song, (prev, update) -> update, HashMap::new)); this.sortedSongIds = new ArrayList<>(this.songs.keySet().stream() @@ -116,7 +116,16 @@ public void like(final KillingPart killingPart, final KillingPartLike likeOnKill } } - private static KillingPart findKillingPart(final KillingPart killingPart, final Song song) { + public void unlike(final KillingPart killingPart, final KillingPartLike unlikeOnKillingPart) { + final Song song = songs.get(killingPart.getSong().getId()); + final KillingPart killingPartById = findKillingPart(killingPart, song); + final boolean updated = killingPartById.unlike(unlikeOnKillingPart); + if (updated) { + reorder(song); + } + } + + private KillingPart findKillingPart(final KillingPart killingPart, final Song song) { return song.getKillingParts().stream() .filter(kp -> kp.equals(killingPart)) .findAny() @@ -126,14 +135,16 @@ private static KillingPart findKillingPart(final KillingPart killingPart, final } private void reorder(final Song updatedSong) { - int currentSongIndex = sortedSongIds.indexOf(updatedSong.getId()); + synchronized (sortedSongIds) { + int currentSongIndex = sortedSongIds.indexOf(updatedSong.getId()); - if (currentSongIndex == -1) { - return; - } + if (currentSongIndex == -1) { + return; + } - moveForward(updatedSong, currentSongIndex); - moveBackward(updatedSong, currentSongIndex); + moveForward(updatedSong, currentSongIndex); + moveBackward(updatedSong, currentSongIndex); + } } private void moveForward(final Song changedSong, final int songIndex) { @@ -186,13 +197,4 @@ private boolean shouldSwapWithNext(final Song song, final Song nextSong) { return hasSmallerTotalLikeCountThanNextSong || hasSameTotalLikeCountAndSmallerIdThanNextSong; } - - public void unlike(final KillingPart killingPart, final KillingPartLike unlikeOnKillingPart) { - final Song song = songs.get(killingPart.getSong().getId()); - final KillingPart killingPartById = findKillingPart(killingPart, song); - final boolean updated = killingPartById.unlike(unlikeOnKillingPart); - if (updated) { - reorder(song); - } - } } diff --git a/backend/src/test/java/shook/shook/song/application/killingpart/KillingPartLikeServiceTest.java b/backend/src/test/java/shook/shook/song/application/killingpart/KillingPartLikeServiceTest.java index 9cba05fd..f3fd844b 100644 --- a/backend/src/test/java/shook/shook/song/application/killingpart/KillingPartLikeServiceTest.java +++ b/backend/src/test/java/shook/shook/song/application/killingpart/KillingPartLikeServiceTest.java @@ -5,7 +5,6 @@ import java.util.Optional; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -47,6 +46,7 @@ class KillingPartLikeServiceTest extends UsingJpaTest { private SongRepository songRepository; private KillingPartLikeService likeService; + private InMemorySongs inMemorySongs; @BeforeEach @@ -221,19 +221,15 @@ void delete_alreadyDeleted_noAction() { // then final Optional savedLike = killingPartLikeRepository. findByKillingPartAndMember(SAVED_KILLING_PART, SAVED_MEMBER); - final Optional updatedKillingPart = killingPartRepository.findById( - SAVED_KILLING_PART.getId()); + final Song savedSong = inMemorySongs.getSongById(SAVED_SONG.getId()); assertThat(savedLike).isPresent() .get() .hasFieldOrPropertyWithValue("isDeleted", true); - assertThat(updatedKillingPart).isPresent() - .get() - .hasFieldOrPropertyWithValue("likeCount", 0); + assertThat(savedSong.getTotalLikeCount()).isZero(); } - @Disabled() @DisplayName("좋아요 데이터가 존재하는 경우, 상태가 변경된다.") @Test void create_noAction() { @@ -251,16 +247,13 @@ void create_noAction() { // then final Optional savedLike = killingPartLikeRepository. findByKillingPartAndMember(SAVED_KILLING_PART, SAVED_MEMBER); - final Optional updatedKillingPart = killingPartRepository.findById( - SAVED_KILLING_PART.getId()); + final Song savedSong = inMemorySongs.getSongById(SAVED_SONG.getId()); assertThat(savedLike).isPresent() .get() .hasFieldOrPropertyWithValue("isDeleted", true); - assertThat(updatedKillingPart).isPresent() - .get() - .hasFieldOrPropertyWithValue("likeCount", 0); + assertThat(savedSong.getTotalLikeCount()).isZero(); } @DisplayName("존재하지 않는 킬링파트면 예외가 발생한다.") diff --git a/backend/src/test/java/shook/shook/song/domain/InMemorySongsTest.java b/backend/src/test/java/shook/shook/song/domain/InMemorySongsTest.java index e849e27a..5f6abd39 100644 --- a/backend/src/test/java/shook/shook/song/domain/InMemorySongsTest.java +++ b/backend/src/test/java/shook/shook/song/domain/InMemorySongsTest.java @@ -3,7 +3,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; -import jakarta.persistence.EntityManager; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -30,9 +29,6 @@ class InMemorySongsTest extends UsingJpaTest { @Autowired private MemberRepository memberRepository; - @Autowired - private EntityManager entityManager; - @BeforeEach void setUp() { MEMBER = memberRepository.findById(1L).get(); diff --git a/backend/src/test/java/shook/shook/song/ui/MyPageControllerTest.java b/backend/src/test/java/shook/shook/song/ui/MyPageControllerTest.java index 9016cf81..73392533 100644 --- a/backend/src/test/java/shook/shook/song/ui/MyPageControllerTest.java +++ b/backend/src/test/java/shook/shook/song/ui/MyPageControllerTest.java @@ -25,6 +25,7 @@ import shook.shook.song.application.dto.MyPartsResponse; import shook.shook.song.application.killingpart.KillingPartLikeService; import shook.shook.song.application.killingpart.dto.KillingPartLikeRequest; +import shook.shook.song.domain.InMemorySongs; import shook.shook.song.domain.Song; import shook.shook.song.domain.killingpart.KillingPart; import shook.shook.song.domain.killingpart.repository.KillingPartRepository; @@ -46,6 +47,9 @@ void setUp() { private static final long SAVED_MEMBER_ID = 1L; private static final String SAVED_MEMBER_NICKNAME = "nickname"; + @Autowired + private InMemorySongs inMemorySongs; + @Autowired private TokenProvider tokenProvider; @@ -73,6 +77,8 @@ class GetLikedKillingParts { @Test void likedKillingPartExistWithOneDeletedLikeExist() { //given + inMemorySongs.refreshSongs(songRepository.findAllWithKillingPartsAndLikes()); + final String accessToken = tokenProvider.createAccessToken(SAVED_MEMBER_ID, SAVED_MEMBER_NICKNAME);