liuchengsen преди 1 месец
родител
ревизия
05acb1544a
променени са 1 файла, в които са добавени 18 реда и са изтрити 2 реда
  1. 18 2
      backend-java/src/main/java/com/pharmacopoeia/service/RetrieverService.java

+ 18 - 2
backend-java/src/main/java/com/pharmacopoeia/service/RetrieverService.java

@@ -19,9 +19,12 @@ public class RetrieverService {
     private final StringRedisTemplate redis;
     private final boolean redisAvailable;
 
-    // Embedding 缓存 key 前缀 + TTL(7 天)
+    // Embedding 缓存 key 前缀 + TTL(7 天,续期 3 次后不再续
     private static final String EMBED_CACHE_PREFIX = "aiyaodian:embed:";
+    private static final String EMBED_RENEW_PREFIX = "aiyaodian:embed:renew:";
     private static final Duration EMBED_CACHE_TTL = Duration.ofDays(7);
+    private static final Duration EMBED_MAX_TTL = Duration.ofDays(30);
+    private static final int MAX_RENEWALS = 3;
 
     private static final List<String> NEGATION_PATTERNS = List.of(
             "不是", "没有", "并非", "算不上", "怎么会是", "不可能", "不会",
@@ -85,7 +88,20 @@ public class RetrieverService {
         String key = cacheKey(query);
         try {
             String cached = redis.opsForValue().get(key);
-            if (cached != null) return decodeVec(cached);
+            if (cached != null) {
+                // 滑动续期:最多续 3 次,总时长不超 30 天
+                var renewKey = EMBED_RENEW_PREFIX + key.substring(EMBED_CACHE_PREFIX.length());
+                try {
+                    var ops = redis.opsForValue();
+                    var cntVal = ops.get(renewKey);
+                    int renewals = cntVal != null ? Integer.parseInt(cntVal) : 0;
+                    if (renewals < MAX_RENEWALS) {
+                        redis.expire(key, EMBED_CACHE_TTL);
+                        ops.set(renewKey, String.valueOf(renewals + 1), EMBED_MAX_TTL);
+                    }
+                } catch (Exception ignored) {}
+                return decodeVec(cached);
+            }
         } catch (DataAccessException ignored) {
             // Redis 异常时降级到远程调用
         }