Skip to content

Commit

Permalink
2369 add caching
Browse files Browse the repository at this point in the history
  • Loading branch information
Elena Moshnikova committed Nov 16, 2024
1 parent 64d47dc commit a0e5f7e
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 63 deletions.
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-batch")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-cache")
implementation("org.springframework.security:spring-security-test")
implementation("org.springframework.boot:spring-boot-devtools")

implementation("org.postgresql:postgresql")
implementation("org.flywaydb:flyway-core:$flywayVersion")

Expand Down
8 changes: 8 additions & 0 deletions src/main/kotlin/com/epam/brn/config/CachingConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.epam.brn.config

import org.springframework.cache.annotation.EnableCaching
import org.springframework.context.annotation.Configuration

@Configuration
@EnableCaching
class CachingConfig
7 changes: 7 additions & 0 deletions src/main/kotlin/com/epam/brn/model/ExerciseGroup.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ data class ExerciseGroup(
series = series.map { series -> series.id }.toMutableList()
)

fun toDtoWithoutSeries() = ExerciseGroupDto(
id = id,
locale = locale,
name = name,
description = description
)

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
Expand Down
28 changes: 10 additions & 18 deletions src/main/kotlin/com/epam/brn/service/ExerciseGroupsService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.epam.brn.model.ExerciseGroup
import com.epam.brn.repo.ExerciseGroupRepository
import org.apache.logging.log4j.kotlin.logger
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Service
import java.util.Optional

Expand All @@ -15,34 +16,25 @@ class ExerciseGroupsService(
) {
private val log = logger()

fun findAllGroups(): List<ExerciseGroupDto> {
log.debug("Searching all groups")
val groups: List<ExerciseGroup> = exerciseGroupRepository.findAll()
return groups.map { group -> group.toDto() }
}

@Cacheable("groupsById")
fun findGroupDtoById(groupId: Long): ExerciseGroupDto {
log.debug("Searching group with id=$groupId")
val group: Optional<ExerciseGroup> = exerciseGroupRepository.findById(groupId)
return group.map { x -> x.toDto() }
.orElseThrow { EntityNotFoundException("no group was found for id=$groupId") }
return group.map { it.toDto() }
.orElseThrow { EntityNotFoundException("No group was found for id=$groupId") }
}

@Cacheable("groupsByLocale")
fun findByLocale(locale: String): List<ExerciseGroupDto> {
log.debug("Searching groups by locale=$locale")
if (locale.isEmpty())
return exerciseGroupRepository.findAll().map { group -> group.toDto() }
return exerciseGroupRepository.findByLocale(locale)
.map { group -> group.toDto() }
}

fun save(exerciseGroup: ExerciseGroup): ExerciseGroup {
return exerciseGroupRepository.save(exerciseGroup)
return if (locale.isEmpty())
exerciseGroupRepository.findAll().map { group -> group.toDto() }
else exerciseGroupRepository.findByLocale(locale)
.map { group -> group.toDtoWithoutSeries() }
}

fun findGroupByCode(groupCode: String): ExerciseGroup {
log.debug("Searching group with code=$groupCode")
return exerciseGroupRepository.findByCode(groupCode)
.orElseThrow { EntityNotFoundException("no group was found for code=$groupCode") }
.orElseThrow { EntityNotFoundException("No group was found for code=$groupCode") }
}
}
8 changes: 3 additions & 5 deletions src/main/kotlin/com/epam/brn/service/SeriesService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,28 @@ package com.epam.brn.service

import com.epam.brn.dto.SeriesDto
import com.epam.brn.exception.EntityNotFoundException
import com.epam.brn.model.Series
import com.epam.brn.repo.SeriesRepository
import org.apache.logging.log4j.kotlin.logger
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Service

