diff --git a/src/main/kotlin/fr/shikkanime/controllers/api/MemberController.kt b/src/main/kotlin/fr/shikkanime/controllers/api/MemberController.kt index 70adb797..0c86ad71 100644 --- a/src/main/kotlin/fr/shikkanime/controllers/api/MemberController.kt +++ b/src/main/kotlin/fr/shikkanime/controllers/api/MemberController.kt @@ -1,13 +1,12 @@ package fr.shikkanime.controllers.api import com.google.inject.Inject -import fr.shikkanime.converters.AbstractConverter import fr.shikkanime.dtos.AllFollowedEpisodeDto import fr.shikkanime.dtos.GenericDto -import fr.shikkanime.dtos.MemberDto import fr.shikkanime.services.MemberFollowAnimeService import fr.shikkanime.services.MemberFollowEpisodeService import fr.shikkanime.services.MemberService +import fr.shikkanime.services.caches.MemberCacheService import fr.shikkanime.utils.StringUtils import fr.shikkanime.utils.routes.* import fr.shikkanime.utils.routes.method.Delete @@ -23,6 +22,9 @@ class MemberController { @Inject private lateinit var memberService: MemberService + @Inject + private lateinit var memberCacheService: MemberCacheService + @Inject private lateinit var memberFollowAnimeService: MemberFollowAnimeService @@ -42,7 +44,7 @@ class MemberController { do { identifier = StringUtils.generateRandomString(12) - } while (memberService.findPrivateMember(identifier) != null) + } while (memberCacheService.findPrivateMember(identifier) != null) memberService.savePrivateMember(identifier) return Response.created(mapOf("identifier" to identifier)) @@ -57,8 +59,7 @@ class MemberController { ] ) private fun loginPrivateMember(@BodyParam identifier: String): Response { - val privateMember = memberService.findPrivateMember(identifier) ?: return Response.notFound() - return Response.ok(AbstractConverter.convert(privateMember, MemberDto::class.java)) + return Response.ok(memberCacheService.findPrivateMember(identifier) ?: return Response.notFound()) } @Path("/animes") diff --git a/src/main/kotlin/fr/shikkanime/converters/member/MemberToMemberDtoConverter.kt b/src/main/kotlin/fr/shikkanime/converters/member/MemberToMemberDtoConverter.kt index ca2b6a7c..5697eb70 100644 --- a/src/main/kotlin/fr/shikkanime/converters/member/MemberToMemberDtoConverter.kt +++ b/src/main/kotlin/fr/shikkanime/converters/member/MemberToMemberDtoConverter.kt @@ -18,7 +18,6 @@ class MemberToMemberDtoConverter : AbstractConverter() { override fun convert(from: Member): MemberDto { val tokenDto = convert(from, TokenDto::class.java) - val followedEpisodes = memberFollowEpisodeService.getAllFollowedEpisodes(from) return MemberDto( uuid = from.uuid!!, @@ -26,9 +25,9 @@ class MemberToMemberDtoConverter : AbstractConverter() { creationDateTime = from.creationDateTime.withUTCString(), lastUpdateDateTime = from.lastUpdateDateTime.withUTCString(), isPrivate = from.isPrivate, - followedAnimes = memberFollowAnimeService.getAllFollowedAnimes(from).mapNotNull { it.uuid }, - followedEpisodes = followedEpisodes.mapNotNull { it.uuid }, - totalDuration = followedEpisodes.sumOf { it.duration } + followedAnimes = memberFollowAnimeService.getAllFollowedAnimesUUID(from), + followedEpisodes = memberFollowEpisodeService.getAllFollowedEpisodesUUID(from), + totalDuration = memberFollowEpisodeService.getTotalDuration(from), ) } } \ No newline at end of file diff --git a/src/main/kotlin/fr/shikkanime/jobs/FetchOldEpisodesJob.kt b/src/main/kotlin/fr/shikkanime/jobs/FetchOldEpisodesJob.kt index e373cb25..dba45946 100644 --- a/src/main/kotlin/fr/shikkanime/jobs/FetchOldEpisodesJob.kt +++ b/src/main/kotlin/fr/shikkanime/jobs/FetchOldEpisodesJob.kt @@ -104,6 +104,11 @@ class FetchOldEpisodesJob : AbstractJob { } } + if (realSaved == 0) { + logger.info("No new episodes found") + return + } + logger.info("Saved $realSaved episodes") logger.info("Updating mappings...") diff --git a/src/main/kotlin/fr/shikkanime/repositories/EpisodeVariantRepository.kt b/src/main/kotlin/fr/shikkanime/repositories/EpisodeVariantRepository.kt index 606f6b78..4feed0db 100644 --- a/src/main/kotlin/fr/shikkanime/repositories/EpisodeVariantRepository.kt +++ b/src/main/kotlin/fr/shikkanime/repositories/EpisodeVariantRepository.kt @@ -1,7 +1,7 @@ package fr.shikkanime.repositories -import fr.shikkanime.entities.* import com.google.inject.Inject +import fr.shikkanime.entities.* import fr.shikkanime.entities.enums.CountryCode import fr.shikkanime.entities.enums.EpisodeType import fr.shikkanime.services.MemberFollowAnimeService @@ -32,8 +32,8 @@ class EpisodeVariantRepository : AbstractRepository() { val predicates = mutableListOf(countryPredicate, datePredicate) member?.let { - val animePredicate = root[EpisodeVariant_.mapping][EpisodeMapping_.anime].`in`( - memberFollowAnimeService.getAllFollowedAnimes(it) + val animePredicate = root[EpisodeVariant_.mapping][EpisodeMapping_.anime].get(Anime_.UUID).`in`( + memberFollowAnimeService.getAllFollowedAnimesUUID(it) ) predicates.add(animePredicate) } diff --git a/src/main/kotlin/fr/shikkanime/repositories/MemberFollowAnimeRepository.kt b/src/main/kotlin/fr/shikkanime/repositories/MemberFollowAnimeRepository.kt index 50cdd5ff..e2b1cae4 100644 --- a/src/main/kotlin/fr/shikkanime/repositories/MemberFollowAnimeRepository.kt +++ b/src/main/kotlin/fr/shikkanime/repositories/MemberFollowAnimeRepository.kt @@ -1,9 +1,7 @@ package fr.shikkanime.repositories -import fr.shikkanime.entities.Anime -import fr.shikkanime.entities.Member -import fr.shikkanime.entities.MemberFollowAnime -import fr.shikkanime.entities.MemberFollowAnime_ +import fr.shikkanime.entities.* +import java.util.* class MemberFollowAnimeRepository : AbstractRepository() { override fun getEntityClass() = MemberFollowAnime::class.java @@ -25,12 +23,12 @@ class MemberFollowAnimeRepository : AbstractRepository() { } } - fun getAllFollowedAnimes(member: Member): List { + fun getAllFollowedAnimesUUID(member: Member): List { return inTransaction { val cb = it.criteriaBuilder - val query = cb.createQuery(Anime::class.java) + val query = cb.createQuery(UUID::class.java) val root = query.from(getEntityClass()) - query.select(root[MemberFollowAnime_.anime]) + query.select(root[MemberFollowAnime_.anime][Anime_.UUID]) query.where( cb.equal(root[MemberFollowAnime_.member], member) diff --git a/src/main/kotlin/fr/shikkanime/repositories/MemberFollowEpisodeRepository.kt b/src/main/kotlin/fr/shikkanime/repositories/MemberFollowEpisodeRepository.kt index d6fbc2a7..0ade2a65 100644 --- a/src/main/kotlin/fr/shikkanime/repositories/MemberFollowEpisodeRepository.kt +++ b/src/main/kotlin/fr/shikkanime/repositories/MemberFollowEpisodeRepository.kt @@ -1,9 +1,7 @@ package fr.shikkanime.repositories -import fr.shikkanime.entities.EpisodeMapping -import fr.shikkanime.entities.Member -import fr.shikkanime.entities.MemberFollowEpisode -import fr.shikkanime.entities.MemberFollowEpisode_ +import fr.shikkanime.entities.* +import java.util.* class MemberFollowEpisodeRepository : AbstractRepository() { override fun getEntityClass() = MemberFollowEpisode::class.java @@ -25,12 +23,12 @@ class MemberFollowEpisodeRepository : AbstractRepository() } } - fun getAllFollowedEpisodes(member: Member): List { + fun getAllFollowedEpisodesUUID(member: Member): List { return inTransaction { val cb = it.criteriaBuilder - val query = cb.createQuery(EpisodeMapping::class.java) + val query = cb.createQuery(UUID::class.java) val root = query.from(getEntityClass()) - query.select(root[MemberFollowEpisode_.episode]) + query.select(root[MemberFollowEpisode_.episode][EpisodeMapping_.UUID]) query.where( cb.equal(root[MemberFollowEpisode_.member], member) @@ -40,4 +38,21 @@ class MemberFollowEpisodeRepository : AbstractRepository() .resultList } } + + fun getTotalDuration(member: Member): Long { + return inTransaction { + val cb = it.criteriaBuilder + val query = cb.createQuery(Long::class.java) + val root = query.from(getEntityClass()) + query.select(cb.sum(root[MemberFollowEpisode_.episode][EpisodeMapping_.duration])) + + query.where( + cb.equal(root[MemberFollowEpisode_.member], member) + ) + + createReadOnlyQuery(it, query) + .resultList + .firstOrNull() ?: 0L + } + } } \ No newline at end of file diff --git a/src/main/kotlin/fr/shikkanime/services/MemberFollowAnimeService.kt b/src/main/kotlin/fr/shikkanime/services/MemberFollowAnimeService.kt index cce0ef51..07f431d3 100644 --- a/src/main/kotlin/fr/shikkanime/services/MemberFollowAnimeService.kt +++ b/src/main/kotlin/fr/shikkanime/services/MemberFollowAnimeService.kt @@ -22,7 +22,7 @@ class MemberFollowAnimeService : AbstractService(classes = listOf(Member::class.java, MemberFollowAnime::class.java, MemberFollowEpisode::class.java)) { + memberService.findPrivateMember(it) + ?.let { member -> AbstractConverter.convert(member, MemberDto::class.java) } + } + fun find(uuid: UUID) = cache[uuid] + + fun findPrivateMember(identifier: String) = findPrivateMemberCache[identifier] } \ No newline at end of file diff --git a/src/test/kotlin/fr/shikkanime/controllers/api/AnimeControllerTest.kt b/src/test/kotlin/fr/shikkanime/controllers/api/AnimeControllerTest.kt index 886e95e9..f1ac9f07 100644 --- a/src/test/kotlin/fr/shikkanime/controllers/api/AnimeControllerTest.kt +++ b/src/test/kotlin/fr/shikkanime/controllers/api/AnimeControllerTest.kt @@ -158,10 +158,10 @@ class AnimeControllerTest { }.apply { assertEquals(HttpStatusCode.OK, status) val findPrivateMember = memberService.findPrivateMember(identifier) - val followedAnimes = memberFollowAnimeService.getAllFollowedAnimes(findPrivateMember!!) + val followedAnimesUUID = memberFollowAnimeService.getAllFollowedAnimesUUID(findPrivateMember!!) assertNotNull(findPrivateMember) - assertEquals(1, followedAnimes.size) - assertEquals(anime1.uuid, followedAnimes.first().uuid) + assertEquals(1, followedAnimesUUID.size) + assertEquals(anime1.uuid, followedAnimesUUID.first()) } client.get("/api/v1/animes/weekly") { diff --git a/src/test/kotlin/fr/shikkanime/controllers/api/MemberControllerTest.kt b/src/test/kotlin/fr/shikkanime/controllers/api/MemberControllerTest.kt index ec127063..1e865cf9 100644 --- a/src/test/kotlin/fr/shikkanime/controllers/api/MemberControllerTest.kt +++ b/src/test/kotlin/fr/shikkanime/controllers/api/MemberControllerTest.kt @@ -5,11 +5,13 @@ import fr.shikkanime.dtos.GenericDto import fr.shikkanime.dtos.MemberDto import fr.shikkanime.entities.Anime import fr.shikkanime.entities.EpisodeMapping +import fr.shikkanime.entities.Member import fr.shikkanime.entities.enums.CountryCode import fr.shikkanime.entities.enums.EpisodeType import fr.shikkanime.module import fr.shikkanime.services.* import fr.shikkanime.utils.Constant +import fr.shikkanime.utils.MapCache import fr.shikkanime.utils.ObjectParser import io.ktor.client.request.* import io.ktor.client.statement.* @@ -49,6 +51,7 @@ class MemberControllerTest { memberService.deleteAll() episodeMappingService.deleteAll() animeService.deleteAll() + MapCache.invalidate(Member::class.java) } @Test @@ -143,10 +146,10 @@ class MemberControllerTest { }.apply { assertEquals(HttpStatusCode.OK, status) val findPrivateMember = memberService.findPrivateMember(identifier) - val followedAnimes = memberFollowAnimeService.getAllFollowedAnimes(findPrivateMember!!) + val followedAnimesUUID = memberFollowAnimeService.getAllFollowedAnimesUUID(findPrivateMember!!) assertNotNull(findPrivateMember) - assertEquals(1, followedAnimes.size) - assertEquals(anime.uuid, followedAnimes.first().uuid) + assertEquals(1, followedAnimesUUID.size) + assertEquals(anime.uuid, followedAnimesUUID.first()) } } } @@ -197,10 +200,10 @@ class MemberControllerTest { }.apply { assertEquals(HttpStatusCode.OK, status) val findPrivateMember = memberService.findPrivateMember(identifier) - val followedAnimes = memberFollowAnimeService.getAllFollowedAnimes(findPrivateMember!!) + val followedAnimesUUID = memberFollowAnimeService.getAllFollowedAnimesUUID(findPrivateMember!!) assertNotNull(findPrivateMember) - assertEquals(1, followedAnimes.size) - assertEquals(anime.uuid, followedAnimes.first().uuid) + assertEquals(1, followedAnimesUUID.size) + assertEquals(anime.uuid, followedAnimesUUID.first()) } client.delete("/api/v1/members/animes") { @@ -210,9 +213,9 @@ class MemberControllerTest { }.apply { assertEquals(HttpStatusCode.OK, status) val findPrivateMember = memberService.findPrivateMember(identifier) - val followedAnimes = memberFollowAnimeService.getAllFollowedAnimes(findPrivateMember!!) + val followedAnimesUUID = memberFollowAnimeService.getAllFollowedAnimesUUID(findPrivateMember!!) assertNotNull(findPrivateMember) - assertEquals(0, followedAnimes.size) + assertEquals(0, followedAnimesUUID.size) } } } @@ -254,10 +257,10 @@ class MemberControllerTest { }.apply { assertEquals(HttpStatusCode.OK, status) val findPrivateMember = memberService.findPrivateMember(identifier) - val followedEpisodes = memberFollowEpisodeService.getAllFollowedEpisodes(findPrivateMember!!) + val followedEpisodesUUID = memberFollowEpisodeService.getAllFollowedEpisodesUUID(findPrivateMember!!) assertNotNull(findPrivateMember) - assertEquals(1, followedEpisodes.size) - assertEquals(episode.uuid, followedEpisodes.first().uuid) + assertEquals(1, followedEpisodesUUID.size) + assertEquals(episode.uuid, followedEpisodesUUID.first()) } } } @@ -318,10 +321,10 @@ class MemberControllerTest { }.apply { assertEquals(HttpStatusCode.OK, status) val findPrivateMember = memberService.findPrivateMember(identifier) - val followedEpisodes = memberFollowEpisodeService.getAllFollowedEpisodes(findPrivateMember!!) + val followedEpisodesUUID = memberFollowEpisodeService.getAllFollowedEpisodesUUID(findPrivateMember!!) assertNotNull(findPrivateMember) - assertEquals(1, followedEpisodes.size) - assertEquals(episode.uuid, followedEpisodes.first().uuid) + assertEquals(1, followedEpisodesUUID.size) + assertEquals(episode.uuid, followedEpisodesUUID.first()) } client.delete("/api/v1/members/episodes") { @@ -331,7 +334,7 @@ class MemberControllerTest { }.apply { assertEquals(HttpStatusCode.OK, status) val findPrivateMember = memberService.findPrivateMember(identifier) - val followedEpisodes = memberFollowEpisodeService.getAllFollowedEpisodes(findPrivateMember!!) + val followedEpisodes = memberFollowEpisodeService.getAllFollowedEpisodesUUID(findPrivateMember!!) assertNotNull(findPrivateMember) assertEquals(0, followedEpisodes.size) } @@ -377,7 +380,7 @@ class MemberControllerTest { }.apply { assertEquals(HttpStatusCode.OK, status) val findPrivateMember = memberService.findPrivateMember(identifier) - val followedEpisodes = memberFollowEpisodeService.getAllFollowedEpisodes(findPrivateMember!!) + val followedEpisodes = memberFollowEpisodeService.getAllFollowedEpisodesUUID(findPrivateMember!!) assertNotNull(findPrivateMember) assertEquals(12, followedEpisodes.size) }