@zintrust/workers 0.1.27

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.
Files changed (178) hide show
  1. package/README.md +861 -0
  2. package/dist/AnomalyDetection.d.ts +102 -0
  3. package/dist/AnomalyDetection.js +321 -0
  4. package/dist/AutoScaler.d.ts +127 -0
  5. package/dist/AutoScaler.js +425 -0
  6. package/dist/BroadcastWorker.d.ts +21 -0
  7. package/dist/BroadcastWorker.js +24 -0
  8. package/dist/CanaryController.d.ts +103 -0
  9. package/dist/CanaryController.js +380 -0
  10. package/dist/ChaosEngineering.d.ts +79 -0
  11. package/dist/ChaosEngineering.js +216 -0
  12. package/dist/CircuitBreaker.d.ts +106 -0
  13. package/dist/CircuitBreaker.js +374 -0
  14. package/dist/ClusterLock.d.ts +90 -0
  15. package/dist/ClusterLock.js +385 -0
  16. package/dist/ComplianceManager.d.ts +177 -0
  17. package/dist/ComplianceManager.js +556 -0
  18. package/dist/DatacenterOrchestrator.d.ts +133 -0
  19. package/dist/DatacenterOrchestrator.js +404 -0
  20. package/dist/DeadLetterQueue.d.ts +122 -0
  21. package/dist/DeadLetterQueue.js +539 -0
  22. package/dist/HealthMonitor.d.ts +42 -0
  23. package/dist/HealthMonitor.js +301 -0
  24. package/dist/MultiQueueWorker.d.ts +89 -0
  25. package/dist/MultiQueueWorker.js +277 -0
  26. package/dist/NotificationWorker.d.ts +21 -0
  27. package/dist/NotificationWorker.js +23 -0
  28. package/dist/Observability.d.ts +153 -0
  29. package/dist/Observability.js +530 -0
  30. package/dist/PluginManager.d.ts +123 -0
  31. package/dist/PluginManager.js +392 -0
  32. package/dist/PriorityQueue.d.ts +117 -0
  33. package/dist/PriorityQueue.js +244 -0
  34. package/dist/ResourceMonitor.d.ts +164 -0
  35. package/dist/ResourceMonitor.js +605 -0
  36. package/dist/SLAMonitor.d.ts +110 -0
  37. package/dist/SLAMonitor.js +274 -0
  38. package/dist/WorkerFactory.d.ts +193 -0
  39. package/dist/WorkerFactory.js +1507 -0
  40. package/dist/WorkerInit.d.ts +85 -0
  41. package/dist/WorkerInit.js +223 -0
  42. package/dist/WorkerMetrics.d.ts +114 -0
  43. package/dist/WorkerMetrics.js +509 -0
  44. package/dist/WorkerRegistry.d.ts +145 -0
  45. package/dist/WorkerRegistry.js +319 -0
  46. package/dist/WorkerShutdown.d.ts +61 -0
  47. package/dist/WorkerShutdown.js +159 -0
  48. package/dist/WorkerVersioning.d.ts +107 -0
  49. package/dist/WorkerVersioning.js +300 -0
  50. package/dist/build-manifest.json +462 -0
  51. package/dist/config/workerConfig.d.ts +3 -0
  52. package/dist/config/workerConfig.js +19 -0
  53. package/dist/createQueueWorker.d.ts +23 -0
  54. package/dist/createQueueWorker.js +113 -0
  55. package/dist/dashboard/index.d.ts +1 -0
  56. package/dist/dashboard/index.js +1 -0
  57. package/dist/dashboard/types.d.ts +117 -0
  58. package/dist/dashboard/types.js +1 -0
  59. package/dist/dashboard/workers-api.d.ts +4 -0
  60. package/dist/dashboard/workers-api.js +638 -0
  61. package/dist/dashboard/workers-dashboard-ui.d.ts +3 -0
  62. package/dist/dashboard/workers-dashboard-ui.js +1026 -0
  63. package/dist/dashboard/workers-dashboard.d.ts +4 -0
  64. package/dist/dashboard/workers-dashboard.js +904 -0
  65. package/dist/helper/index.d.ts +5 -0
  66. package/dist/helper/index.js +10 -0
  67. package/dist/http/WorkerApiController.d.ts +38 -0
  68. package/dist/http/WorkerApiController.js +312 -0
  69. package/dist/http/WorkerController.d.ts +374 -0
  70. package/dist/http/WorkerController.js +1351 -0
  71. package/dist/http/middleware/CustomValidation.d.ts +92 -0
  72. package/dist/http/middleware/CustomValidation.js +270 -0
  73. package/dist/http/middleware/DatacenterValidator.d.ts +3 -0
  74. package/dist/http/middleware/DatacenterValidator.js +94 -0
  75. package/dist/http/middleware/EditWorkerValidation.d.ts +7 -0
  76. package/dist/http/middleware/EditWorkerValidation.js +55 -0
  77. package/dist/http/middleware/FeaturesValidator.d.ts +3 -0
  78. package/dist/http/middleware/FeaturesValidator.js +60 -0
  79. package/dist/http/middleware/InfrastructureValidator.d.ts +31 -0
  80. package/dist/http/middleware/InfrastructureValidator.js +226 -0
  81. package/dist/http/middleware/OptionsValidator.d.ts +3 -0
  82. package/dist/http/middleware/OptionsValidator.js +112 -0
  83. package/dist/http/middleware/PayloadSanitizer.d.ts +7 -0
  84. package/dist/http/middleware/PayloadSanitizer.js +42 -0
  85. package/dist/http/middleware/ProcessorPathSanitizer.d.ts +3 -0
  86. package/dist/http/middleware/ProcessorPathSanitizer.js +74 -0
  87. package/dist/http/middleware/QueueNameSanitizer.d.ts +3 -0
  88. package/dist/http/middleware/QueueNameSanitizer.js +45 -0
  89. package/dist/http/middleware/ValidateDriver.d.ts +7 -0
  90. package/dist/http/middleware/ValidateDriver.js +20 -0
  91. package/dist/http/middleware/VersionSanitizer.d.ts +3 -0
  92. package/dist/http/middleware/VersionSanitizer.js +25 -0
  93. package/dist/http/middleware/WorkerNameSanitizer.d.ts +3 -0
  94. package/dist/http/middleware/WorkerNameSanitizer.js +46 -0
  95. package/dist/http/middleware/WorkerValidationChain.d.ts +27 -0
  96. package/dist/http/middleware/WorkerValidationChain.js +185 -0
  97. package/dist/index.d.ts +46 -0
  98. package/dist/index.js +48 -0
  99. package/dist/routes/workers.d.ts +12 -0
  100. package/dist/routes/workers.js +81 -0
  101. package/dist/storage/WorkerStore.d.ts +45 -0
  102. package/dist/storage/WorkerStore.js +195 -0
  103. package/dist/type.d.ts +76 -0
  104. package/dist/type.js +1 -0
  105. package/dist/ui/router/ui.d.ts +3 -0
  106. package/dist/ui/router/ui.js +83 -0
  107. package/dist/ui/types/worker-ui.d.ts +229 -0
  108. package/dist/ui/types/worker-ui.js +5 -0
  109. package/package.json +53 -0
  110. package/src/AnomalyDetection.ts +434 -0
  111. package/src/AutoScaler.ts +654 -0
  112. package/src/BroadcastWorker.ts +34 -0
  113. package/src/CanaryController.ts +531 -0
  114. package/src/ChaosEngineering.ts +301 -0
  115. package/src/CircuitBreaker.ts +495 -0
  116. package/src/ClusterLock.ts +499 -0
  117. package/src/ComplianceManager.ts +815 -0
  118. package/src/DatacenterOrchestrator.ts +561 -0
  119. package/src/DeadLetterQueue.ts +733 -0
  120. package/src/HealthMonitor.ts +390 -0
  121. package/src/MultiQueueWorker.ts +431 -0
  122. package/src/NotificationWorker.ts +33 -0
  123. package/src/Observability.ts +696 -0
  124. package/src/PluginManager.ts +551 -0
  125. package/src/PriorityQueue.ts +351 -0
  126. package/src/ResourceMonitor.ts +769 -0
  127. package/src/SLAMonitor.ts +408 -0
  128. package/src/WorkerFactory.ts +2108 -0
  129. package/src/WorkerInit.ts +313 -0
  130. package/src/WorkerMetrics.ts +709 -0
  131. package/src/WorkerRegistry.ts +443 -0
  132. package/src/WorkerShutdown.ts +210 -0
  133. package/src/WorkerVersioning.ts +422 -0
  134. package/src/config/workerConfig.ts +25 -0
  135. package/src/createQueueWorker.ts +174 -0
  136. package/src/dashboard/index.ts +6 -0
  137. package/src/dashboard/types.ts +141 -0
  138. package/src/dashboard/workers-api.ts +785 -0
  139. package/src/dashboard/zintrust.svg +30 -0
  140. package/src/helper/index.ts +11 -0
  141. package/src/http/WorkerApiController.ts +369 -0
  142. package/src/http/WorkerController.ts +1512 -0
  143. package/src/http/middleware/CustomValidation.ts +360 -0
  144. package/src/http/middleware/DatacenterValidator.ts +124 -0
  145. package/src/http/middleware/EditWorkerValidation.ts +74 -0
  146. package/src/http/middleware/FeaturesValidator.ts +82 -0
  147. package/src/http/middleware/InfrastructureValidator.ts +295 -0
  148. package/src/http/middleware/OptionsValidator.ts +144 -0
  149. package/src/http/middleware/PayloadSanitizer.ts +52 -0
  150. package/src/http/middleware/ProcessorPathSanitizer.ts +86 -0
  151. package/src/http/middleware/QueueNameSanitizer.ts +55 -0
  152. package/src/http/middleware/ValidateDriver.ts +29 -0
  153. package/src/http/middleware/VersionSanitizer.ts +30 -0
  154. package/src/http/middleware/WorkerNameSanitizer.ts +56 -0
  155. package/src/http/middleware/WorkerValidationChain.ts +230 -0
  156. package/src/index.ts +98 -0
  157. package/src/routes/workers.ts +154 -0
  158. package/src/storage/WorkerStore.ts +240 -0
  159. package/src/type.ts +89 -0
  160. package/src/types/queue-monitor.d.ts +38 -0
  161. package/src/types/queue-redis.d.ts +38 -0
  162. package/src/ui/README.md +13 -0
  163. package/src/ui/components/JsonEditor.js +670 -0
  164. package/src/ui/components/JsonViewer.js +387 -0
  165. package/src/ui/components/WorkerCard.js +178 -0
  166. package/src/ui/components/WorkerExpandPanel.js +257 -0
  167. package/src/ui/components/fetcher.js +42 -0
  168. package/src/ui/components/sla-scorecard.js +32 -0
  169. package/src/ui/components/styles.css +30 -0
  170. package/src/ui/components/table-expander.js +34 -0
  171. package/src/ui/integration/worker-ui-integration.js +565 -0
  172. package/src/ui/router/ui.ts +99 -0
  173. package/src/ui/services/workerApi.js +240 -0
  174. package/src/ui/types/worker-ui.ts +283 -0
  175. package/src/ui/utils/jsonValidator.js +444 -0
  176. package/src/ui/workers/index.html +202 -0
  177. package/src/ui/workers/main.js +1781 -0
  178. package/src/ui/workers/styles.css +1350 -0
