@serve.zone/dcrouter 11.11.0 → 11.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_serve/bundle.js +514 -514
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/appstate.js +97 -63
- package/dist_ts_web/elements/ops-view-certificates.js +2 -2
- package/dist_ts_web/elements/ops-view-emails.js +2 -2
- package/dist_ts_web/elements/ops-view-network.d.ts +1 -0
- package/dist_ts_web/elements/ops-view-network.js +18 -3
- package/dist_ts_web/elements/ops-view-remoteingress.js +2 -2
- package/dist_ts_web/router.js +2 -2
- package/package.json +7 -7
- package/readme.md +1 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate.ts +98 -63
- package/ts_web/elements/ops-view-certificates.ts +1 -1
- package/ts_web/elements/ops-view-emails.ts +1 -1
- package/ts_web/elements/ops-view-network.ts +21 -6
- package/ts_web/elements/ops-view-remoteingress.ts +1 -1
- package/ts_web/readme.md +11 -1
- package/ts_web/router.ts +1 -1
|
@@ -47,10 +47,11 @@ export class OpsViewNetwork extends DeesElement {
|
|
|
47
47
|
// Track if we need to update the chart to avoid unnecessary re-renders
|
|
48
48
|
private lastChartUpdate = 0;
|
|
49
49
|
private chartUpdateThreshold = 1000; // Minimum ms between chart updates
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
private trafficUpdateTimer: any = null;
|
|
52
52
|
private requestsPerSecHistory: number[] = []; // Track requests/sec over time for trend
|
|
53
53
|
private historyLoaded = false; // Whether server-side throughput history has been loaded
|
|
54
|
+
private visibilityHandler: (() => void) | null = null;
|
|
54
55
|
|
|
55
56
|
constructor() {
|
|
56
57
|
super();
|
|
@@ -59,28 +60,42 @@ export class OpsViewNetwork extends DeesElement {
|
|
|
59
60
|
this.updateNetworkData();
|
|
60
61
|
this.startTrafficUpdateTimer();
|
|
61
62
|
}
|
|
62
|
-
|
|
63
|
+
|
|
63
64
|
async connectedCallback() {
|
|
64
65
|
await super.connectedCallback();
|
|
65
|
-
|
|
66
|
+
|
|
67
|
+
// Pause/resume traffic timer when tab visibility changes
|
|
68
|
+
this.visibilityHandler = () => {
|
|
69
|
+
if (document.hidden) {
|
|
70
|
+
this.stopTrafficUpdateTimer();
|
|
71
|
+
} else {
|
|
72
|
+
this.startTrafficUpdateTimer();
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
document.addEventListener('visibilitychange', this.visibilityHandler);
|
|
76
|
+
|
|
66
77
|
// When network view becomes visible, ensure we fetch network data
|
|
67
78
|
await appstate.networkStatePart.dispatchAction(appstate.fetchNetworkStatsAction, null);
|
|
68
79
|
}
|
|
69
|
-
|
|
80
|
+
|
|
70
81
|
async disconnectedCallback() {
|
|
71
82
|
await super.disconnectedCallback();
|
|
72
83
|
this.stopTrafficUpdateTimer();
|
|
84
|
+
if (this.visibilityHandler) {
|
|
85
|
+
document.removeEventListener('visibilitychange', this.visibilityHandler);
|
|
86
|
+
this.visibilityHandler = null;
|
|
87
|
+
}
|
|
73
88
|
}
|
|
74
89
|
|
|
75
90
|
private subscribeToStateParts() {
|
|
76
91
|
// Subscribe and track unsubscribe functions
|
|
77
|
-
const statsUnsubscribe = appstate.statsStatePart.
|
|
92
|
+
const statsUnsubscribe = appstate.statsStatePart.select().subscribe((state) => {
|
|
78
93
|
this.statsState = state;
|
|
79
94
|
this.updateNetworkData();
|
|
80
95
|
});
|
|
81
96
|
this.rxSubscriptions.push(statsUnsubscribe);
|
|
82
97
|
|
|
83
|
-
const networkUnsubscribe = appstate.networkStatePart.
|
|
98
|
+
const networkUnsubscribe = appstate.networkStatePart.select().subscribe((state) => {
|
|
84
99
|
this.networkState = state;
|
|
85
100
|
this.updateNetworkData();
|
|
86
101
|
});
|
|
@@ -25,7 +25,7 @@ export class OpsViewRemoteIngress extends DeesElement {
|
|
|
25
25
|
|
|
26
26
|
constructor() {
|
|
27
27
|
super();
|
|
28
|
-
const sub = appstate.remoteIngressStatePart.
|
|
28
|
+
const sub = appstate.remoteIngressStatePart.select().subscribe((newState) => {
|
|
29
29
|
this.riState = newState;
|
|
30
30
|
});
|
|
31
31
|
this.rxSubscriptions.push(sub);
|
package/ts_web/readme.md
CHANGED
|
@@ -111,7 +111,7 @@ ts_web/
|
|
|
111
111
|
|
|
112
112
|
### State Management
|
|
113
113
|
|
|
114
|
-
The app uses `@push.rocks/smartstate` with multiple state parts:
|
|
114
|
+
The app uses `@push.rocks/smartstate` v2.3+ with multiple state parts, scheduled actions with `autoPause: 'visibility'`, and batched updates:
|
|
115
115
|
|
|
116
116
|
| State Part | Mode | Description |
|
|
117
117
|
|-----------|------|-------------|
|
|
@@ -125,6 +125,16 @@ The app uses `@push.rocks/smartstate` with multiple state parts:
|
|
|
125
125
|
| `certificateStatePart` | Soft | Certificate list, summary, loading state |
|
|
126
126
|
| `remoteIngressStatePart` | Soft | Edge list, statuses, new edge secret |
|
|
127
127
|
|
|
128
|
+
### Tab Visibility Optimization
|
|
129
|
+
|
|
130
|
+
The dashboard automatically pauses all background activity when the browser tab is hidden and resumes when visible:
|
|
131
|
+
|
|
132
|
+
- **Auto-refresh polling** uses `createScheduledAction` with `autoPause: 'visibility'` — stops HTTP requests while the tab is sleeping
|
|
133
|
+
- **In-flight guard** prevents concurrent refresh requests from piling up
|
|
134
|
+
- **WebSocket connection** disconnects when hidden and reconnects when visible, preventing log entry accumulation
|
|
135
|
+
- **Network traffic timer** pauses chart updates when the tab is backgrounded
|
|
136
|
+
- **Log entry batching** — incoming WebSocket log pushes are buffered and flushed once per animation frame to avoid per-entry re-renders
|
|
137
|
+
|
|
128
138
|
### Actions
|
|
129
139
|
|
|
130
140
|
```typescript
|
package/ts_web/router.ts
CHANGED
|
@@ -38,7 +38,7 @@ class AppRouter {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
private setupStateSync(): void {
|
|
41
|
-
appstate.uiStatePart.
|
|
41
|
+
appstate.uiStatePart.select().subscribe((uiState) => {
|
|
42
42
|
if (this.suppressStateUpdate) return;
|
|
43
43
|
|
|
44
44
|
const currentPath = window.location.pathname;
|