Bläddra i källkod

fix(cockpit): round snapshot cache ttl up

Kazerin 3 veckor sedan
förälder
incheckning
5191e7b74e

+ 22 - 0
pipe-network-service/zksy-admin/src/test/java/com/zksy/web/controller/cockpit/BusinessCockpitMapSnapshotAdapterTest.java

@@ -296,6 +296,28 @@ class BusinessCockpitMapSnapshotAdapterTest {
                         .collect(java.util.stream.Collectors.toList()));
     }
 
+    @Test
+    void redisTtlRoundsUpToTheSnapshotExpiryBoundary() {
+        RedisTemplate<Object, Object> sharedRedis = mock(RedisTemplate.class);
+        ValueOperations<Object, Object> values = mock(ValueOperations.class);
+        when(sharedRedis.opsForValue()).thenReturn(values);
+        when(values.get(any())).thenReturn(null);
+        when(values.setIfAbsent(any(), any(), anyLong(), eq(java.util.concurrent.TimeUnit.SECONDS)))
+                .thenReturn(Boolean.TRUE);
+        when(monitorPointService.list()).thenReturn(Collections.emptyList());
+        when(equipmentBaseService.list()).thenReturn(Collections.emptyList());
+        when(equipmentTypeService.list()).thenReturn(Collections.emptyList());
+        BusinessCockpitMapSnapshotAdapter fractionalClockAdapter = new BusinessCockpitMapSnapshotAdapter(
+                monitorPointService, equipmentBaseService, equipmentTypeService, deviceFactResolver,
+                Clock.fixed(Instant.parse("2026-09-02T02:00:00.900Z"), ZoneOffset.UTC), sharedRedis);
+
+        fractionalClockAdapter.load("2026-09-02T10:00:00+08:00");
+
+        verify(values).setIfAbsent(eq("cockpit:map-snapshot:2026-09-02T10:00:00+08:00"), any(), eq(600L),
+                eq(java.util.concurrent.TimeUnit.SECONDS));
+    }
+
+
     @Test
     void expiredSnapshotAtIsRejectedInsteadOfLoadingCurrentRelations() {
         when(monitorPointService.list()).thenReturn(Collections.emptyList());

+ 2 - 1
pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/map/BusinessCockpitMapSnapshotAdapter.java

@@ -129,8 +129,9 @@ public class BusinessCockpitMapSnapshotAdapter implements CockpitMapSnapshotAdap
 
         CockpitMapSnapshot built = buildSnapshot(resolvedSnapshotAt);
         if (redisTemplate != null) {
+            Duration remaining = Duration.between(now, requestedAt.plus(SNAPSHOT_RETENTION));
             long ttlSeconds = Math.max(1,
-                    Duration.between(now, requestedAt.plus(SNAPSHOT_RETENTION)).getSeconds());
+                    remaining.getSeconds() + (remaining.getNano() > 0 ? 1 : 0));
             Boolean stored = redisTemplate.opsForValue()
                     .setIfAbsent(cacheKey, built, ttlSeconds, TimeUnit.SECONDS);
             if (!Boolean.TRUE.equals(stored)) {