-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* refactor: 노래 데이터 캐싱 정책 추가 * refactor: 테스트를 위한 schedule 시간 변경 * refactor: 메인 top100 노래 데이터 캐싱으로 변경 * refactor: 노래 데이터 캐싱하는 것 수정 세부사항 - cachedSong -> InMemorySongs으로 이름 변경 - util 클래스 -> repository 빈으로 수정 * test: 현재 완성되지 않는 테스트 제거 * test: InMemorySong 테스트 추가 * config: security 스냅샷 생성 * fix: 테스트, 로컬 InMemorySongsScheduler 시간 수정 * config: security 수정 설정 스냅샷 최신화 * config: InMemoryScheduler 시간 수정 * refactor: TODO 제거 --------- Co-authored-by: somsom13 <[email protected]> Co-authored-by: somin <[email protected]> Co-authored-by: Eunsol Kim <[email protected]>
- Loading branch information
1 parent
417c6cc
commit 2583129
Showing
17 changed files
with
378 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
backend/src/main/java/shook/shook/song/application/InMemorySongsScheduler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package shook.shook.song.application; | ||
|
||
import jakarta.annotation.PostConstruct; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.scheduling.annotation.Scheduled; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import shook.shook.song.domain.InMemorySongs; | ||
import shook.shook.song.domain.repository.SongRepository; | ||
|
||
@RequiredArgsConstructor | ||
@Transactional(readOnly = true) | ||
@Component | ||
public class InMemorySongsScheduler { | ||
|
||
private final SongRepository songRepository; | ||
private final InMemorySongs inMemorySongs; | ||
|
||
@PostConstruct | ||
public void initialize() { | ||
recreateCachedSong(); | ||
} | ||
|
||
@Scheduled(cron = "${schedules.in-memory-song.cron}") | ||
public void recreateCachedSong() { | ||
inMemorySongs.recreate(songRepository.findAllWithKillingParts()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
backend/src/main/java/shook/shook/song/domain/InMemorySongs.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package shook.shook.song.domain; | ||
|
||
import java.util.Collections; | ||
import java.util.Comparator; | ||
import java.util.LinkedHashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
import org.springframework.stereotype.Repository; | ||
import shook.shook.song.exception.SongException; | ||
|
||
@Repository | ||
public class InMemorySongs { | ||
|
||
private Map<Long, Song> songsSortedInLikeCountById = new LinkedHashMap<>(); | ||
|
||
public void recreate(final List<Song> songs) { | ||
songsSortedInLikeCountById = getSortedSong(songs); | ||
} | ||
|
||
private static Map<Long, Song> getSortedSong(final List<Song> songs) { | ||
songs.sort(Comparator.comparing( | ||
Song::getTotalLikeCount, | ||
Comparator.reverseOrder() | ||
).thenComparing(Song::getId, Comparator.reverseOrder())); | ||
|
||
return songs.stream() | ||
.collect(Collectors.toMap( | ||
Song::getId, | ||
song -> song, | ||
(prev, update) -> update, | ||
LinkedHashMap::new | ||
)); | ||
} | ||
|
||
public List<Song> getSongs() { | ||
return songsSortedInLikeCountById.values() | ||
.stream() | ||
.toList(); | ||
} | ||
|
||
public Song getSongById(final Long id) { | ||
if (songsSortedInLikeCountById.containsKey(id)) { | ||
return songsSortedInLikeCountById.get(id); | ||
} | ||
throw new SongException.SongNotExistException( | ||
Map.of("song id", String.valueOf(id)) | ||
); | ||
} | ||
|
||
public List<Song> getPrevLikedSongs(final Song currentSong, final int prevSongCount) { | ||
final List<Long> songIds = songsSortedInLikeCountById.keySet() | ||
.stream() | ||
.toList(); | ||
final int currentSongIndex = songIds.indexOf(currentSong.getId()); | ||
|
||
return songIds.subList(Math.max(0, currentSongIndex - prevSongCount), currentSongIndex).stream() | ||
.map(songsSortedInLikeCountById::get) | ||
.toList(); | ||
} | ||
|
||
public List<Song> getNextLikedSongs(final Song currentSong, final int nextSongCount) { | ||
final List<Long> songIds = songsSortedInLikeCountById.keySet().stream() | ||
.toList(); | ||
final int currentSongIndex = songIds.indexOf(currentSong.getId()); | ||
|
||
if (currentSongIndex == songIds.size() - 1) { | ||
return Collections.emptyList(); | ||
} | ||
|
||
return songIds.subList(Math.min(currentSongIndex + 1, songIds.size() - 1), Math.min(songIds.size(), currentSongIndex + nextSongCount + 1)) | ||
.stream() | ||
.map(songsSortedInLikeCountById::get) | ||
.toList(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule shook-security
updated
from 30d5e0 to df2277
47 changes: 47 additions & 0 deletions
47
backend/src/test/java/shook/shook/song/application/InMemorySongsSchedulerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package shook.shook.song.application; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
import java.util.Collections; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
import org.springframework.scheduling.annotation.EnableScheduling; | ||
import org.springframework.test.context.jdbc.Sql; | ||
import shook.shook.song.domain.InMemorySongs; | ||
|
||
@Sql(value = "classpath:/killingpart/initialize_killing_part_song.sql") | ||
@EnableScheduling | ||
@SpringBootTest | ||
class InMemorySongsSchedulerTest { | ||
|
||
@Autowired | ||
private InMemorySongs inMemorySongs; | ||
|
||
@Autowired | ||
private InMemorySongsScheduler scheduler; | ||
|
||
@DisplayName("InMemorySongs 를 재생성한다.") | ||
@Test | ||
void recreateCachedSong() { | ||
// given | ||
// when | ||
scheduler.recreateCachedSong(); | ||
|
||
// then | ||
assertThat(inMemorySongs.getSongs()).hasSize(3); | ||
} | ||
|
||
@DisplayName("Scheduler 가 1초마다 실행된다.") | ||
@Test | ||
void schedule() throws InterruptedException { | ||
// given | ||
// when | ||
inMemorySongs.recreate(Collections.emptyList()); | ||
Thread.sleep(1000); | ||
|
||
// then | ||
assertThat(inMemorySongs.getSongs()).hasSize(3); | ||
} | ||
} |
Oops, something went wrong.