Skip to content

Commit

Permalink
2369 add caching (#2645)
Browse files Browse the repository at this point in the history
* 2369 some optimization and adding caching
  • Loading branch information
ElenaSpb authored Nov 17, 2024
1 parent a107081 commit 997bfbf
Show file tree
Hide file tree
Showing 15 changed files with 183 additions and 145 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
10 changes: 9 additions & 1 deletion src/main/kotlin/com/epam/brn/model/ExerciseGroup.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.epam.brn.upload.csv.group.GroupRecord
import javax.persistence.CascadeType
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.FetchType
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
Expand All @@ -27,7 +28,7 @@ data class ExerciseGroup(
val name: String,
@Column
val description: String? = "",
@OneToMany(mappedBy = "exerciseGroup", cascade = [(CascadeType.ALL)])
@OneToMany(mappedBy = "exerciseGroup", fetch = FetchType.LAZY, cascade = [(CascadeType.ALL)])
val series: MutableList<Series> = ArrayList()
) {
constructor(record: GroupRecord) : this(
Expand All @@ -45,6 +46,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.toDtoWithoutSeries() }
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
27 changes: 12 additions & 15 deletions src/test/kotlin/com/epam/brn/integration/BaseIT.kt
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
package com.epam.brn.integration

import com.epam.brn.model.Role
import com.epam.brn.enums.BrnGender
import com.epam.brn.model.Exercise
import com.epam.brn.model.ExerciseGroup
import com.epam.brn.enums.BrnGender
import com.epam.brn.model.Role
import com.epam.brn.model.Series
import com.epam.brn.model.StudyHistory
import com.epam.brn.model.SubGroup
import com.epam.brn.model.UserAccount
import com.epam.brn.repo.RoleRepository
import com.epam.brn.repo.ExerciseGroupRepository
import com.epam.brn.repo.ExerciseRepository
import com.epam.brn.repo.RoleRepository
import com.epam.brn.repo.SeriesRepository
import com.epam.brn.repo.StudyHistoryRepository
import com.epam.brn.repo.SubGroupRepository
import com.epam.brn.repo.TaskRepository
import com.epam.brn.repo.UserAccountRepository
import com.fasterxml.jackson.databind.ObjectMapper
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.time.temporal.ChronoUnit
import org.amshove.kluent.internal.platformClassName
import org.junit.jupiter.api.Tag
import org.springframework.beans.factory.annotation.Autowired
Expand All @@ -24,9 +28,6 @@ import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.ActiveProfiles
import org.springframework.test.web.servlet.MockMvc
import org.testcontainers.junit.jupiter.Testcontainers
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.time.temporal.ChronoUnit

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
Expand All @@ -43,22 +44,18 @@ abstract class BaseIT {

@Autowired
private lateinit var userAccountRepository: UserAccountRepository

@Autowired
private lateinit var studyHistoryRepository: StudyHistoryRepository

@Autowired
private lateinit var exerciseRepository: ExerciseRepository

private lateinit var exerciseGroupRepository: ExerciseGroupRepository
@Autowired
private lateinit var seriesRepository: SeriesRepository
@Autowired
private lateinit var subGroupRepository: SubGroupRepository

@Autowired
private lateinit var exerciseGroupRepository: ExerciseGroupRepository

private lateinit var exerciseRepository: ExerciseRepository
@Autowired
private lateinit var seriesRepository: SeriesRepository

private lateinit var taskRepository: TaskRepository
@Autowired
private lateinit var roleRepository: RoleRepository

Expand Down
Loading

0 comments on commit 997bfbf

Please sign in to comment.