diff --git a/changelog.md b/changelog.md index ea1d3ca..561ac5e 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,12 @@ # Changelog +## 2026-04-03 - 12.5.1 - fix(ops-view-network) +centralize traffic chart timing constants for consistent rolling window updates + +- Defines shared constants for the chart window, update interval, and maximum buffered data points +- Replaces hardcoded traffic history sizes and timer intervals with derived values across initialization, history loading, and live updates +- Keeps the chart rolling window configuration aligned with the in-memory traffic buffer + ## 2026-04-02 - 12.5.0 - feat(ops-view-routes) add priority support and list-based domain editing for routes diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index e64099d..943453a 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@serve.zone/dcrouter', - version: '12.5.0', + version: '12.5.1', description: 'A multifaceted routing service handling mail and SMS delivery functions.' } diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index e64099d..943453a 100644 --- a/ts_web/00_commitinfo_data.ts +++ b/ts_web/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@serve.zone/dcrouter', - version: '12.5.0', + version: '12.5.1', description: 'A multifaceted routing service handling mail and SMS delivery functions.' } diff --git a/ts_web/elements/ops-view-network.ts b/ts_web/elements/ops-view-network.ts index 75c437a..8bcb799 100644 --- a/ts_web/elements/ops-view-network.ts +++ b/ts_web/elements/ops-view-network.ts @@ -28,6 +28,13 @@ interface INetworkRequest { @customElement('ops-view-network') export class OpsViewNetwork extends DeesElement { + /** How far back the traffic chart shows */ + private static readonly CHART_WINDOW_MS = 5 * 60 * 1000; // 5 minutes + /** How often a new data point is added */ + private static readonly UPDATE_INTERVAL_MS = 1000; // 1 second + /** Derived: max data points the buffer holds */ + private static readonly MAX_DATA_POINTS = OpsViewNetwork.CHART_WINDOW_MS / OpsViewNetwork.UPDATE_INTERVAL_MS; + @state() accessor statsState = appstate.statsStatePart.getState()!; @@ -46,7 +53,7 @@ export class OpsViewNetwork extends DeesElement { // Track if we need to update the chart to avoid unnecessary re-renders private lastChartUpdate = 0; - private chartUpdateThreshold = 1000; // Minimum ms between chart updates + private chartUpdateThreshold = OpsViewNetwork.UPDATE_INTERVAL_MS; // Minimum ms between chart updates private trafficUpdateTimer: any = null; private requestsPerSecHistory: number[] = []; // Track requests/sec over time for trend @@ -104,13 +111,11 @@ export class OpsViewNetwork extends DeesElement { private initializeTrafficData() { const now = Date.now(); - // Fixed 5 minute time range - const range = 5 * 60 * 1000; // 5 minutes - const bucketSize = range / 60; // 60 data points + const { MAX_DATA_POINTS, UPDATE_INTERVAL_MS } = OpsViewNetwork; // Initialize with empty data points for both in and out - const emptyData = Array.from({ length: 60 }, (_, i) => { - const time = now - ((59 - i) * bucketSize); + const emptyData = Array.from({ length: MAX_DATA_POINTS }, (_, i) => { + const time = now - ((MAX_DATA_POINTS - 1 - i) * UPDATE_INTERVAL_MS); return { x: new Date(time).toISOString(), y: 0, @@ -143,23 +148,23 @@ export class OpsViewNetwork extends DeesElement { y: Math.round((p.out * 8) / 1000000 * 10) / 10, })); - // Use history as the chart data, keeping the most recent 60 points (5 min window) - const sliceStart = Math.max(0, historyIn.length - 60); + const { MAX_DATA_POINTS, UPDATE_INTERVAL_MS } = OpsViewNetwork; + + // Use history as the chart data, keeping the most recent points within the window + const sliceStart = Math.max(0, historyIn.length - MAX_DATA_POINTS); this.trafficDataIn = historyIn.slice(sliceStart); this.trafficDataOut = historyOut.slice(sliceStart); - // If fewer than 60 points, pad the front with zeros - if (this.trafficDataIn.length < 60) { + // If fewer than MAX_DATA_POINTS, pad the front with zeros + if (this.trafficDataIn.length < MAX_DATA_POINTS) { const now = Date.now(); - const range = 5 * 60 * 1000; - const bucketSize = range / 60; - const padCount = 60 - this.trafficDataIn.length; + const padCount = MAX_DATA_POINTS - this.trafficDataIn.length; const firstTimestamp = this.trafficDataIn.length > 0 ? new Date(this.trafficDataIn[0].x).getTime() : now; const padIn = Array.from({ length: padCount }, (_, i) => ({ - x: new Date(firstTimestamp - ((padCount - i) * bucketSize)).toISOString(), + x: new Date(firstTimestamp - ((padCount - i) * UPDATE_INTERVAL_MS)).toISOString(), y: 0, })); const padOut = padIn.map(p => ({ ...p })); @@ -296,7 +301,7 @@ export class OpsViewNetwork extends DeesElement { } ]} .realtimeMode=${true} - .rollingWindow=${300000} + .rollingWindow=${OpsViewNetwork.CHART_WINDOW_MS} .yAxisFormatter=${(val: number) => `${val} Mbit/s`} > @@ -709,9 +714,8 @@ export class OpsViewNetwork extends DeesElement { private startTrafficUpdateTimer() { this.stopTrafficUpdateTimer(); // Clear any existing timer this.trafficUpdateTimer = setInterval(() => { - // Add a new data point every second this.addTrafficDataPoint(); - }, 1000); // Update every second + }, OpsViewNetwork.UPDATE_INTERVAL_MS); } private addTrafficDataPoint() { @@ -742,7 +746,7 @@ export class OpsViewNetwork extends DeesElement { }; // In-place mutation then reassign for Lit reactivity (avoids 4 intermediate arrays) - if (this.trafficDataIn.length >= 60) { + if (this.trafficDataIn.length >= OpsViewNetwork.MAX_DATA_POINTS) { this.trafficDataIn.shift(); this.trafficDataOut.shift(); }