diff --git a/lime-infrastructure/src/main/java/com/programmers/lime/redis/chat/ChatCursorCacheReader.java b/lime-infrastructure/src/main/java/com/programmers/lime/redis/chat/ChatCursorCacheReader.java index f36e914f..cc752184 100644 --- a/lime-infrastructure/src/main/java/com/programmers/lime/redis/chat/ChatCursorCacheReader.java +++ b/lime-infrastructure/src/main/java/com/programmers/lime/redis/chat/ChatCursorCacheReader.java @@ -6,7 +6,6 @@ import java.util.List; import java.util.Objects; -import org.springframework.data.redis.connection.ReturnType; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; @@ -22,6 +21,8 @@ public class ChatCursorCacheReader { private final RedisTemplate redisTemplate; + private final ChatLLScriptManager chatLLScriptManager; + public ChatCursorCacheResult readByCursor( final Long roomId, final String cursorId, @@ -112,12 +113,8 @@ private List readCursorCachesByLua( final String currCursorId, final int size ) { - String linkedListScript = ChatLuaScriptManager.getReadByLinkedListScript(); - // 스크립트 실행 - List result = redisTemplate.execute( - connection -> connection.eval(linkedListScript.getBytes(), ReturnType.MULTI, 0, - roomId.toString().getBytes(), currCursorId.getBytes(), String.valueOf(size).getBytes()), true); + List result = chatLLScriptManager.executeLLScript(roomId, currCursorId, size); if (result == null || result.isEmpty()) { return List.of(); @@ -131,4 +128,5 @@ private List readCursorCachesByLua( return chatCursorCaches; } + } diff --git a/lime-infrastructure/src/main/java/com/programmers/lime/redis/chat/ChatLLScriptManager.java b/lime-infrastructure/src/main/java/com/programmers/lime/redis/chat/ChatLLScriptManager.java new file mode 100644 index 00000000..1b68f272 --- /dev/null +++ b/lime-infrastructure/src/main/java/com/programmers/lime/redis/chat/ChatLLScriptManager.java @@ -0,0 +1,55 @@ +package com.programmers.lime.redis.chat; + +import java.util.List; + +import org.springframework.data.redis.RedisSystemException; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.connection.ReturnType; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import com.programmers.lime.redis.chat.model.LLReadScript; + +import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class ChatLLScriptManager { + + private final RedisTemplate redisTemplate; + + private final LLReadScript llReadScript; + private String llScriptSha1; + + private static boolean isNoscript(final RedisSystemException e) { + return e.getCause().getMessage().contains("NOSCRIPT"); + } + + @PostConstruct + public void initLLSha1() { + byte[] llBytes = llReadScript.getReadByLinkedListScriptBytes(); + llScriptSha1 = redisTemplate.execute((RedisConnection connection) -> + connection.scriptLoad(llBytes) + ); + } + + public List executeLLScript(final Long roomId, final String currCursorId, final int size) { + try { + return executeEvalSha(roomId, currCursorId, size); + } catch (RedisSystemException e) { + if (isNoscript(e)) { + initLLSha1(); + return executeEvalSha(roomId, currCursorId, size); + } + throw e; + } + } + + private List executeEvalSha(final Long roomId, final String currCursorId, final int size) { + return redisTemplate.execute( + connection -> connection.evalSha(llScriptSha1.getBytes(), ReturnType.MULTI, 0, + roomId.toString().getBytes(), currCursorId.getBytes(), String.valueOf(size).getBytes()), true + ); + } +} diff --git a/lime-infrastructure/src/main/java/com/programmers/lime/redis/chat/ChatLuaScriptManager.java b/lime-infrastructure/src/main/java/com/programmers/lime/redis/chat/model/LLReadScript.java similarity index 66% rename from lime-infrastructure/src/main/java/com/programmers/lime/redis/chat/ChatLuaScriptManager.java rename to lime-infrastructure/src/main/java/com/programmers/lime/redis/chat/model/LLReadScript.java index 07c92ab5..ce77b0e2 100644 --- a/lime-infrastructure/src/main/java/com/programmers/lime/redis/chat/ChatLuaScriptManager.java +++ b/lime-infrastructure/src/main/java/com/programmers/lime/redis/chat/model/LLReadScript.java @@ -1,4 +1,4 @@ -package com.programmers.lime.redis.chat; +package com.programmers.lime.redis.chat.model; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -10,22 +10,22 @@ import jakarta.annotation.PostConstruct; @Component -public class ChatLuaScriptManager { +public class LLReadScript { - private static String readBylinkedListScript; + private String readByLinkedListScript; @PostConstruct public void init() { try { ClassPathResource cpr = new ClassPathResource("ReadByLinkedList.lua"); byte[] bdata = FileCopyUtils.copyToByteArray(cpr.getInputStream()); - readBylinkedListScript = new String(bdata, StandardCharsets.UTF_8); + readByLinkedListScript = new String(bdata, StandardCharsets.UTF_8); } catch (IOException e) { throw new RuntimeException("Failed to load redis script", e); } } - public static String getReadByLinkedListScript() { - return readBylinkedListScript; + public byte[] getReadByLinkedListScriptBytes() { + return readByLinkedListScript.getBytes(StandardCharsets.UTF_8); } }