@Service
class SeriesService(private val seriesRepository: SeriesRepository) {

private val log = logger()

@Cacheable("series")
fun findSeriesForGroup(groupId: Long): List<SeriesDto> {
log.debug("try to find series for groupId=$groupId")
val series = seriesRepository.findByExerciseGroupLike(groupId)
return series.map { seriesEntry -> seriesEntry.toDto() }
}

@Cacheable("seriesDto")
fun findSeriesDtoForId(seriesId: Long): SeriesDto {
log.debug("try to find series for seriesId=$seriesId")
val series = seriesRepository.findById(seriesId)
.orElseThrow { EntityNotFoundException("no series was found for id=$seriesId") }
return series.toDto()
}

fun save(series: Series): Series {
return seriesRepository.save(series)
}
}
24 changes: 11 additions & 13 deletions src/main/kotlin/com/epam/brn/service/SubGroupService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import com.epam.brn.repo.ExerciseRepository
import com.epam.brn.repo.SeriesRepository
import com.epam.brn.repo.SubGroupRepository
import org.apache.logging.log4j.kotlin.logger
import org.springframework.cache.annotation.CacheEvict
import org.springframework.cache.annotation.CachePut
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Service
import java.util.stream.Collectors

@Service
class SubGroupService(
Expand All @@ -21,25 +23,23 @@ class SubGroupService(
) {
private val log = logger()

@Cacheable("subgroupsBySeriesId")
fun findSubGroupsForSeries(seriesId: Long): List<SubGroupResponse> {
log.debug("Try to find subGroups for seriesId=$seriesId")
return subGroupRepository
.findBySeriesId(seriesId)
.parallelStream()
.map { subGroup -> toSubGroupResponse(subGroup) }
.collect(Collectors.toList())
.sortedWith(compareBy({ it.level }, { it.withPictures }))
}

@Cacheable("subgroupsBySubGroupId")
fun findById(subGroupId: Long): SubGroupResponse {
log.debug("try to find SubGroup by Id=$subGroupId")
val subGroup = subGroupRepository.findById(subGroupId)
.orElseThrow { EntityNotFoundException("No subGroup was found by id=$subGroupId.") }
return toSubGroupResponse(subGroup)
}

@CacheEvict("subgroupsBySeriesId", "subgroupsBySubGroupId")
fun deleteSubGroupById(subGroupId: Long) {
log.debug("try to delete SubGroup by Id=$subGroupId")
if (subGroupRepository.existsById(subGroupId)) {
if (exerciseRepository.existsBySubGroupId(subGroupId))
throw IllegalArgumentException("Can not delete subGroup because there are exercises that refer to the subGroup.")
Expand All @@ -48,8 +48,8 @@ class SubGroupService(
throw IllegalArgumentException("Can not delete subGroup because subGroup is not found by this id.")
}

@CachePut("subgroupsBySeriesId", "subgroupsBySubGroupId")
fun updateSubGroupById(subGroupId: Long, subGroupChangeRequest: SubGroupChangeRequest): SubGroupResponse {
log.debug("try to update SubGroup by Id=$subGroupId")
val subGroup = subGroupRepository.findById(subGroupId)
.orElseThrow { EntityNotFoundException("Can not update subGroup because subGroup is not found by this id.") }
subGroup.withPictures = subGroupChangeRequest.withPictures
Expand All @@ -59,15 +59,13 @@ class SubGroupService(

fun addSubGroupToSeries(subGroupRequest: SubGroupRequest, seriesId: Long): SubGroupResponse {
log.debug("try to find subgroup by name=${subGroupRequest.name} and the level=${subGroupRequest.level}")
val existSubGroup = subGroupRepository.findByNameAndLevel(subGroupRequest.name, subGroupRequest.level!!)
val level = subGroupRequest.level ?: throw IllegalArgumentException("Level is required")
val existSubGroup = subGroupRepository.findByNameAndLevel(subGroupRequest.name, level)
if (existSubGroup != null)
throw IllegalArgumentException("The subgroup with name=${subGroupRequest.name} and the level=${subGroupRequest.level} already exists!")
log.debug("try to find Series by Id=$seriesId")
throw IllegalArgumentException("The subgroup with name=${subGroupRequest.name} and the level=$level already exists!")
val series = seriesRepository.findById(seriesId)
.orElseThrow { EntityNotFoundException("No series was found by id=$seriesId.") }
val subGroup = subGroupRequest.toModel(series)
val savedSubGroup = subGroupRepository.save(subGroup)
return toSubGroupResponse(savedSubGroup)
return toSubGroupResponse(subGroupRepository.save(subGroupRequest.toModel(series)))
}

fun toSubGroupResponse(subGroup: SubGroup): SubGroupResponse {
Expand Down
13 changes: 7 additions & 6 deletions src/main/kotlin/com/epam/brn/service/TaskService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import com.epam.brn.repo.ResourceRepository
import com.epam.brn.repo.TaskRepository
import com.epam.brn.service.cloud.CloudService
import org.apache.logging.log4j.kotlin.logger
import org.springframework.cache.annotation.CacheEvict
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

Expand All @@ -33,6 +35,7 @@ class TaskService(
) {
private val log = logger()

@Cacheable("tasksByExerciseId")
fun getTasksByExerciseId(exerciseId: Long): List<Any> {
val exercise: Exercise = exerciseRepository.findById(exerciseId)
.orElseThrow { EntityNotFoundException("No exercise found for id=$exerciseId") }
Expand All @@ -51,6 +54,7 @@ class TaskService(
}
}

@Cacheable("tasksById")
fun getTaskById(taskId: Long): Any {
log.debug("Searching task with id=$taskId")
val task =
Expand All @@ -75,6 +79,7 @@ class TaskService(
}
}

@CacheEvict("tasksByExerciseId", "tasksById")
@Transactional
fun save(task: Task): Task {
val resources = mutableSetOf<Resource>()
Expand All @@ -85,13 +90,9 @@ class TaskService(
}
}

val vowels = "а,е,ё,и,о,у,э,ы,ю,я".toCharArray()
private val vowelSet = setOf('а', 'е', 'ё', 'и', 'о', 'у', 'э', 'ы', 'ю', 'я')

fun String.findSyllableCount(): Int {
var syllableCount = 0
this.toCharArray().forEach { if (vowels.contains(it)) syllableCount++ }
return syllableCount
}
fun String.findSyllableCount(): Int = count { it in vowelSet }

fun Task.toDetailWordsTaskDto(exerciseType: ExerciseType) = TaskResponse(
id = id!!,
Expand Down
8 changes: 2 additions & 6 deletions src/main/kotlin/com/epam/brn/service/UrlConversionService.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.epam.brn.service

import com.epam.brn.service.cloud.CloudService
import org.apache.logging.log4j.kotlin.logger
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service

Expand All @@ -10,12 +9,9 @@ class UrlConversionService(private val cloudService: CloudService) {
@Value("\${aws.folderForThemePictures}")
private lateinit var folderForThemePictures: String

private val log = logger()

fun makeUrlForNoise(noiseUrl: String?): String {
if (noiseUrl.isNullOrEmpty())
return ""
return cloudService.baseFileUrl() + noiseUrl
return if (noiseUrl.isNullOrEmpty()) ""
else cloudService.baseFileUrl() + noiseUrl
}

fun makeUrlForSubGroupPicture(subGroupCode: String): String =
Expand Down
15 changes: 0 additions & 15 deletions src/test/kotlin/com/epam/brn/service/ExerciseGroupServiceTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import io.mockk.impl.annotations.MockK
import io.mockk.junit5.MockKExtension
import io.mockk.mockk
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import java.util.Optional
Expand All @@ -24,20 +23,6 @@ internal class ExerciseGroupServiceTest {
@InjectMockKs
lateinit var exerciseGroupsService: ExerciseGroupsService

@Test
fun `should get all groups`() {
// GIVEN
val exerciseGroupMock: ExerciseGroup = mockk(relaxed = true)
val exerciseGroupDtoMock = ExerciseGroupDto(id = 1, locale = "en", name = "name", description = "descr")

every { exerciseGroupMock.toDto() } returns (exerciseGroupDtoMock)
every { exerciseGroupRepository.findAll() } returns (listOf(exerciseGroupMock))
// WHEN
val actualResult: List<ExerciseGroupDto> = exerciseGroupsService.findAllGroups()
// THEN
assertTrue(actualResult.contains(exerciseGroupDtoMock))
}

@Test
fun `should get group by id`() {
// GIVEN
Expand Down

0 comments on commit a0e5f7e

Please sign in to comment.