From f4f4fc53260eb67483dce406a963628273786a61 Mon Sep 17 00:00:00 2001
From: liusuyi <1951119284@qq.com>
Date: Sat, 30 May 2026 17:22:17 +0800
Subject: [PATCH] 优化

---
 ard-modules/ard-modules-work/src/main/java/com/ard/work/device/camera/service/PtzTask.java |   71 +++++++++++++++++++++++++++++------
 1 files changed, 59 insertions(+), 12 deletions(-)

diff --git a/ard-modules/ard-modules-work/src/main/java/com/ard/work/device/camera/service/PtzTask.java b/ard-modules/ard-modules-work/src/main/java/com/ard/work/device/camera/service/PtzTask.java
index 546430a..273e488 100644
--- a/ard-modules/ard-modules-work/src/main/java/com/ard/work/device/camera/service/PtzTask.java
+++ b/ard-modules/ard-modules-work/src/main/java/com/ard/work/device/camera/service/PtzTask.java
@@ -9,6 +9,9 @@
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
@@ -28,33 +31,38 @@
 
     private final Set<String> runningCamera = ConcurrentHashMap.newKeySet();
 
+    /** 缓存数据有效期: 超过此时间不再推送 */
+    private static final long DATA_VALID_MS = 5_000L;
+    /** 缓存数据淘汰阈值: 超过此时间从内存清掉 */
+    private static final long DATA_EVICT_MS = 60_000L;
+    /** 相机列表本地缓存 TTL */
+    private static final long CAMERA_LIST_TTL_MS = 30_000L;
+
+    private volatile List<ArdCamera> cachedCameraList = Collections.emptyList();
+    private volatile long cameraListExpireAt = 0L;
+
     /**
-     * 采集任务(不会堆积)
+     * 采集任务
      */
     @Scheduled(initialDelay = 5000, fixedDelay = 1000)
     public void startCollectTask() {
+        List<ArdCamera> cameraList = getCameraList();
+        if (cameraList.isEmpty()) return;
 
-        List<Object> cameraList = redisService.getCacheMapValues(CacheConstants.CAMERA_LIST);
-        if (cameraList == null || cameraList.isEmpty()) return;
-
-        for (Object obj : cameraList) {
-            ArdCamera camera = (ArdCamera) obj;
+        for (ArdCamera camera : cameraList) {
             String camId = camera.getId();
-
-            // ✅ 防重复执行
             if (!runningCamera.add(camId)) continue;
-
             ptzDataCollector.collectCamera(camera, runningCamera);
         }
     }
 
     /**
-     * 推送
+     * 推送任务
      */
     @Scheduled(fixedDelay = 1000)
     public void pushPTZ() {
         try {
-            List<PtzParamDTO> list = ptzCacheManager.getAllValidData(5000);
+            List<PtzParamDTO> list = ptzCacheManager.getAllValidData(DATA_VALID_MS);
             if (!list.isEmpty()) {
                 PTZWebSocketUtils.sendMessageAll(list);
             }
@@ -62,4 +70,43 @@
             log.error("推送PTZ异常", e);
         }
     }
-}
\ No newline at end of file
+
+    /**
+     * 清理过期缓存,防止已禁用/删除的相机数据残留
+     */
+    @Scheduled(fixedDelay = 60_000)
+    public void evictStaleCache() {
+        int n = ptzCacheManager.evictStale(DATA_EVICT_MS);
+        if (n > 0) {
+            log.debug("清理过期PTZ缓存 {} 条", n);
+        }
+    }
+
+    /**
+     * 本地缓存相机列表,降低 Redis QPS
+     */
+    private List<ArdCamera> getCameraList() {
+        long now = System.currentTimeMillis();
+        if (now < cameraListExpireAt) {
+            return cachedCameraList;
+        }
+        synchronized (this) {
+            if (now < cameraListExpireAt) {
+                return cachedCameraList;
+            }
+            List<Object> raw = redisService.getCacheMapValues(CacheConstants.CAMERA_LIST);
+            List<ArdCamera> list;
+            if (raw == null || raw.isEmpty()) {
+                list = Collections.emptyList();
+            } else {
+                list = new ArrayList<>(raw.size());
+                for (Object o : raw) {
+                    list.add((ArdCamera) o);
+                }
+            }
+            cachedCameraList = list;
+            cameraListExpireAt = now + CAMERA_LIST_TTL_MS;
+            return list;
+        }
+    }
+}

--
Gitblit v1.9.3