Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 장소 거리 데이터 cache 적용 #168

Merged
merged 18 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import com.piikii.application.domain.place.Place
import com.piikii.application.domain.schedule.Schedule
import com.piikii.application.port.input.CourseUseCase
import com.piikii.application.port.input.dto.response.CourseResponse
import com.piikii.application.port.output.cache.CourseCachePort
import com.piikii.application.port.output.persistence.CourseQueryPort
import com.piikii.application.port.output.persistence.PlaceCommandPort
import com.piikii.application.port.output.persistence.PlaceQueryPort
import com.piikii.application.port.output.persistence.RoomQueryPort
import com.piikii.application.port.output.persistence.ScheduleQueryPort
import com.piikii.application.port.output.persistence.VoteQueryPort
import com.piikii.application.port.output.web.NavigationPort
import com.piikii.common.exception.ExceptionCode
import com.piikii.common.exception.PiikiiException
import org.springframework.stereotype.Service
Expand All @@ -27,7 +27,7 @@ class CourseService(
private val placeQueryPort: PlaceQueryPort,
private val placeCommandPort: PlaceCommandPort,
private val voteQueryPort: VoteQueryPort,
private val navigationPort: NavigationPort,
private val courseCachePort: CourseCachePort,
) : CourseUseCase {
override fun isCourseExist(roomUid: UuidTypeId): Boolean {
return courseQueryPort.isCourseExist(roomUid)
Expand Down Expand Up @@ -123,17 +123,11 @@ class CourseService(
confirmedPlace: Place,
): CoursePlace {
val coordinate = confirmedPlace.getCoordinate()

return CoursePlace.from(
schedule = schedule,
place = confirmedPlace,
coordinate = coordinate,
distance =
preCoursePlace?.coordinate?.let { preCoordinate ->
coordinate.let { coordinate ->
navigationPort.getDistance(start = preCoordinate, end = coordinate)
}
},
distance = courseCachePort.getDistance(preCoursePlace, confirmedPlace),
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.piikii.application.domain.course

data class Distance(
val totalDistanceMeter: Int?,
val totalTimeMinute: Int?,
val totalDistanceMeter: Int? = null,
val totalTimeMinute: Int? = null,
) {
companion object {
val EMPTY = Distance(null, null)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.piikii.application.port.output.cache

import com.piikii.application.domain.course.CoursePlace
import com.piikii.application.domain.course.Distance
import com.piikii.application.domain.place.Place

interface CourseCachePort {
fun getDistance(
startPlace: CoursePlace?,
endPlace: Place,
): Distance?
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import com.piikii.application.domain.fixture.RoomFixture
import com.piikii.application.domain.fixture.ScheduleFixture
import com.piikii.application.domain.fixture.VoteFixture
import com.piikii.application.domain.vote.VoteResult
import com.piikii.application.port.output.cache.CourseCachePort
import com.piikii.application.port.output.persistence.CourseQueryPort
import com.piikii.application.port.output.persistence.PlaceCommandPort
import com.piikii.application.port.output.persistence.PlaceQueryPort
import com.piikii.application.port.output.persistence.RoomQueryPort
import com.piikii.application.port.output.persistence.ScheduleQueryPort
import com.piikii.application.port.output.persistence.VoteQueryPort
import com.piikii.application.port.output.web.NavigationPort
import com.piikii.common.exception.PiikiiException
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
Expand Down Expand Up @@ -45,7 +45,7 @@ class CourseServiceTest {
lateinit var voteQueryPort: VoteQueryPort

@Mock
lateinit var navigationPort: NavigationPort
lateinit var courseCachePort: CourseCachePort

@Mock
lateinit var courseQueryPort: CourseQueryPort
Expand Down Expand Up @@ -132,9 +132,17 @@ class CourseServiceTest {
),
)

val coordinate1 = Coordinate(places[0].longitude, places[0].latitude)
val coordinate2 = Coordinate(places[2].longitude, places[2].latitude)
given(navigationPort.getDistance(coordinate1, coordinate2))
val coursePlace =
CoursePlace.from(
schedule = schedules[0],
place = places[0],
coordinate = Coordinate(places[0].longitude, places[0].latitude),
distance = Distance.EMPTY,
)

given(courseCachePort.getDistance(null, places[0]))
.willReturn(Distance.EMPTY)
given(courseCachePort.getDistance(coursePlace, places[2]))
.willReturn(Distance(100, 5))

val updatedPlace = places[2].copy(confirmed = true)
Expand Down
1 change: 1 addition & 0 deletions piikii-bootstrap/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ spring:
- classpath:avocado-config/application.yml
- classpath:tmap-config/application.yml
- classpath:application-actuator.yml
- classpath:cache-config/application.yml
application:
name: "piikii"
messages:
Expand Down
1 change: 1 addition & 0 deletions piikii-bootstrap/src/test/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ spring:
- classpath:avocado-config/application.yml
- classpath:database-config/application-test.yml
- classpath:tmap-config/application.yml
- classpath:cache-config/application.yml
application:
name: "piikii"
messages:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.piikii.output.redis.adapter

import com.piikii.application.domain.course.CoursePlace
import com.piikii.application.domain.course.Distance
import com.piikii.application.domain.place.Place
import com.piikii.application.port.output.cache.CourseCachePort
import com.piikii.application.port.output.web.NavigationPort
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Component

@Component
class CourseRedisCacheAdapter(
KimDoubleB marked this conversation as resolved.
Show resolved Hide resolved
private val navigationPort: NavigationPort,
) : CourseCachePort {
@Cacheable(
value = ["Distances"],
key = "#startPlace?.placeId + '_' + #endPlace.id",
cacheManager = "cacheManager",
condition = "#startPlace != null",
unless = "#result == null",
KimDoubleB marked this conversation as resolved.
Show resolved Hide resolved
)
override fun getDistance(
startPlace: CoursePlace?,
endPlace: Place,
KimDoubleB marked this conversation as resolved.
Show resolved Hide resolved
): Distance? {
return startPlace?.coordinate?.let { preCoordinate ->
endPlace.getCoordinate().let { coordinate ->
navigationPort.getDistance(start = preCoordinate, end = coordinate)
}
}
KimDoubleB marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.piikii.output.redis.config

import org.springframework.cache.CacheManager
import org.springframework.cache.annotation.EnableCaching
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.redis.cache.RedisCacheConfiguration
import org.springframework.data.redis.cache.RedisCacheManager
import org.springframework.data.redis.connection.RedisConnectionFactory
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer
import org.springframework.data.redis.serializer.RedisSerializationContext
import org.springframework.data.redis.serializer.StringRedisSerializer
import java.time.Duration

@Configuration
@EnableCaching
class RedisCacheConfig {
KimDoubleB marked this conversation as resolved.
Show resolved Hide resolved
@Bean
fun cacheManager(redisConnectionFactory: RedisConnectionFactory): CacheManager {
val redisCacheConfiguration =
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofDays(7))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(StringRedisSerializer()))
.serializeValuesWith(
RedisSerializationContext.SerializationPair.fromSerializer(
GenericJackson2JsonRedisSerializer(),
),
)

return RedisCacheManager.RedisCacheManagerBuilder
.fromConnectionFactory(redisConnectionFactory)
.cacheDefaults(redisCacheConfiguration)
.build()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,28 @@ import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.databind.json.JsonMapper
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.redis.connection.RedisPassword
import org.springframework.data.redis.connection.RedisStandaloneConfiguration
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer
import org.springframework.data.redis.serializer.StringRedisSerializer

// TODO: 필요 시에 등록을 위해 설정
// @Configuration
@Configuration
@EnableRedisRepositories
class RedisConfig {
@Value("\${redis.host}")
private val redisHost: String? = null

@Value("\${redis.port}")
private val redisPort = 0

@Value("\${redis.password}")
private val redisPassword: String? = null
KimDoubleB marked this conversation as resolved.
Show resolved Hide resolved

@Bean
fun objectMapper(): ObjectMapper {
return JsonMapper.builder()
K-Diger marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -34,11 +42,21 @@ class RedisConfig {

@Bean
fun lettuceConnectionFactory(): LettuceConnectionFactory {
return LettuceConnectionFactory(redisHost!!, redisPort)
val redisConfig = RedisStandaloneConfiguration()
redisConfig.hostName = redisHost!!
redisConfig.port = redisPort
redisConfig.password = RedisPassword.of(redisPassword)
KimDoubleB marked this conversation as resolved.
Show resolved Hide resolved

val clientConfig =
LettuceClientConfiguration.builder()
.useSsl()
.build()

return LettuceConnectionFactory(redisConfig, clientConfig)
}

@Bean
fun redistemplate(): RedisTemplate<String, Any> {
fun redisTemplate(): RedisTemplate<String, Any> {
K-Diger marked this conversation as resolved.
Show resolved Hide resolved
val redisTemplate = RedisTemplate<String, Any>()
redisTemplate.connectionFactory = lettuceConnectionFactory()
redisTemplate.keySerializer = StringRedisSerializer()
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
redis:
host: ${REDIS_HOST}
port: 6379
password: ${REDIS_PASSWORD}
ssl: true
Loading