@zintrust/workers 0.1.28 → 0.1.30
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/README.md +16 -1
- package/dist/AnomalyDetection.d.ts +4 -0
- package/dist/AnomalyDetection.js +8 -0
- package/dist/BroadcastWorker.d.ts +2 -0
- package/dist/CanaryController.js +49 -5
- package/dist/ChaosEngineering.js +13 -0
- package/dist/ClusterLock.js +21 -10
- package/dist/DeadLetterQueue.js +12 -8
- package/dist/MultiQueueWorker.d.ts +1 -1
- package/dist/MultiQueueWorker.js +12 -7
- package/dist/NotificationWorker.d.ts +2 -0
- package/dist/PriorityQueue.d.ts +2 -2
- package/dist/PriorityQueue.js +20 -21
- package/dist/ResourceMonitor.js +65 -38
- package/dist/WorkerFactory.d.ts +23 -3
- package/dist/WorkerFactory.js +420 -40
- package/dist/WorkerInit.js +8 -3
- package/dist/WorkerMetrics.d.ts +2 -1
- package/dist/WorkerMetrics.js +152 -93
- package/dist/WorkerRegistry.d.ts +6 -0
- package/dist/WorkerRegistry.js +70 -1
- package/dist/WorkerShutdown.d.ts +21 -0
- package/dist/WorkerShutdown.js +82 -9
- package/dist/WorkerShutdownDurableObject.d.ts +12 -0
- package/dist/WorkerShutdownDurableObject.js +41 -0
- package/dist/build-manifest.json +171 -99
- package/dist/createQueueWorker.d.ts +2 -0
- package/dist/createQueueWorker.js +42 -27
- package/dist/dashboard/types.d.ts +5 -0
- package/dist/dashboard/workers-api.js +136 -43
- package/dist/http/WorkerApiController.js +1 -0
- package/dist/http/WorkerController.js +133 -85
- package/dist/http/WorkerMonitoringService.d.ts +11 -0
- package/dist/http/WorkerMonitoringService.js +62 -0
- package/dist/http/middleware/CustomValidation.js +1 -1
- package/dist/http/middleware/EditWorkerValidation.d.ts +1 -1
- package/dist/http/middleware/EditWorkerValidation.js +7 -6
- package/dist/http/middleware/ProcessorPathSanitizer.js +101 -35
- package/dist/http/middleware/WorkerValidationChain.js +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/routes/workers.js +48 -6
- package/dist/storage/WorkerStore.d.ts +4 -1
- package/dist/storage/WorkerStore.js +55 -7
- package/dist/telemetry/api/TelemetryAPI.d.ts +46 -0
- package/dist/telemetry/api/TelemetryAPI.js +219 -0
- package/dist/telemetry/api/TelemetryMonitoringService.d.ts +17 -0
- package/dist/telemetry/api/TelemetryMonitoringService.js +113 -0
- package/dist/telemetry/components/AlertPanel.d.ts +1 -0
- package/dist/telemetry/components/AlertPanel.js +13 -0
- package/dist/telemetry/components/CostTracking.d.ts +1 -0
- package/dist/telemetry/components/CostTracking.js +14 -0
- package/dist/telemetry/components/ResourceUsageChart.d.ts +1 -0
- package/dist/telemetry/components/ResourceUsageChart.js +11 -0
- package/dist/telemetry/components/WorkerHealthChart.d.ts +1 -0
- package/dist/telemetry/components/WorkerHealthChart.js +11 -0
- package/dist/telemetry/index.d.ts +15 -0
- package/dist/telemetry/index.js +60 -0
- package/dist/telemetry/routes/dashboard.d.ts +6 -0
- package/dist/telemetry/routes/dashboard.js +608 -0
- package/dist/ui/router/EmbeddedAssets.d.ts +4 -0
- package/dist/ui/router/EmbeddedAssets.js +13 -0
- package/dist/ui/router/ui.js +100 -4
- package/package.json +9 -5
- package/src/AnomalyDetection.ts +9 -0
- package/src/CanaryController.ts +41 -5
- package/src/ChaosEngineering.ts +14 -0
- package/src/ClusterLock.ts +22 -9
- package/src/DeadLetterQueue.ts +13 -8
- package/src/MultiQueueWorker.ts +15 -8
- package/src/PriorityQueue.ts +21 -22
- package/src/ResourceMonitor.ts +72 -40
- package/src/WorkerFactory.ts +545 -49
- package/src/WorkerInit.ts +8 -3
- package/src/WorkerMetrics.ts +183 -105
- package/src/WorkerRegistry.ts +80 -1
- package/src/WorkerShutdown.ts +115 -9
- package/src/WorkerShutdownDurableObject.ts +64 -0
- package/src/createQueueWorker.ts +73 -30
- package/src/dashboard/types.ts +5 -0
- package/src/dashboard/workers-api.ts +165 -52
- package/src/http/WorkerApiController.ts +1 -0
- package/src/http/WorkerController.ts +167 -90
- package/src/http/WorkerMonitoringService.ts +77 -0
- package/src/http/middleware/CustomValidation.ts +1 -1
- package/src/http/middleware/EditWorkerValidation.ts +7 -6
- package/src/http/middleware/ProcessorPathSanitizer.ts +123 -36
- package/src/http/middleware/WorkerValidationChain.ts +1 -0
- package/src/index.ts +6 -1
- package/src/routes/workers.ts +66 -9
- package/src/storage/WorkerStore.ts +59 -9
- package/src/telemetry/api/TelemetryAPI.ts +292 -0
- package/src/telemetry/api/TelemetryMonitoringService.ts +149 -0
- package/src/telemetry/components/AlertPanel.ts +13 -0
- package/src/telemetry/components/CostTracking.ts +14 -0
- package/src/telemetry/components/ResourceUsageChart.ts +11 -0
- package/src/telemetry/components/WorkerHealthChart.ts +11 -0
- package/src/telemetry/index.ts +121 -0
- package/src/telemetry/public/assets/zintrust-logo.svg +15 -0
- package/src/telemetry/routes/dashboard.ts +638 -0
- package/src/telemetry/styles/tailwind.css +1 -0
- package/src/telemetry/styles/zintrust-theme.css +8 -0
- package/src/ui/router/EmbeddedAssets.ts +13 -0
- package/src/ui/router/ui.ts +112 -5
- package/src/ui/workers/index.html +2 -2
- package/src/ui/workers/main.js +232 -61
- package/src/ui/workers/zintrust.svg +30 -0
- package/dist/dashboard/workers-dashboard-ui.d.ts +0 -3
- package/dist/dashboard/workers-dashboard-ui.js +0 -1026
- package/dist/dashboard/workers-dashboard.d.ts +0 -4
- package/dist/dashboard/workers-dashboard.js +0 -904
package/dist/WorkerShutdown.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Centralized graceful shutdown handling for the worker management system.
|
|
5
5
|
* Coordinates orderly shutdown of all worker modules and the WorkerFactory.
|
|
6
6
|
*/
|
|
7
|
-
import { Logger } from '@zintrust/core';
|
|
7
|
+
import { Cloudflare, Logger } from '@zintrust/core';
|
|
8
8
|
import { WorkerFactory } from './WorkerFactory';
|
|
9
9
|
// ============================================================================
|
|
10
10
|
// Implementation
|
|
@@ -15,7 +15,43 @@ const state = {
|
|
|
15
15
|
startedAt: null,
|
|
16
16
|
reason: null,
|
|
17
17
|
};
|
|
18
|
+
const getDurableShutdownStub = () => {
|
|
19
|
+
const env = Cloudflare.getWorkersEnv();
|
|
20
|
+
if (env === null)
|
|
21
|
+
return null;
|
|
22
|
+
const namespace = env['WORKER_SHUTDOWN'];
|
|
23
|
+
if (!namespace ||
|
|
24
|
+
typeof namespace.idFromName !== 'function' ||
|
|
25
|
+
typeof namespace.get !== 'function') {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const id = namespace.idFromName('zintrust-shutdown');
|
|
29
|
+
return namespace.get(id) ?? null;
|
|
30
|
+
};
|
|
31
|
+
const requestDurableShutdown = async (reason = 'manual') => {
|
|
32
|
+
const stub = getDurableShutdownStub();
|
|
33
|
+
if (!stub) {
|
|
34
|
+
Logger.warn('Worker shutdown Durable Object binding not configured');
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
const res = await stub.fetch('https://worker-shutdown/shutdown', {
|
|
38
|
+
method: 'POST',
|
|
39
|
+
headers: { 'content-type': 'application/json' },
|
|
40
|
+
body: JSON.stringify({ reason }),
|
|
41
|
+
});
|
|
42
|
+
return res.ok;
|
|
43
|
+
};
|
|
44
|
+
const getDurableShutdownState = async () => {
|
|
45
|
+
const stub = getDurableShutdownStub();
|
|
46
|
+
if (!stub)
|
|
47
|
+
return null;
|
|
48
|
+
const res = await stub.fetch('https://worker-shutdown/status');
|
|
49
|
+
if (!res.ok)
|
|
50
|
+
return null;
|
|
51
|
+
return (await res.json());
|
|
52
|
+
};
|
|
18
53
|
let shutdownHandlersRegistered = false;
|
|
54
|
+
const signalHandlers = {};
|
|
19
55
|
/**
|
|
20
56
|
* Perform graceful shutdown of all worker modules
|
|
21
57
|
*/
|
|
@@ -72,7 +108,7 @@ function registerShutdownHandlers() {
|
|
|
72
108
|
}
|
|
73
109
|
Logger.debug('Registering worker management system shutdown handlers');
|
|
74
110
|
// SIGTERM - graceful shutdown (Docker, systemd, etc.)
|
|
75
|
-
|
|
111
|
+
signalHandlers.sigterm = async () => {
|
|
76
112
|
Logger.info('📨 Received SIGTERM signal');
|
|
77
113
|
try {
|
|
78
114
|
await shutdown({ signal: 'SIGTERM', timeout: 30000, forceExit: true });
|
|
@@ -80,7 +116,8 @@ function registerShutdownHandlers() {
|
|
|
80
116
|
catch (error) {
|
|
81
117
|
Logger.error('Error during SIGTERM shutdown', error);
|
|
82
118
|
}
|
|
83
|
-
}
|
|
119
|
+
};
|
|
120
|
+
process.on('SIGTERM', signalHandlers.sigterm);
|
|
84
121
|
// SIGINT - user interrupt (Ctrl+C) - REMOVED: handled by bootstrap.ts to prevent race condition
|
|
85
122
|
// process.on('SIGINT', async () => {
|
|
86
123
|
// Logger.info('📨 Received SIGINT signal');
|
|
@@ -91,7 +128,7 @@ function registerShutdownHandlers() {
|
|
|
91
128
|
// }
|
|
92
129
|
// });
|
|
93
130
|
// SIGHUP - terminal closed
|
|
94
|
-
|
|
131
|
+
signalHandlers.sighup = async () => {
|
|
95
132
|
Logger.info('📨 Received SIGHUP signal');
|
|
96
133
|
try {
|
|
97
134
|
await shutdown({ signal: 'SIGHUP', timeout: 30000, forceExit: true });
|
|
@@ -99,9 +136,10 @@ function registerShutdownHandlers() {
|
|
|
99
136
|
catch (error) {
|
|
100
137
|
Logger.error('Error during SIGHUP shutdown', error);
|
|
101
138
|
}
|
|
102
|
-
}
|
|
139
|
+
};
|
|
140
|
+
process.on('SIGHUP', signalHandlers.sighup);
|
|
103
141
|
// Handle uncaught errors during shutdown
|
|
104
|
-
|
|
142
|
+
signalHandlers.uncaughtException = async (error) => {
|
|
105
143
|
Logger.error('💥 Uncaught exception during worker operations', error);
|
|
106
144
|
try {
|
|
107
145
|
await shutdown({ signal: 'uncaughtException', timeout: 10000, forceExit: true });
|
|
@@ -110,16 +148,39 @@ function registerShutdownHandlers() {
|
|
|
110
148
|
// Ignore errors during emergency shutdown
|
|
111
149
|
}
|
|
112
150
|
process.exit(1);
|
|
113
|
-
}
|
|
114
|
-
process.on('
|
|
151
|
+
};
|
|
152
|
+
process.on('uncaughtException', signalHandlers.uncaughtException);
|
|
153
|
+
signalHandlers.unhandledRejection = (reason) => {
|
|
115
154
|
// Only log the error - don't shut down the entire application
|
|
116
155
|
Logger.error('💥 Unhandled promise rejection detected', reason);
|
|
117
156
|
Logger.warn('⚠️ This error has been logged but will not shut down the server');
|
|
118
157
|
Logger.warn('⚠️ Check the error context and fix the underlying issue');
|
|
119
|
-
}
|
|
158
|
+
};
|
|
159
|
+
process.on('unhandledRejection', signalHandlers.unhandledRejection);
|
|
120
160
|
shutdownHandlersRegistered = true;
|
|
121
161
|
Logger.debug('Worker management system shutdown handlers registered');
|
|
122
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* Unregister process signal handlers (for hot reload/testing)
|
|
165
|
+
*/
|
|
166
|
+
function unregisterShutdownHandlers() {
|
|
167
|
+
if (!shutdownHandlersRegistered)
|
|
168
|
+
return;
|
|
169
|
+
if (signalHandlers.sigterm)
|
|
170
|
+
process.off('SIGTERM', signalHandlers.sigterm);
|
|
171
|
+
if (signalHandlers.sighup)
|
|
172
|
+
process.off('SIGHUP', signalHandlers.sighup);
|
|
173
|
+
if (signalHandlers.uncaughtException)
|
|
174
|
+
process.off('uncaughtException', signalHandlers.uncaughtException);
|
|
175
|
+
if (signalHandlers.unhandledRejection)
|
|
176
|
+
process.off('unhandledRejection', signalHandlers.unhandledRejection);
|
|
177
|
+
signalHandlers.sigterm = undefined;
|
|
178
|
+
signalHandlers.sighup = undefined;
|
|
179
|
+
signalHandlers.uncaughtException = undefined;
|
|
180
|
+
signalHandlers.unhandledRejection = undefined;
|
|
181
|
+
shutdownHandlersRegistered = false;
|
|
182
|
+
Logger.debug('Worker management system shutdown handlers unregistered');
|
|
183
|
+
}
|
|
123
184
|
/**
|
|
124
185
|
* Check if system is currently shutting down
|
|
125
186
|
*/
|
|
@@ -144,6 +205,10 @@ export const WorkerShutdown = Object.freeze({
|
|
|
144
205
|
* Register process signal handlers for graceful shutdown
|
|
145
206
|
*/
|
|
146
207
|
registerShutdownHandlers,
|
|
208
|
+
/**
|
|
209
|
+
* Unregister process signal handlers (for hot reload/testing)
|
|
210
|
+
*/
|
|
211
|
+
unregisterShutdownHandlers,
|
|
147
212
|
/**
|
|
148
213
|
* Check if system is currently shutting down
|
|
149
214
|
*/
|
|
@@ -152,4 +217,12 @@ export const WorkerShutdown = Object.freeze({
|
|
|
152
217
|
* Get current shutdown state
|
|
153
218
|
*/
|
|
154
219
|
getShutdownState,
|
|
220
|
+
/**
|
|
221
|
+
* Request shutdown via Durable Object (Workers)
|
|
222
|
+
*/
|
|
223
|
+
requestDurableShutdown,
|
|
224
|
+
/**
|
|
225
|
+
* Read shutdown state from Durable Object (Workers)
|
|
226
|
+
*/
|
|
227
|
+
getDurableShutdownState,
|
|
155
228
|
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type DurableObjectState = {
|
|
2
|
+
storage: {
|
|
3
|
+
get: (key: string) => Promise<unknown>;
|
|
4
|
+
put: (key: string, value: unknown) => Promise<void>;
|
|
5
|
+
};
|
|
6
|
+
};
|
|
7
|
+
export declare class ZinTrustWorkerShutdownDurableObject {
|
|
8
|
+
private readonly state;
|
|
9
|
+
constructor(state: DurableObjectState);
|
|
10
|
+
fetch(request: Request): Promise<Response>;
|
|
11
|
+
}
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Logger } from '@zintrust/core';
|
|
2
|
+
const loadState = async (state) => {
|
|
3
|
+
const stored = (await state.storage.get('shutdown'));
|
|
4
|
+
return stored ?? { shuttingDown: false };
|
|
5
|
+
};
|
|
6
|
+
const saveState = async (state, value) => {
|
|
7
|
+
await state.storage.put('shutdown', value);
|
|
8
|
+
};
|
|
9
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
10
|
+
export class ZinTrustWorkerShutdownDurableObject {
|
|
11
|
+
state;
|
|
12
|
+
constructor(state) {
|
|
13
|
+
this.state = state;
|
|
14
|
+
}
|
|
15
|
+
async fetch(request) {
|
|
16
|
+
const url = new URL(request.url);
|
|
17
|
+
const path = url.pathname;
|
|
18
|
+
if (request.method === 'GET' && path === '/status') {
|
|
19
|
+
const current = await loadState(this.state);
|
|
20
|
+
return new Response(JSON.stringify(current), {
|
|
21
|
+
status: 200,
|
|
22
|
+
headers: { 'content-type': 'application/json' },
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
if (request.method === 'POST' && path === '/shutdown') {
|
|
26
|
+
const payload = (await request.json().catch(() => ({})));
|
|
27
|
+
const next = {
|
|
28
|
+
shuttingDown: true,
|
|
29
|
+
startedAt: new Date().toISOString(),
|
|
30
|
+
reason: payload.reason ?? 'manual',
|
|
31
|
+
};
|
|
32
|
+
await saveState(this.state, next);
|
|
33
|
+
Logger.info('Worker shutdown requested via Durable Object', next);
|
|
34
|
+
return new Response(JSON.stringify({ ok: true }), {
|
|
35
|
+
status: 202,
|
|
36
|
+
headers: { 'content-type': 'application/json' },
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return new Response('Not Found', { status: 404 });
|
|
40
|
+
}
|
|
41
|
+
}
|