22import type { ISdk } from "iii-sdk" ;
33import { getHeapStatistics } from "node:v8" ;
44import type { HealthSnapshot } from "../types.js" ;
5+ import type { HealthWorker } from "../types.js" ;
56import type { StateKV } from "../state/kv.js" ;
67import { KV } from "../state/schema.js" ;
78import { evaluateHealth } from "./thresholds.js" ;
@@ -12,12 +13,51 @@ let latestHealthSnapshot: HealthSnapshot | null = null;
1213const BASE_INTERVAL_MS = 30_000 ;
1314const MAX_INTERVAL_MS = 300_000 ; // 5 min cap when backing off
1415
16+ const GHOST_WORKER_CONNECTED_DELTA_MS = 5_000 ;
17+
1518export interface PipelineMetrics {
1619 compressActive : number ;
1720 compressPending : number ;
1821 totalInflight : number ;
1922}
2023
24+ function isGhostWorkerCandidate ( worker : HealthWorker ) : boolean {
25+ return (
26+ worker . status === "connected" &&
27+ ( worker . function_count ?? 0 ) === 0 &&
28+ ! worker . name &&
29+ ! worker . runtime &&
30+ ! worker . version
31+ ) ;
32+ }
33+
34+ function sharesWorkerOrigin ( a : HealthWorker , b : HealthWorker ) : boolean {
35+ if ( a . ip_address && b . ip_address && a . ip_address === b . ip_address ) {
36+ return true ;
37+ }
38+ if (
39+ typeof a . connected_at_ms === "number" &&
40+ typeof b . connected_at_ms === "number" &&
41+ Math . abs ( a . connected_at_ms - b . connected_at_ms ) <= GHOST_WORKER_CONNECTED_DELTA_MS
42+ ) {
43+ return true ;
44+ }
45+ return false ;
46+ }
47+
48+ export function filterGhostWorkers ( workers : HealthWorker [ ] ) : HealthWorker [ ] {
49+ return workers . filter ( ( worker ) => {
50+ if ( ! isGhostWorkerCandidate ( worker ) ) return true ;
51+ return ! workers . some ( ( other ) => {
52+ if ( other . id === worker . id ) return false ;
53+ if ( other . status !== "connected" ) return false ;
54+ if ( ( other . function_count ?? 0 ) <= 0 ) return false ;
55+ if ( ! other . name ) return false ;
56+ return sharesWorkerOrigin ( worker , other ) ;
57+ } ) ;
58+ } ) ;
59+ }
60+
2161export function registerHealthMonitor (
2262 sdk : ISdk ,
2363 kv : StateKV ,
@@ -75,7 +115,7 @@ export function registerHealthMonitor(
75115 unknown ,
76116 { workers ?: HealthSnapshot [ "workers" ] }
77117 > ( { function_id : "engine::workers::list" , payload : { } } ) ;
78- if ( result ?. workers ) workers = result . workers ;
118+ if ( result ?. workers ) workers = filterGhostWorkers ( result . workers ) ;
79119 } catch { }
80120
81121 // Skip KV probe when persist circuit is open — engine is already struggling
0 commit comments