Skip to content

Commit

Permalink
feat: 캐싱을 위한 레디스 요청 파이프라이닝
Browse files Browse the repository at this point in the history
  • Loading branch information
Dltmd202 committed Aug 24, 2024
1 parent 9843607 commit f301aa8
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.backgu.amaker.infra.jpa.chat.repository.ChatRoomRepository
import com.backgu.amaker.infra.jpa.chat.repository.ChatRoomUserRepository
import com.backgu.amaker.infra.redis.chat.repository.ChatCacheRepository
import com.backgu.amaker.infra.redis.chat.repository.ChatRoomUserCacheRepository
import com.backgu.amaker.infra.redis.chat.repository.ChatPipelinedQueryRepository
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

Expand Down Expand Up @@ -43,12 +44,14 @@ class ChatServiceConfig {
fun chatUserCacheService(
chatCacheService: ChatCacheService,
userCacheService: UserCacheService,
chatPipelinedQueryRepository: ChatPipelinedQueryRepository,
chatRoomUserCacheService: ChatRoomUserCacheService,
userService: UserService,
chatService: ChatService,
eventAssignedUserService: EventAssignedUserService,
) = ChatUserCacheFacadeService(
chatCacheService,
chatPipelinedQueryRepository,
userCacheService,
chatRoomUserCacheService,
userService,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,6 @@ class ChatFacadeService(
?.let { return ChatListDto.of(chatQuery, it.map { chatWithUser -> ChatWithUserDto.of(chatWithUser) }) }

val chatList = chatQueryService.findAfterChatList(chatQuery.chatRoomId, chatQuery.cursor, chatQuery.size)
for (defaultChatWithUser in chatList) {
println(defaultChatWithUser.id)
}

val eventMap =
eventService.findEventByIdsToMap(chatList.filter { ChatType.isEventChat(it.chatType) }.map { it.id })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ import com.backgu.amaker.domain.user.User
import com.backgu.amaker.infra.redis.chat.data.ChatWithUserCache
import com.backgu.amaker.infra.redis.chat.data.DefaultChatWithUserCache
import com.backgu.amaker.infra.redis.chat.data.EventChatWithUserCache
import com.backgu.amaker.infra.redis.chat.repository.ChatPipelinedQueryRepository
import org.springframework.stereotype.Service
import org.springframework.transaction.event.TransactionalEventListener

@Service
class ChatUserCacheFacadeService(
private val chatCacheService: ChatCacheService,
private val chatPipelinedQueryRepository: ChatPipelinedQueryRepository,
private val userCacheService: UserCacheService,
private val chatRoomUserCacheService: ChatRoomUserCacheService,
private val userService: UserService,
Expand Down Expand Up @@ -103,7 +105,21 @@ class ChatUserCacheFacadeService(
.map { chat -> mapChatToDto(chatRoomId, chat, cachedUsersMap) }
}

fun mapChatToDto(
fun findAfterChatsWithPipelinedQuery(
chatRoomId: Long,
cursor: Long,
count: Int,
): List<ChatWithUser<*>>? =
chatPipelinedQueryRepository.findAfterChats(chatRoomId, cursor, count)?.let { chats ->
userCacheService
.findAllByUserIds(chatRoomUserCacheService.findUserIds(chatRoomId).toList())
.associateBy { it.id }
.let { cachedUsersMap ->
chats.map { chat -> mapChatToDto(chatRoomId, chat, cachedUsersMap) }
}
}

private fun mapChatToDto(
chatRoomId: Long,
chat: ChatWithUserCache<*>,
cachedUsersMap: Map<String, User>,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.backgu.amaker.infra.redis.chat.repository

import com.backgu.amaker.infra.redis.chat.data.ChatWithUserCache
import com.fasterxml.jackson.databind.ObjectMapper
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.data.redis.core.script.RedisScript
import org.springframework.stereotype.Repository

@Repository
class ChatPipelinedQueryRepository(
private val redisChatTemplate: RedisTemplate<String, String>,
private val timeObjectMapper: ObjectMapper,
) {
companion object {
const val PREFIX = "chatRoom:"

fun key(chatRoomId: Long) = "$PREFIX$chatRoomId"

const val AFTER_CHAT_SCRIPT =
"""
local key = KEYS[1]
local cursor = tonumber(ARGV[1])
local count = tonumber(ARGV[2])
local firstResult = redis.call('ZRANGE', key, 0, 0, 'WITHSCORES')
if #firstResult > 0 then
local firstChat = firstResult[1]
local firstScore = tonumber(firstResult[2]) -- 첫 번째 요소의 score 값을 가져옴
if firstScore > cursor then
local result = redis.call('ZRANGEBYSCORE', key, cursor + 1, math.huge, 'LIMIT', 0, count)
if #result > 0 then
return table.concat(result, ",")
else
return ""
end
else
return firstChat
end
else
return nil
end
"""
}

fun findAfterChats(
chatRoomId: Long,
cursor: Long,
count: Int,
): List<ChatWithUserCache<*>>? {
val result: List<String> =
redisChatTemplate.execute(
RedisScript.of(AFTER_CHAT_SCRIPT.trimIndent(), List::class.java as Class<List<String>>),
listOf(key(chatRoomId)),
cursor.toString(),
count.toString(),
)

return result.map { chat ->
timeObjectMapper.readValue(chat, ChatWithUserCache::class.java)
}
}
}

0 comments on commit f301aa8

Please sign in to comment.