@@ -0,0 +1,404 @@
1
+ /**
2
+ * Datacenter Orchestration
3
+ * Multi-datacenter worker coordination with region affinity and failover
4
+ * Sealed namespace for immutability
5
+ */
6
+ import { ErrorFactory, Logger } from '@zintrust/core';
7
+ import { ClusterLock } from './ClusterLock';
8
+ // Internal state
9
+ const regions = new Map();
10
+ const workerPlacements = new Map();
11
+ const failoverPolicies = new Map();
12
+ const healthCheckIntervals = new Map();
13
+ /**
14
+ * Helper: Calculate distance between two coordinates (Haversine formula)
15
+ */
16
+ const calculateDistance = (lat1, lng1, lat2, lng2) => {
17
+ const R = 6371; // Earth's radius in km
18
+ const dLat = ((lat2 - lat1) * Math.PI) / 180;
19
+ const dLng = ((lng2 - lng1) * Math.PI) / 180;
20
+ const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
21
+ Math.cos((lat1 * Math.PI) / 180) *
22
+ Math.cos((lat2 * Math.PI) / 180) *
23
+ Math.sin(dLng / 2) *
24
+ Math.sin(dLng / 2);
25
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
26
+ return R * c;
27
+ };
28
+ /**
29
+ * Helper: Find optimal region for placement
30
+ */
31
+ const findOptimalRegion = (placement, clientRegion) => {
32
+ const candidateRegions = [placement.primaryRegion, ...placement.secondaryRegions];
33
+ const healthyRegions = candidateRegions.filter((regionId) => {
34
+ const region = regions.get(regionId);
35
+ return region?.healthStatus === 'healthy' && region.currentLoad < region.capacity;
36
+ });
37
+ if (healthyRegions.length === 0) {
38
+ return null;
39
+ }
40
+ // If client region specified and local preference enabled
41
+ if (placement.affinityRules.preferLocal &&
42
+ typeof clientRegion === 'string' &&
43
+ clientRegion.length > 0) {
44
+ if (healthyRegions.includes(clientRegion)) {
45
+ return clientRegion;
46
+ }
47
+ }
48
+ // Sort by priority, then by current load (lower is better)
49
+ healthyRegions.sort((a, b) => {
50
+ const regionA = regions.get(a);
51
+ const regionB = regions.get(b);
52
+ if (!regionA || !regionB) {
53
+ return 0;
54
+ }
55
+ if (regionA.priority !== regionB.priority) {
56
+ return regionB.priority - regionA.priority;
57
+ }
58
+ const loadA = regionA.currentLoad / regionA.capacity;
59
+ const loadB = regionB.currentLoad / regionB.capacity;
60
+ return loadA - loadB;
61
+ });
62
+ return healthyRegions[0];
63
+ };
64
+ /**
65
+ * Helper: Perform health check for region
66
+ */
67
+ const performHealthCheck = async (regionId) => {
68
+ const region = regions.get(regionId);
69
+ if (!region) {
70
+ return;
71
+ }
72
+ try {
73
+ // Check if region can acquire lock (indicates healthy Redis connection)
74
+ const lockKey = `health:${regionId}`;
75
+ const acquired = await ClusterLock.acquire({
76
+ lockKey,
77
+ ttl: 5,
78
+ region: regionId,
79
+ userId: regionId,
80
+ });
81
+ if (acquired) {
82
+ await ClusterLock.release(lockKey, regionId);
83
+ // Update health status
84
+ if (region.healthStatus === 'offline') {
85
+ region.healthStatus = 'healthy';
86
+ Logger.info(`Region recovered: ${regionId}`);
87
+ }
88
+ }
89
+ }
90
+ catch (error) {
91
+ Logger.error(`Health check failed for region: ${regionId}`, error);
92
+ region.healthStatus = 'offline';
93
+ // Trigger failover if enabled
94
+ const policy = failoverPolicies.get(regionId);
95
+ if (policy?.enabled === true && policy.autoFailover) {
96
+ triggerFailover(regionId);
97
+ }
98
+ }
99
+ };
100
+ /**
101
+ * Helper: Trigger failover from unhealthy region
102
+ */
103
+ const triggerFailover = (failedRegionId) => {
104
+ Logger.warn(`Triggering failover from region: ${failedRegionId}`);
105
+ // Find all workers placed in failed region
106
+ const affectedWorkers = [];
107
+ for (const [workerName, placement] of workerPlacements.entries()) {
108
+ if (placement.primaryRegion === failedRegionId) {
109
+ affectedWorkers.push(workerName);
110
+ }
111
+ }
112
+ // Reassign workers to healthy regions
113
+ for (const workerName of affectedWorkers) {
114
+ const placement = workerPlacements.get(workerName);
115
+ if (!placement) {
116
+ continue;
117
+ }
118
+ const newRegion = findOptimalRegion(placement);
119
+ if (newRegion === null) {
120
+ Logger.error(`Failover failed: No healthy region available for worker`, {
121
+ workerName,
122
+ failedRegion: failedRegionId,
123
+ });
124
+ continue;
125
+ }
126
+ Logger.info(`Failover: Moving worker from ${failedRegionId} to ${newRegion}`, {
127
+ workerName,
128
+ });
129
+ // Update placement (would trigger actual worker migration in real implementation)
130
+ placement.primaryRegion = newRegion;
131
+ }
132
+ };
133
+ /**
134
+ * Datacenter Orchestrator - Sealed namespace
135
+ */
136
+ export const DatacenterOrchestrator = Object.freeze({
137
+ /**
138
+ * Register datacenter region
139
+ */
140
+ registerRegion(region) {
141
+ if (regions.has(region.id)) {
142
+ throw ErrorFactory.createConfigError(`Region "${region.id}" already registered`);
143
+ }
144
+ regions.set(region.id, { ...region });
145
+ Logger.info(`Datacenter region registered: ${region.id}`, {
146
+ location: `${region.location.city}, ${region.location.country}`,
147
+ capacity: region.capacity,
148
+ });
149
+ },
150
+ /**
151
+ * Unregister datacenter region
152
+ */
153
+ unregisterRegion(regionId) {
154
+ const region = regions.get(regionId);
155
+ if (!region) {
156
+ throw ErrorFactory.createNotFoundError(`Region "${regionId}" not found`);
157
+ }
158
+ // Check if any workers are still placed in this region
159
+ const hasWorkers = Array.from(workerPlacements.values()).some((p) => p.primaryRegion === regionId || p.secondaryRegions.includes(regionId));
160
+ if (hasWorkers) {
161
+ throw ErrorFactory.createValidationError(`Cannot unregister region with active workers: ${regionId}`);
162
+ }
163
+ regions.delete(regionId);
164
+ // Stop health checks
165
+ const interval = healthCheckIntervals.get(regionId);
166
+ if (interval) {
167
+ clearInterval(interval);
168
+ healthCheckIntervals.delete(regionId);
169
+ }
170
+ Logger.info(`Datacenter region unregistered: ${regionId}`);
171
+ },
172
+ /**
173
+ * Get region information
174
+ */
175
+ getRegion(regionId) {
176
+ const region = regions.get(regionId);
177
+ return region ? { ...region } : null;
178
+ },
179
+ /**
180
+ * List all regions
181
+ */
182
+ listRegions(healthStatus) {
183
+ const allRegions = Array.from(regions.values());
184
+ if (healthStatus) {
185
+ return allRegions.filter((r) => r.healthStatus === healthStatus);
186
+ }
187
+ return allRegions;
188
+ },
189
+ /**
190
+ * Update region health status
191
+ */
192
+ updateRegionHealth(regionId, healthStatus) {
193
+ const region = regions.get(regionId);
194
+ if (!region) {
195
+ throw ErrorFactory.createNotFoundError(`Region "${regionId}" not found`);
196
+ }
197
+ const oldStatus = region.healthStatus;
198
+ region.healthStatus = healthStatus;
199
+ Logger.info(`Region health updated: ${regionId}`, {
200
+ oldStatus,
201
+ newStatus: healthStatus,
202
+ });
203
+ // Trigger failover if region went offline
204
+ if (healthStatus === 'offline' && oldStatus !== 'offline') {
205
+ const policy = failoverPolicies.get(regionId);
206
+ if (policy?.enabled === true && policy.autoFailover) {
207
+ triggerFailover(regionId);
208
+ }
209
+ }
210
+ },
211
+ /**
212
+ * Update region load
213
+ */
214
+ updateRegionLoad(regionId, currentLoad) {
215
+ const region = regions.get(regionId);
216
+ if (!region) {
217
+ throw ErrorFactory.createNotFoundError(`Region "${regionId}" not found`);
218
+ }
219
+ region.currentLoad = currentLoad;
220
+ // Check if region is overloaded
221
+ if (currentLoad > region.capacity * 0.9) {
222
+ Logger.warn(`Region approaching capacity: ${regionId}`, {
223
+ currentLoad,
224
+ capacity: region.capacity,
225
+ });
226
+ region.healthStatus = 'degraded';
227
+ }
228
+ else if (region.healthStatus === 'degraded' && currentLoad < region.capacity * 0.7) {
229
+ region.healthStatus = 'healthy';
230
+ }
231
+ },
232
+ /**
233
+ * Place worker in datacenter
234
+ */
235
+ placeWorker(placement) {
236
+ if (workerPlacements.has(placement.workerName)) {
237
+ throw ErrorFactory.createConfigError(`Worker "${placement.workerName}" already has a placement`);
238
+ }
239
+ // Validate regions exist
240
+ const allRegions = [placement.primaryRegion, ...placement.secondaryRegions];
241
+ for (const regionId of allRegions) {
242
+ if (!regions.has(regionId)) {
243
+ throw ErrorFactory.createNotFoundError(`Region "${regionId}" not found`);
244
+ }
245
+ }
246
+ workerPlacements.set(placement.workerName, { ...placement });
247
+ Logger.info(`Worker placed in datacenter: ${placement.workerName}`, {
248
+ primaryRegion: placement.primaryRegion,
249
+ secondaryRegions: placement.secondaryRegions,
250
+ });
251
+ },
252
+ /**
253
+ * Get worker placement
254
+ */
255
+ getPlacement(workerName) {
256
+ const placement = workerPlacements.get(workerName);
257
+ return placement ? { ...placement } : null;
258
+ },
259
+ /**
260
+ * Update worker placement
261
+ */
262
+ updatePlacement(workerName, updates) {
263
+ const placement = workerPlacements.get(workerName);
264
+ if (!placement) {
265
+ throw ErrorFactory.createNotFoundError(`Placement not found for worker "${workerName}"`);
266
+ }
267
+ Object.assign(placement, updates);
268
+ Logger.info(`Worker placement updated: ${workerName}`);
269
+ },
270
+ /**
271
+ * Remove worker placement
272
+ */
273
+ removeWorker(workerName) {
274
+ if (!workerPlacements.has(workerName)) {
275
+ return;
276
+ }
277
+ workerPlacements.delete(workerName);
278
+ Logger.info(`Worker placement removed: ${workerName}`);
279
+ },
280
+ /**
281
+ * Find optimal region for job execution
282
+ */
283
+ findOptimalRegion(workerName, clientRegion) {
284
+ const placement = workerPlacements.get(workerName);
285
+ if (!placement) {
286
+ throw ErrorFactory.createNotFoundError(`Placement not found for worker "${workerName}"`);
287
+ }
288
+ return findOptimalRegion(placement, clientRegion);
289
+ },
290
+ /**
291
+ * Set failover policy for region
292
+ */
293
+ setFailoverPolicy(regionId, policy) {
294
+ const region = regions.get(regionId);
295
+ if (!region) {
296
+ throw ErrorFactory.createNotFoundError(`Region "${regionId}" not found`);
297
+ }
298
+ failoverPolicies.set(regionId, { ...policy });
299
+ // Start health checks if enabled
300
+ if (policy.enabled) {
301
+ DatacenterOrchestrator.startHealthChecks(regionId, policy.healthCheckInterval);
302
+ }
303
+ Logger.info(`Failover policy set for region: ${regionId}`, {
304
+ autoFailover: policy.autoFailover,
305
+ });
306
+ },
307
+ /**
308
+ * Get failover policy
309
+ */
310
+ getFailoverPolicy(regionId) {
311
+ const policy = failoverPolicies.get(regionId);
312
+ return policy ? { ...policy } : null;
313
+ },
314
+ /**
315
+ * Start health checks for region
316
+ */
317
+ startHealthChecks(regionId, intervalSeconds) {
318
+ // Clear existing interval
319
+ const existing = healthCheckIntervals.get(regionId);
320
+ if (existing) {
321
+ clearInterval(existing);
322
+ }
323
+ // Start new interval
324
+ const interval = setInterval(() => {
325
+ performHealthCheck(regionId);
326
+ }, intervalSeconds * 1000);
327
+ healthCheckIntervals.set(regionId, interval);
328
+ Logger.info(`Health checks started for region: ${regionId}`, {
329
+ interval: intervalSeconds,
330
+ });
331
+ },
332
+ /**
333
+ * Stop health checks for region
334
+ */
335
+ stopHealthChecks(regionId) {
336
+ const interval = healthCheckIntervals.get(regionId);
337
+ if (interval) {
338
+ clearInterval(interval);
339
+ healthCheckIntervals.delete(regionId);
340
+ Logger.info(`Health checks stopped for region: ${regionId}`);
341
+ }
342
+ },
343
+ /**
344
+ * Get datacenter topology
345
+ */
346
+ getTopology() {
347
+ const regionList = Array.from(regions.values());
348
+ const connections = [];
349
+ // Calculate latencies between regions based on distance
350
+ for (let i = 0; i < regionList.length; i++) {
351
+ for (let j = i + 1; j < regionList.length; j++) {
352
+ const from = regionList[i];
353
+ const to = regionList[j];
354
+ if (from.location.coordinates && to.location.coordinates) {
355
+ const distance = calculateDistance(from.location.coordinates.lat, from.location.coordinates.lng, to.location.coordinates.lat, to.location.coordinates.lng);
356
+ // Rough estimate: 1ms per 100km + base latency
357
+ const latency = Math.round(distance / 100) + 10;
358
+ connections.push({
359
+ from: from.id,
360
+ to: to.id,
361
+ latency,
362
+ bandwidth: 10000, // 10 Gbps default
363
+ });
364
+ }
365
+ }
366
+ }
367
+ return {
368
+ regions: regionList,
369
+ connections,
370
+ };
371
+ },
372
+ /**
373
+ * Get load balancing recommendation
374
+ */
375
+ getLoadBalancingRecommendation() {
376
+ const regionList = Array.from(regions.values()).filter((r) => r.healthStatus === 'healthy');
377
+ const totalCapacity = regionList.reduce((sum, r) => sum + r.capacity, 0);
378
+ return regionList.map((region) => {
379
+ const idealLoad = (region.capacity / totalCapacity) * 100;
380
+ const currentLoadPercent = (region.currentLoad / region.capacity) * 100;
381
+ const recommendedAdjustment = idealLoad - currentLoadPercent;
382
+ return {
383
+ regionId: region.id,
384
+ recommendedLoad: Math.max(0, region.currentLoad + recommendedAdjustment),
385
+ };
386
+ });
387
+ },
388
+ /**
389
+ * Shutdown datacenter orchestrator
390
+ */
391
+ shutdown() {
392
+ Logger.info('DatacenterOrchestrator shutting down...');
393
+ // Stop all health checks
394
+ for (const interval of healthCheckIntervals.values()) {
395
+ clearInterval(interval);
396
+ }
397
+ healthCheckIntervals.clear();
398
+ regions.clear();
399
+ workerPlacements.clear();
400
+ failoverPolicies.clear();
401
+ Logger.info('DatacenterOrchestrator shutdown complete');
402
+ },
403
+ });
404
+ // Graceful shutdown handled by WorkerShutdown
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Dead Letter Queue Manager
3
+ * Failed job handling with compliance tracking (GDPR/HIPAA/SOC2)
4
+ * Sealed namespace for immutability
5
+ */
6
+ import { type RedisConfig } from '@zintrust/core';
7
+ export type FailedJobEntry = {
8
+ id: string;
9
+ queueName: string;
10
+ workerName: string;
11
+ jobName: string;
12
+ data: unknown;
13
+ error: {
14
+ message: string;
15
+ stack?: string;
16
+ name: string;
17
+ };
18
+ attemptsMade: number;
19
+ maxAttempts: number;
20
+ failedAt: Date;
21
+ firstAttemptAt: Date;
22
+ lastAttemptAt: Date;
23
+ processingTime: number;
24
+ metadata: {
25
+ version?: string;
26
+ region?: string;
27
+ instanceId?: string;
28
+ };
29
+ complianceFlags: {
30
+ containsPII: boolean;
31
+ containsPHI: boolean;
32
+ dataClassification: 'public' | 'internal' | 'confidential' | 'restricted';
33
+ };
34
+ };
35
+ export type ComplianceAuditEntry = {
36
+ timestamp: Date;
37
+ action: 'access' | 'retry' | 'delete' | 'export' | 'anonymize';
38
+ failedJobId: string;
39
+ userId: string;
40
+ userRole?: string;
41
+ reason: string;
42
+ ipAddress?: string;
43
+ dataAccessed?: string[];
44
+ result: 'success' | 'failure';
45
+ errorMessage?: string;
46
+ };
47
+ export type RetentionPolicy = {
48
+ enabled: boolean;
49
+ defaultRetentionDays: number;
50
+ gdprCompliant: boolean;
51
+ hipaaCompliant: boolean;
52
+ soc2Compliant: boolean;
53
+ autoDeleteAfterDays?: number;
54
+ anonymizeInsteadOfDelete: boolean;
55
+ };
56
+ export type DLQStats = {
57
+ totalFailed: number;
58
+ byQueue: Record<string, number>;
59
+ byWorker: Record<string, number>;
60
+ byErrorType: Record<string, number>;
61
+ oldestFailure: Date | null;
62
+ newestFailure: Date | null;
63
+ averageAttempts: number;
64
+ retentionViolations: number;
65
+ };
66
+ /**
67
+ * Dead Letter Queue Manager - Sealed namespace
68
+ */
69
+ export declare const DeadLetterQueue: Readonly<{
70
+ /**
71
+ * Initialize DLQ with Redis and retention policy
72
+ */
73
+ initialize(config: RedisConfig, policy: RetentionPolicy): void;
74
+ /**
75
+ * Add failed job to DLQ
76
+ */
77
+ addFailedJob(entry: FailedJobEntry): Promise<void>;
78
+ /**
79
+ * Get failed job by ID
80
+ */
81
+ getFailedJob(queueName: string, jobId: string, userId: string, reason: string): Promise<FailedJobEntry | null>;
82
+ /**
83
+ * Get all failed jobs for a queue
84
+ */
85
+ getFailedJobs(queueName: string, limit?: number): Promise<ReadonlyArray<FailedJobEntry>>;
86
+ /**
87
+ * Retry a failed job
88
+ */
89
+ retry(queueName: string, jobId: string, userId: string, reason: string): Promise<boolean>;
90
+ /**
91
+ * Delete a failed job (GDPR right to deletion)
92
+ */
93
+ deleteFailedJob(queueName: string, jobId: string, userId: string, reason: string): Promise<boolean>;
94
+ /**
95
+ * Anonymize a failed job (GDPR/HIPAA compliance)
96
+ */
97
+ anonymizeFailedJob(queueName: string, jobId: string, userId: string, reason: string): Promise<boolean>;
98
+ /**
99
+ * Get audit log for a failed job
100
+ */
101
+ getAuditLog(failedJobId: string, limit?: number): Promise<ReadonlyArray<ComplianceAuditEntry>>;
102
+ /**
103
+ * Get DLQ statistics
104
+ */
105
+ getStats(): Promise<DLQStats>;
106
+ /**
107
+ * Export failed jobs (compliance)
108
+ */
109
+ exportFailedJobs(queueName: string, userId: string, reason: string): Promise<ReadonlyArray<FailedJobEntry>>;
110
+ /**
111
+ * Update retention policy
112
+ */
113
+ updateRetentionPolicy(policy: RetentionPolicy): void;
114
+ /**
115
+ * Get current retention policy
116
+ */
117
+ getRetentionPolicy(): RetentionPolicy | null;
118
+ /**
119
+ * Shutdown DLQ manager
120
+ */
121
+ shutdown(): Promise<void>;
122
+ }>;