From 747a86bb94006aaca721cfc0c0ce7061643a9ea6 Mon Sep 17 00:00:00 2001
From: chenyc <501753378@qq.com>
Date: 星期四, 20 八月 2026 12:19:35 +0800
Subject: [PATCH] gx

---
 metric-aggregator.js |   65 ++++++++++++++++++++++++++++----
 1 files changed, 56 insertions(+), 9 deletions(-)

diff --git a/metric-aggregator.js b/metric-aggregator.js
index a238075..8d607de 100644
--- a/metric-aggregator.js
+++ b/metric-aggregator.js
@@ -12,7 +12,7 @@
     this.timer = null;
     this.started = false;
     this.flushing = false;
-    this.flushQueued = false;
+    this.queuedFlushOptions = null;
   }
 
   start() {
@@ -47,8 +47,15 @@
 
     const entry = this.getOrCreateEntry(device);
     entry.device = device;
+    const now = Date.now();
+
+    // 首次进入脏状态时记录时间,便于控制“缓存满一轮再发送”。
+    if (!entry.dirty) {
+      entry.dirtySinceAt = now;
+    }
+
     entry.dirty = true;
-    entry.lastUpdateAt = Date.now();
+    entry.lastUpdateAt = now;
 
     if (this.includeDeviceIdField) {
       entry.payload[this.deviceIdField] = device.deviceId;
@@ -69,6 +76,7 @@
         device,
         payload: {},
         dirty: false,
+        dirtySinceAt: 0,
         firstSeenAt: Date.now(),
         lastUpdateAt: 0,
         lastFlushAt: 0,
@@ -98,7 +106,7 @@
 
     this.timer = setTimeout(() => {
       this.flush({ reason: 'timer' }).catch((error) => {
-        this.logger.error(`[APP] Aggregator flush failed: ${error.message}`);
+        this.logger.error(`[APP] 聚合器刷新失败: ${error.message}`);
       });
     }, this.computeDelayMs());
 
@@ -107,12 +115,36 @@
     }
   }
 
+  mergeQueuedFlushOptions(options = {}) {
+    const nextOptions = {
+      reason: options.reason || 'manual',
+      deviceId: options.deviceId || '',
+    };
+
+    if (!this.queuedFlushOptions) {
+      this.queuedFlushOptions = nextOptions;
+      return;
+    }
+
+    const currentOptions = this.queuedFlushOptions;
+    const currentIsTimer = currentOptions.reason === 'timer' || currentOptions.reason === 'queued';
+    const nextIsTimer = nextOptions.reason === 'timer' || nextOptions.reason === 'queued';
+
+    if (currentIsTimer && !nextIsTimer) {
+      currentOptions.reason = nextOptions.reason;
+    }
+
+    if (!currentOptions.deviceId || !nextOptions.deviceId || currentOptions.deviceId !== nextOptions.deviceId) {
+      currentOptions.deviceId = '';
+    }
+  }
+
   async flush(options = {}) {
     const reason = options.reason || 'manual';
     const deviceId = options.deviceId || '';
 
     if (this.flushing) {
-      this.flushQueued = true;
+      this.mergeQueuedFlushOptions({ reason, deviceId });
       return false;
     }
 
@@ -133,10 +165,20 @@
           return false;
         }
 
+        // 定时触发时要求数据至少缓存满一个周期,避免刚收到就被单独发出。
+        if ((reason === 'timer' || reason === 'queued') && entry.dirtySinceAt > 0) {
+          const dirtyAgeMs = Date.now() - entry.dirtySinceAt;
+
+          if (dirtyAgeMs < this.flushIntervalMs) {
+            return false;
+          }
+        }
+
         return true;
       });
 
       for (const entry of entries) {
+        const flushUpdateAt = entry.lastUpdateAt;
         const payload = {
           ...entry.payload,
         };
@@ -157,10 +199,14 @@
             continue;
           }
 
-          entry.dirty = false;
+          if (entry.lastUpdateAt === flushUpdateAt) {
+            entry.dirty = false;
+            entry.dirtySinceAt = 0;
+          }
+
           entry.lastFlushAt = Date.now();
         } catch (error) {
-          this.logger.error(`[APP] Aggregator device flush failed deviceId=${entry.device.deviceId}: ${error.message}`);
+          this.logger.error(`[APP] 聚合器设备刷新失败 deviceId=${entry.device.deviceId}: ${error.message}`);
         }
       }
 
@@ -172,9 +218,10 @@
         this.scheduleNextFlush();
       }
 
-      if (this.flushQueued) {
-        this.flushQueued = false;
-        await this.flush({ reason: 'queued' });
+      if (this.queuedFlushOptions) {
+        const queuedOptions = this.queuedFlushOptions;
+        this.queuedFlushOptions = null;
+        await this.flush(queuedOptions);
       }
     }
   }

--
Gitblit v1.8.0