@ifc-lite/geometry 7.2.0 → 7.4.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/coordinate-handler.js +4 -4
- package/dist/coordinate-handler.js.map +1 -1
- package/dist/coordinate-types.d.ts +8 -1
- package/dist/coordinate-types.d.ts.map +1 -1
- package/dist/geometry-parallel-options.d.ts +29 -0
- package/dist/geometry-parallel-options.d.ts.map +1 -1
- package/dist/geometry-parallel.d.ts.map +1 -1
- package/dist/geometry-parallel.js +228 -87
- package/dist/geometry-parallel.js.map +1 -1
- package/dist/geometry-worker-init.d.ts +9 -0
- package/dist/geometry-worker-init.d.ts.map +1 -0
- package/dist/geometry-worker-init.js +64 -0
- package/dist/geometry-worker-init.js.map +1 -0
- package/dist/geometry.worker.d.ts +16 -0
- package/dist/geometry.worker.d.ts.map +1 -1
- package/dist/geometry.worker.js +15 -8
- package/dist/geometry.worker.js.map +1 -1
- package/dist/hung-job-recovery.d.ts +145 -0
- package/dist/hung-job-recovery.d.ts.map +1 -0
- package/dist/hung-job-recovery.js +289 -0
- package/dist/hung-job-recovery.js.map +1 -0
- package/dist/index.d.ts +18 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/dist/rtc-rebase.d.ts +101 -0
- package/dist/rtc-rebase.d.ts.map +1 -0
- package/dist/rtc-rebase.js +135 -0
- package/dist/rtc-rebase.js.map +1 -0
- package/dist/stall-phase.d.ts +111 -0
- package/dist/stall-phase.d.ts.map +1 -0
- package/dist/stall-phase.js +164 -0
- package/dist/stall-phase.js.map +1 -0
- package/dist/types.d.ts +6 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/world-frame.d.ts +44 -5
- package/dist/world-frame.d.ts.map +1 -1
- package/dist/world-frame.js +70 -6
- package/dist/world-frame.js.map +1 -1
- package/package.json +9 -4
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hung-job recovery for the parallel geometry pool (#4884).
|
|
3
|
+
*
|
|
4
|
+
* A geometry worker runs one synchronous WASM call at a time. When a single
|
|
5
|
+
* element's geometry never finishes (an unbounded tessellation / sweep / CDT
|
|
6
|
+
* loop), that call never returns, the worker never reaches its queued chunks,
|
|
7
|
+
* and nothing on the host could time it out: the consumer's stream watchdog
|
|
8
|
+
* failed the WHOLE load once every other worker had drained. Production showed
|
|
9
|
+
* the signature plainly — the same model stalling at the exact same mesh count
|
|
10
|
+
* on every attempt, including the lower-detail resource retry.
|
|
11
|
+
*
|
|
12
|
+
* This module is the host's bookkeeping for escaping that: it remembers which
|
|
13
|
+
* job slices each worker has been sent but not finished, which call is in
|
|
14
|
+
* flight, and when the worker last spoke. When a busy worker stays silent past
|
|
15
|
+
* the hang budget, the pool terminates it, spawns a replacement, and replays
|
|
16
|
+
* the unfinished work from the {@link RecoveryPlan}:
|
|
17
|
+
*
|
|
18
|
+
* - an in-flight call of ONE job is the culprit — it is skipped and reported;
|
|
19
|
+
* - an in-flight call of several jobs is re-run one job per call
|
|
20
|
+
* (`maxBatchJobs: 1`), so the next stall (if any) isolates the element in
|
|
21
|
+
* exactly one more budget instead of a log2 bisection;
|
|
22
|
+
* - the rest of the slice and every later queued slice are replayed as-is.
|
|
23
|
+
*
|
|
24
|
+
* Nothing is emitted twice: a worker posts a call's meshes only after the call
|
|
25
|
+
* returns, and always before the `progress` of its next call, so everything the
|
|
26
|
+
* host already received is strictly before the in-flight range.
|
|
27
|
+
*
|
|
28
|
+
* The ledger is pure bookkeeping (no Worker, no timers) so the policy is
|
|
29
|
+
* unit-testable; {@link startHungJobMonitor} applies it to a live pool.
|
|
30
|
+
*/
|
|
31
|
+
/** Silence budget for one busy worker inside a MULTI-job call before it is
|
|
32
|
+
* replaced (the value a consumer opts in with; recovery is off by default).
|
|
33
|
+
* Above the viewer's 40 s mid-stream watchdog (watchdog.ts), so no call that
|
|
34
|
+
* loaded before recovery existed is disturbed: replacing a worker is not free
|
|
35
|
+
* on huge files (a fresh wasm heap plus a source copy). Such a call is re-run
|
|
36
|
+
* one job per call, never skipped, so a false positive costs time only. */
|
|
37
|
+
export declare const DEFAULT_HUNG_JOB_TIMEOUT_MS = 45000;
|
|
38
|
+
/** A SINGLE-job call is only skipped after this multiple of the budget (90 s by
|
|
39
|
+
* default), so an element that is merely slow is never dropped. */
|
|
40
|
+
export declare const SINGLE_JOB_SKIP_FACTOR = 2;
|
|
41
|
+
/** Upper bound on worker replacements per load. A model where element after
|
|
42
|
+
* element hangs is not one bad element; past this the pool stops recovering
|
|
43
|
+
* and the consumer watchdog reports the stall as before. */
|
|
44
|
+
export declare const MAX_HUNG_JOB_RECOVERIES = 16;
|
|
45
|
+
/** One unfinished job slice as dispatched to a worker. */
|
|
46
|
+
export interface LedgerSlice {
|
|
47
|
+
seq: number;
|
|
48
|
+
/** Flat `[expressId, byteStart, byteEnd]` triples — a private copy. */
|
|
49
|
+
jobs: Uint32Array;
|
|
50
|
+
/** Per-call job cap forwarded with the chunk; undefined = adaptive sizing. */
|
|
51
|
+
maxBatchJobs?: number;
|
|
52
|
+
}
|
|
53
|
+
/** The unfinished work of a hung worker, in replay order. */
|
|
54
|
+
export interface RecoveryPlan {
|
|
55
|
+
/** The single job whose call never returned; skipped. Null when the hung call
|
|
56
|
+
* held several jobs (they are in `slices`, capped at one job per call). */
|
|
57
|
+
skippedJob: Uint32Array | null;
|
|
58
|
+
/** Slices to re-dispatch to the replacement worker, in order. */
|
|
59
|
+
slices: Array<Omit<LedgerSlice, 'seq'>>;
|
|
60
|
+
}
|
|
61
|
+
export declare class WorkerJobLedger {
|
|
62
|
+
private readonly retainSlices;
|
|
63
|
+
private readonly states;
|
|
64
|
+
private nextSeq;
|
|
65
|
+
/**
|
|
66
|
+
* @param retainSlices Keep a copy of every dispatched slice for replay. False
|
|
67
|
+
* when recovery is disabled, so a pool that cannot recover pays nothing.
|
|
68
|
+
*/
|
|
69
|
+
constructor(workerCount: number, now: number, retainSlices?: boolean);
|
|
70
|
+
/** Record a chunk before it is transferred to `worker`; returns its seq. */
|
|
71
|
+
recordDispatch(worker: number, jobs: Uint32Array, maxBatchJobs?: number): number;
|
|
72
|
+
/** Any message from the worker proves it is alive. */
|
|
73
|
+
onHeard(worker: number, now: number): void;
|
|
74
|
+
/** Pre-call heartbeat: the worker is about to run `callJobs` jobs of slice `seq`. */
|
|
75
|
+
onCallStart(worker: number, seq: number, fromJob: number, callJobs: number, now: number): void;
|
|
76
|
+
/** The worker finished every call of slice `seq`. */
|
|
77
|
+
onSliceDone(worker: number, seq: number, now: number): void;
|
|
78
|
+
/** The host was suspended: restart every silence clock (see SUSPEND_GAP_INTERVALS). */
|
|
79
|
+
onHostResumed(now: number): void;
|
|
80
|
+
/**
|
|
81
|
+
* Workers to replace: silent inside a multi-job call for `timeoutMs`, or inside
|
|
82
|
+
* a single-job call for `timeoutMs * SINGLE_JOB_SKIP_FACTOR`.
|
|
83
|
+
*/
|
|
84
|
+
findHung(now: number, timeoutMs: number): number[];
|
|
85
|
+
/** True while some busy worker is silent long enough that the consumer's
|
|
86
|
+
* watchdog could fire, yet not long enough to be recovered. */
|
|
87
|
+
needsLiveness(now: number, timeoutMs: number): boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Take the unfinished work of a hung worker and reset its slot for the
|
|
90
|
+
* replacement (which re-records the plan's slices as it dispatches them).
|
|
91
|
+
*/
|
|
92
|
+
takeRecoveryPlan(worker: number, now: number): RecoveryPlan;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The IFC entity keyword of a job (`IFCWALL`), read from the source bytes the
|
|
96
|
+
* job points at. A schema constant, never user data, so it is safe to report;
|
|
97
|
+
* anything that does not look like a keyword comes back as `'UNKNOWN'`.
|
|
98
|
+
*/
|
|
99
|
+
export declare function readJobIfcType(source: Uint8Array, job: Uint32Array): string;
|
|
100
|
+
/** Elements the pool skipped because their geometry never finished. */
|
|
101
|
+
export interface SkippedHungElements {
|
|
102
|
+
/** Express ids of the skipped elements, in skip order. */
|
|
103
|
+
expressIds: number[];
|
|
104
|
+
/** Skipped elements by IFC entity keyword, count-desc then keyword-asc. */
|
|
105
|
+
byType: Array<{
|
|
106
|
+
ifcType: string;
|
|
107
|
+
count: number;
|
|
108
|
+
}>;
|
|
109
|
+
}
|
|
110
|
+
/** Accumulates skipped jobs into the `complete` event's report. */
|
|
111
|
+
export declare class SkippedHungElementsCollector {
|
|
112
|
+
private readonly expressIds;
|
|
113
|
+
private readonly counts;
|
|
114
|
+
add(source: Uint8Array, job: Uint32Array): void;
|
|
115
|
+
get size(): number;
|
|
116
|
+
report(): SkippedHungElements | undefined;
|
|
117
|
+
}
|
|
118
|
+
/** What the monitor needs from the pool that owns the workers. */
|
|
119
|
+
export interface HungJobPool {
|
|
120
|
+
/** The live pool; a replaced slot is overwritten in place. */
|
|
121
|
+
workers: Worker[];
|
|
122
|
+
ledger: WorkerJobLedger;
|
|
123
|
+
makeWorker: () => Worker;
|
|
124
|
+
installHandlers: (worker: Worker, index: number) => void;
|
|
125
|
+
/** Every per-load state message, in order, as recorded by the pool. */
|
|
126
|
+
setup: ReadonlyArray<(worker: Worker) => void>;
|
|
127
|
+
postChunk: (index: number, jobs: Uint32Array, maxBatchJobs?: number) => void;
|
|
128
|
+
streamEndSent: () => boolean;
|
|
129
|
+
terminate: (worker: Worker, label: string) => void;
|
|
130
|
+
/** File bytes the jobs point into, for the skipped elements' IFC types. */
|
|
131
|
+
source: Uint8Array;
|
|
132
|
+
skipped: SkippedHungElementsCollector;
|
|
133
|
+
/** False once the stream failed or was aborted. */
|
|
134
|
+
isLive: () => boolean;
|
|
135
|
+
/** A worker was replaced, or a single-job call is in its skip grace: the
|
|
136
|
+
* consumer's watchdog should see liveness. */
|
|
137
|
+
onLiveness: () => void;
|
|
138
|
+
onFailed: (error: Error) => void;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Poll the ledger and replace every worker that stayed silent inside one call
|
|
142
|
+
* for `timeoutMs`. Returns the stop function; `timeoutMs <= 0` disables it.
|
|
143
|
+
*/
|
|
144
|
+
export declare function startHungJobMonitor(pool: HungJobPool, timeoutMs: number): () => void;
|
|
145
|
+
//# sourceMappingURL=hung-job-recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hung-job-recovery.d.ts","sourceRoot":"","sources":["../src/hung-job-recovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* Hung-job recovery for the parallel geometry pool (#4884).
|
|
6
|
+
*
|
|
7
|
+
* A geometry worker runs one synchronous WASM call at a time. When a single
|
|
8
|
+
* element's geometry never finishes (an unbounded tessellation / sweep / CDT
|
|
9
|
+
* loop), that call never returns, the worker never reaches its queued chunks,
|
|
10
|
+
* and nothing on the host could time it out: the consumer's stream watchdog
|
|
11
|
+
* failed the WHOLE load once every other worker had drained. Production showed
|
|
12
|
+
* the signature plainly — the same model stalling at the exact same mesh count
|
|
13
|
+
* on every attempt, including the lower-detail resource retry.
|
|
14
|
+
*
|
|
15
|
+
* This module is the host's bookkeeping for escaping that: it remembers which
|
|
16
|
+
* job slices each worker has been sent but not finished, which call is in
|
|
17
|
+
* flight, and when the worker last spoke. When a busy worker stays silent past
|
|
18
|
+
* the hang budget, the pool terminates it, spawns a replacement, and replays
|
|
19
|
+
* the unfinished work from the {@link RecoveryPlan}:
|
|
20
|
+
*
|
|
21
|
+
* - an in-flight call of ONE job is the culprit — it is skipped and reported;
|
|
22
|
+
* - an in-flight call of several jobs is re-run one job per call
|
|
23
|
+
* (`maxBatchJobs: 1`), so the next stall (if any) isolates the element in
|
|
24
|
+
* exactly one more budget instead of a log2 bisection;
|
|
25
|
+
* - the rest of the slice and every later queued slice are replayed as-is.
|
|
26
|
+
*
|
|
27
|
+
* Nothing is emitted twice: a worker posts a call's meshes only after the call
|
|
28
|
+
* returns, and always before the `progress` of its next call, so everything the
|
|
29
|
+
* host already received is strictly before the in-flight range.
|
|
30
|
+
*
|
|
31
|
+
* The ledger is pure bookkeeping (no Worker, no timers) so the policy is
|
|
32
|
+
* unit-testable; {@link startHungJobMonitor} applies it to a live pool.
|
|
33
|
+
*/
|
|
34
|
+
/** Silence budget for one busy worker inside a MULTI-job call before it is
|
|
35
|
+
* replaced (the value a consumer opts in with; recovery is off by default).
|
|
36
|
+
* Above the viewer's 40 s mid-stream watchdog (watchdog.ts), so no call that
|
|
37
|
+
* loaded before recovery existed is disturbed: replacing a worker is not free
|
|
38
|
+
* on huge files (a fresh wasm heap plus a source copy). Such a call is re-run
|
|
39
|
+
* one job per call, never skipped, so a false positive costs time only. */
|
|
40
|
+
export const DEFAULT_HUNG_JOB_TIMEOUT_MS = 45_000;
|
|
41
|
+
/** A SINGLE-job call is only skipped after this multiple of the budget (90 s by
|
|
42
|
+
* default), so an element that is merely slow is never dropped. */
|
|
43
|
+
export const SINGLE_JOB_SKIP_FACTOR = 2;
|
|
44
|
+
/** Once a busy worker has been silent for this fraction of the budget (30 s by
|
|
45
|
+
* default, under the viewer's 40 s watchdog) the monitor reports pool liveness
|
|
46
|
+
* until the call returns or is recovered: the pool, not the consumer's
|
|
47
|
+
* watchdog, bounds that call from here on. */
|
|
48
|
+
const LIVENESS_AFTER_FRACTION = 2 / 3;
|
|
49
|
+
/** Monitor ticks further apart than this many intervals mean the host was
|
|
50
|
+
* suspended (sleep, frozen tab). Worker messages posted meanwhile are still
|
|
51
|
+
* queued behind the tick, so silence measured across the gap is not evidence. */
|
|
52
|
+
const SUSPEND_GAP_INTERVALS = 3;
|
|
53
|
+
/** Upper bound on worker replacements per load. A model where element after
|
|
54
|
+
* element hangs is not one bad element; past this the pool stops recovering
|
|
55
|
+
* and the consumer watchdog reports the stall as before. */
|
|
56
|
+
export const MAX_HUNG_JOB_RECOVERIES = 16;
|
|
57
|
+
export class WorkerJobLedger {
|
|
58
|
+
retainSlices;
|
|
59
|
+
states = [];
|
|
60
|
+
nextSeq = 0;
|
|
61
|
+
/**
|
|
62
|
+
* @param retainSlices Keep a copy of every dispatched slice for replay. False
|
|
63
|
+
* when recovery is disabled, so a pool that cannot recover pays nothing.
|
|
64
|
+
*/
|
|
65
|
+
constructor(workerCount, now, retainSlices = true) {
|
|
66
|
+
this.retainSlices = retainSlices;
|
|
67
|
+
for (let i = 0; i < workerCount; i++)
|
|
68
|
+
this.states.push(emptyState(now));
|
|
69
|
+
}
|
|
70
|
+
/** Record a chunk before it is transferred to `worker`; returns its seq. */
|
|
71
|
+
recordDispatch(worker, jobs, maxBatchJobs) {
|
|
72
|
+
const seq = this.nextSeq++;
|
|
73
|
+
if (!this.retainSlices)
|
|
74
|
+
return seq;
|
|
75
|
+
this.states[worker].slices.push({
|
|
76
|
+
seq,
|
|
77
|
+
jobs: jobs.slice(),
|
|
78
|
+
...(maxBatchJobs !== undefined ? { maxBatchJobs } : {}),
|
|
79
|
+
});
|
|
80
|
+
return seq;
|
|
81
|
+
}
|
|
82
|
+
/** Any message from the worker proves it is alive. */
|
|
83
|
+
onHeard(worker, now) {
|
|
84
|
+
this.states[worker].lastHeardAt = now;
|
|
85
|
+
}
|
|
86
|
+
/** Pre-call heartbeat: the worker is about to run `callJobs` jobs of slice `seq`. */
|
|
87
|
+
onCallStart(worker, seq, fromJob, callJobs, now) {
|
|
88
|
+
const state = this.states[worker];
|
|
89
|
+
state.lastHeardAt = now;
|
|
90
|
+
// Slices are processed in dispatch order, so any earlier slice is finished.
|
|
91
|
+
state.slices = state.slices.filter((s) => s.seq >= seq);
|
|
92
|
+
if (state.inFlight)
|
|
93
|
+
state.lastReturnedCallJobs = state.inFlight.callJobs;
|
|
94
|
+
state.inFlight = { seq, fromJob, callJobs };
|
|
95
|
+
}
|
|
96
|
+
/** The worker finished every call of slice `seq`. */
|
|
97
|
+
onSliceDone(worker, seq, now) {
|
|
98
|
+
const state = this.states[worker];
|
|
99
|
+
state.lastHeardAt = now;
|
|
100
|
+
state.slices = state.slices.filter((s) => s.seq > seq);
|
|
101
|
+
if (state.inFlight && state.inFlight.seq <= seq) {
|
|
102
|
+
state.lastReturnedCallJobs = state.inFlight.callJobs;
|
|
103
|
+
state.inFlight = null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/** The host was suspended: restart every silence clock (see SUSPEND_GAP_INTERVALS). */
|
|
107
|
+
onHostResumed(now) {
|
|
108
|
+
for (const state of this.states)
|
|
109
|
+
state.lastHeardAt = now;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Workers to replace: silent inside a multi-job call for `timeoutMs`, or inside
|
|
113
|
+
* a single-job call for `timeoutMs * SINGLE_JOB_SKIP_FACTOR`.
|
|
114
|
+
*/
|
|
115
|
+
findHung(now, timeoutMs) {
|
|
116
|
+
const hung = [];
|
|
117
|
+
this.states.forEach((state, worker) => {
|
|
118
|
+
if (state.inFlight && now - state.lastHeardAt >= budgetFor(state.inFlight.callJobs, timeoutMs))
|
|
119
|
+
hung.push(worker);
|
|
120
|
+
});
|
|
121
|
+
return hung;
|
|
122
|
+
}
|
|
123
|
+
/** True while some busy worker is silent long enough that the consumer's
|
|
124
|
+
* watchdog could fire, yet not long enough to be recovered. */
|
|
125
|
+
needsLiveness(now, timeoutMs) {
|
|
126
|
+
return this.states.some((state) => {
|
|
127
|
+
if (!state.inFlight)
|
|
128
|
+
return false;
|
|
129
|
+
const silent = now - state.lastHeardAt;
|
|
130
|
+
return silent >= timeoutMs * LIVENESS_AFTER_FRACTION && silent < budgetFor(state.inFlight.callJobs, timeoutMs);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Take the unfinished work of a hung worker and reset its slot for the
|
|
135
|
+
* replacement (which re-records the plan's slices as it dispatches them).
|
|
136
|
+
*/
|
|
137
|
+
takeRecoveryPlan(worker, now) {
|
|
138
|
+
const state = this.states[worker];
|
|
139
|
+
const inFlight = state.inFlight;
|
|
140
|
+
const pending = state.slices;
|
|
141
|
+
this.states[worker] = emptyState(now);
|
|
142
|
+
// A fresh worker restarts adaptive sizing at its maximum; in the dense region
|
|
143
|
+
// that just hung, that can trip the budget again. Keep the learned size.
|
|
144
|
+
const capOf = (slice) => slice.maxBatchJobs ?? state.lastReturnedCallJobs;
|
|
145
|
+
const plan = { skippedJob: null, slices: [] };
|
|
146
|
+
for (const slice of pending) {
|
|
147
|
+
if (!inFlight || slice.seq !== inFlight.seq) {
|
|
148
|
+
plan.slices.push(withCap(slice.jobs, capOf(slice)));
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
const callStart = inFlight.fromJob * 3;
|
|
152
|
+
const callEnd = Math.min(slice.jobs.length, callStart + inFlight.callJobs * 3);
|
|
153
|
+
const call = slice.jobs.subarray(callStart, callEnd);
|
|
154
|
+
if (call.length === 3) {
|
|
155
|
+
plan.skippedJob = call.slice();
|
|
156
|
+
}
|
|
157
|
+
else if (call.length > 0) {
|
|
158
|
+
plan.slices.push(withCap(call.slice(), 1));
|
|
159
|
+
}
|
|
160
|
+
if (callEnd < slice.jobs.length) {
|
|
161
|
+
plan.slices.push(withCap(slice.jobs.slice(callEnd), capOf(slice)));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return plan;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function emptyState(now) {
|
|
168
|
+
return { slices: [], inFlight: null, lastReturnedCallJobs: undefined, lastHeardAt: now };
|
|
169
|
+
}
|
|
170
|
+
function budgetFor(callJobs, timeoutMs) {
|
|
171
|
+
return callJobs === 1 ? timeoutMs * SINGLE_JOB_SKIP_FACTOR : timeoutMs;
|
|
172
|
+
}
|
|
173
|
+
function withCap(jobs, maxBatchJobs) {
|
|
174
|
+
return maxBatchJobs !== undefined ? { jobs, maxBatchJobs } : { jobs };
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* The IFC entity keyword of a job (`IFCWALL`), read from the source bytes the
|
|
178
|
+
* job points at. A schema constant, never user data, so it is safe to report;
|
|
179
|
+
* anything that does not look like a keyword comes back as `'UNKNOWN'`.
|
|
180
|
+
*/
|
|
181
|
+
export function readJobIfcType(source, job) {
|
|
182
|
+
const start = job[1];
|
|
183
|
+
const end = Math.min(job[2], source.length, start + 256);
|
|
184
|
+
let i = start;
|
|
185
|
+
while (i < end && source[i] !== 0x3d /* = */)
|
|
186
|
+
i++;
|
|
187
|
+
i++;
|
|
188
|
+
while (i < end && (source[i] === 0x20 || source[i] === 0x09))
|
|
189
|
+
i++;
|
|
190
|
+
let keyword = '';
|
|
191
|
+
for (; i < end; i++) {
|
|
192
|
+
const c = source[i];
|
|
193
|
+
const isUpper = c >= 0x41 && c <= 0x5a;
|
|
194
|
+
const isLower = c >= 0x61 && c <= 0x7a;
|
|
195
|
+
const isDigit = c >= 0x30 && c <= 0x39;
|
|
196
|
+
if (!isUpper && !isLower && !isDigit && c !== 0x5f)
|
|
197
|
+
break;
|
|
198
|
+
keyword += String.fromCharCode(isLower ? c - 0x20 : c);
|
|
199
|
+
}
|
|
200
|
+
return /^IFC[A-Z0-9_]+$/.test(keyword) ? keyword : 'UNKNOWN';
|
|
201
|
+
}
|
|
202
|
+
/** Accumulates skipped jobs into the `complete` event's report. */
|
|
203
|
+
export class SkippedHungElementsCollector {
|
|
204
|
+
expressIds = [];
|
|
205
|
+
counts = new Map();
|
|
206
|
+
add(source, job) {
|
|
207
|
+
this.expressIds.push(job[0]);
|
|
208
|
+
const ifcType = readJobIfcType(source, job);
|
|
209
|
+
this.counts.set(ifcType, (this.counts.get(ifcType) ?? 0) + 1);
|
|
210
|
+
}
|
|
211
|
+
get size() {
|
|
212
|
+
return this.expressIds.length;
|
|
213
|
+
}
|
|
214
|
+
report() {
|
|
215
|
+
if (this.expressIds.length === 0)
|
|
216
|
+
return undefined;
|
|
217
|
+
const byType = [...this.counts.entries()]
|
|
218
|
+
.map(([ifcType, count]) => ({ ifcType, count }))
|
|
219
|
+
.sort((a, b) => b.count - a.count || a.ifcType.localeCompare(b.ifcType));
|
|
220
|
+
return { expressIds: [...this.expressIds], byType };
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Poll the ledger and replace every worker that stayed silent inside one call
|
|
225
|
+
* for `timeoutMs`. Returns the stop function; `timeoutMs <= 0` disables it.
|
|
226
|
+
*/
|
|
227
|
+
export function startHungJobMonitor(pool, timeoutMs) {
|
|
228
|
+
if (timeoutMs <= 0)
|
|
229
|
+
return () => { };
|
|
230
|
+
let recoveries = 0;
|
|
231
|
+
const replace = (i) => {
|
|
232
|
+
recoveries++;
|
|
233
|
+
const plan = pool.ledger.takeRecoveryPlan(i, performance.now());
|
|
234
|
+
const hung = pool.workers[i];
|
|
235
|
+
const replacement = pool.makeWorker();
|
|
236
|
+
// Swap first: the pool's stale-worker guard then drops anything the hung one flushes.
|
|
237
|
+
pool.workers[i] = replacement;
|
|
238
|
+
pool.terminate(hung, 'hung process worker');
|
|
239
|
+
pool.installHandlers(replacement, i);
|
|
240
|
+
for (const setup of pool.setup)
|
|
241
|
+
setup(replacement);
|
|
242
|
+
if (plan.skippedJob)
|
|
243
|
+
pool.skipped.add(pool.source, plan.skippedJob);
|
|
244
|
+
for (const slice of plan.slices)
|
|
245
|
+
pool.postChunk(i, slice.jobs, slice.maxBatchJobs);
|
|
246
|
+
if (pool.streamEndSent())
|
|
247
|
+
replacement.postMessage({ type: 'stream-end' });
|
|
248
|
+
console.warn(`[stream] worker[${i}] silent for ${budgetFor(plan.skippedJob ? 1 : 2, timeoutMs)}ms inside one geometry call — replaced ` +
|
|
249
|
+
(plan.skippedJob ? `and skipped entity #${plan.skippedJob[0]}` : 'and re-running that call one job at a time') +
|
|
250
|
+
` (recovery ${recoveries}/${MAX_HUNG_JOB_RECOVERIES})`);
|
|
251
|
+
pool.onLiveness();
|
|
252
|
+
};
|
|
253
|
+
const intervalMs = Math.min(2_000, timeoutMs);
|
|
254
|
+
let lastTickAt = performance.now();
|
|
255
|
+
// A worker must look hung on two consecutive ticks: messages it posted just
|
|
256
|
+
// before a tick are delivered between ticks, never skipped past.
|
|
257
|
+
let suspects = new Set();
|
|
258
|
+
const timer = setInterval(() => {
|
|
259
|
+
const now = performance.now();
|
|
260
|
+
const gap = now - lastTickAt;
|
|
261
|
+
lastTickAt = now;
|
|
262
|
+
if (gap > intervalMs * SUSPEND_GAP_INTERVALS) {
|
|
263
|
+
pool.ledger.onHostResumed(now);
|
|
264
|
+
suspects = new Set();
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
// Past the cap nothing is recovered, so nothing may mask the consumer's watchdog.
|
|
268
|
+
if (!pool.isLive() || recoveries >= MAX_HUNG_JOB_RECOVERIES)
|
|
269
|
+
return;
|
|
270
|
+
if (pool.ledger.needsLiveness(now, timeoutMs))
|
|
271
|
+
pool.onLiveness();
|
|
272
|
+
const hung = pool.ledger.findHung(now, timeoutMs);
|
|
273
|
+
const confirmed = hung.filter((i) => suspects.has(i));
|
|
274
|
+
suspects = new Set(hung.filter((i) => !suspects.has(i)));
|
|
275
|
+
for (const i of confirmed) {
|
|
276
|
+
if (recoveries >= MAX_HUNG_JOB_RECOVERIES)
|
|
277
|
+
return;
|
|
278
|
+
try {
|
|
279
|
+
replace(i);
|
|
280
|
+
}
|
|
281
|
+
catch (err) {
|
|
282
|
+
pool.onFailed(new Error(`Geometry worker failed: hung-worker replacement failed (${err instanceof Error ? err.message : String(err)})`));
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}, intervalMs);
|
|
287
|
+
return () => clearInterval(timer);
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=hung-job-recovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hung-job-recovery.js","sourceRoot":"","sources":["../src/hung-job-recovery.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export { CoordinateHandler, NORMAL_COORD_THRESHOLD_M } from './coordinate-handle
|
|
|
14
14
|
export type { RtcFrame } from './rtc-frame.js';
|
|
15
15
|
export { computeWorkerCount, pickWorkerCount, type WorkerCountInputs, type WorkerCountResult } from './worker-count.js';
|
|
16
16
|
export { getGeometryStreamWatchdogMs, type WatchdogInputs } from './watchdog.js';
|
|
17
|
+
export { DEFAULT_HUNG_JOB_TIMEOUT_MS, type SkippedHungElements } from './hung-job-recovery.js';
|
|
18
|
+
export { type StallPhase, type StallPhaseHandle } from './stall-phase.js';
|
|
17
19
|
export { prewarmSharedWasmModule } from './wasm-shared-module.js';
|
|
18
20
|
export { isWasmAssetUnavailableError, isWorkerScriptSkewMessage, WASM_ASSET_UNAVAILABLE_EVENT, } from './wasm-asset-error.js';
|
|
19
21
|
export { isWasmRuntimeTrap, isWasmRuntimeUnrecoverableError, WASM_RUNTIME_UNRECOVERABLE_CODE, WASM_RUNTIME_UNRECOVERABLE_EVENT, } from './wasm-runtime-trap.js';
|
|
@@ -23,6 +25,7 @@ import { type GeometryStats as PlatformGeometryStats } from './platform-bridge.j
|
|
|
23
25
|
import type { GeometryResult, MeshData, GridAxis, TessellationQuality, KmzAltitudeMode, SimplifyMeshesResult } from './types.js';
|
|
24
26
|
import type { HbjsonStats } from './hbjson-stats.js';
|
|
25
27
|
import { type RtcFrame } from './rtc-frame.js';
|
|
28
|
+
import type { StallPhaseHandle } from './stall-phase.js';
|
|
26
29
|
/**
|
|
27
30
|
* Default quantization grid (metres) for per-entity geometry hashing,
|
|
28
31
|
* mirroring `ifc_lite_geometry::DEFAULT_GEOM_HASH_TOLERANCE` on the Rust
|
|
@@ -151,6 +154,8 @@ export type StreamingGeometryEvent = {
|
|
|
151
154
|
* non-parallel load paths. See ./diagnostics.ts for the field semantics
|
|
152
155
|
* and which counts are exact vs batch-summed upper bounds. */
|
|
153
156
|
diagnostics?: import('./diagnostics.js').GeometryDiagnostics;
|
|
157
|
+
/** Elements skipped because their geometry never finished (#4884); omitted when none. */
|
|
158
|
+
skippedHungElements?: import('./hung-job-recovery.js').SkippedHungElements;
|
|
154
159
|
};
|
|
155
160
|
export declare class GeometryProcessor {
|
|
156
161
|
private static largeFileByteStreamingThreshold;
|
|
@@ -264,7 +269,13 @@ export declare class GeometryProcessor {
|
|
|
264
269
|
* clamped to the memory budget. Geometry output is unaffected (workers
|
|
265
270
|
* process disjoint, deterministic element slices). Undefined ⇒ heuristic.
|
|
266
271
|
*/
|
|
267
|
-
workerCountOverride?: number, sourceFingerprint?: SharedArrayBuffer
|
|
272
|
+
workerCountOverride?: number, sourceFingerprint?: SharedArrayBuffer,
|
|
273
|
+
/** Terminates the worker pool and ends the stream (#4884). */
|
|
274
|
+
signal?: AbortSignal,
|
|
275
|
+
/** Opt in to hung-call recovery; see `ProcessParallelOptions.hungJobTimeoutMs` (#4884). */
|
|
276
|
+
hungJobTimeoutMs?: number,
|
|
277
|
+
/** See `ProcessParallelOptions.stallPhaseHandle` (#4902). */
|
|
278
|
+
stallPhaseHandle?: StallPhaseHandle): AsyncGenerator<StreamingGeometryEvent>;
|
|
268
279
|
/**
|
|
269
280
|
* Adaptive processing: Choose sync or streaming based on file size
|
|
270
281
|
* Small files (< threshold): Load all at once for instant display
|
|
@@ -311,6 +322,12 @@ export declare class GeometryProcessor {
|
|
|
311
322
|
* Geometry output is unaffected by the count.
|
|
312
323
|
*/
|
|
313
324
|
workerCountOverride?: number;
|
|
325
|
+
/** Terminates the parallel worker pool; see `ProcessParallelOptions.signal` (#4884). */
|
|
326
|
+
signal?: AbortSignal;
|
|
327
|
+
/** Opt in to hung-call recovery on the parallel path (#4884). */
|
|
328
|
+
hungJobTimeoutMs?: number;
|
|
329
|
+
/** See `ProcessParallelOptions.stallPhaseHandle` (#4902); parallel path only. */
|
|
330
|
+
stallPhaseHandle?: StallPhaseHandle;
|
|
314
331
|
}): AsyncGenerator<StreamingGeometryEvent>;
|
|
315
332
|
/**
|
|
316
333
|
* Enable per-entity geometry fingerprinting on the WASM mesh pass
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA;;;GAGG;AAGH,OAAO,EAAE,aAAa,EAAE,KAAK,gCAAgC,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAIrL,OAAO,EACL,oBAAoB,EACpB,OAAO,EACP,KAAK,eAAe,EACpB,KAAK,wBAAwB,EAC7B,KAAK,aAAa,IAAI,qBAAqB,EAC3C,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,wBAAwB,EAC7B,KAAK,8BAA8B,EACnC,KAAK,4BAA4B,GAClC,MAAM,sBAAsB,CAAC;AAI9B,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAOjF,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAG9E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACtF,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACxH,OAAO,EAAE,2BAA2B,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,7 @@ export { BufferBuilder } from './buffer-builder.js';
|
|
|
24
24
|
export { CoordinateHandler, NORMAL_COORD_THRESHOLD_M } from './coordinate-handler.js';
|
|
25
25
|
export { computeWorkerCount, pickWorkerCount } from './worker-count.js';
|
|
26
26
|
export { getGeometryStreamWatchdogMs } from './watchdog.js';
|
|
27
|
+
export { DEFAULT_HUNG_JOB_TIMEOUT_MS } from './hung-job-recovery.js';
|
|
27
28
|
// Cold-start prewarm: start the shared wasm fetch+compile before a file is
|
|
28
29
|
// opened so the download overlaps think time instead of blocking first
|
|
29
30
|
// geometry. The host app decides when (idle / intent) and affordability.
|
|
@@ -461,7 +462,13 @@ export class GeometryProcessor {
|
|
|
461
462
|
* clamped to the memory budget. Geometry output is unaffected (workers
|
|
462
463
|
* process disjoint, deterministic element slices). Undefined ⇒ heuristic.
|
|
463
464
|
*/
|
|
464
|
-
workerCountOverride, sourceFingerprint
|
|
465
|
+
workerCountOverride, sourceFingerprint,
|
|
466
|
+
/** Terminates the worker pool and ends the stream (#4884). */
|
|
467
|
+
signal,
|
|
468
|
+
/** Opt in to hung-call recovery; see `ProcessParallelOptions.hungJobTimeoutMs` (#4884). */
|
|
469
|
+
hungJobTimeoutMs,
|
|
470
|
+
/** See `ProcessParallelOptions.stallPhaseHandle` (#4902). */
|
|
471
|
+
stallPhaseHandle) {
|
|
465
472
|
// Initialize if needed
|
|
466
473
|
if (!this.bridge?.isInitialized()) {
|
|
467
474
|
await this.init();
|
|
@@ -469,6 +476,9 @@ export class GeometryProcessor {
|
|
|
469
476
|
yield* processParallel(buffer, this.coordinateHandler, sharedRtcOffset, existingSab, {
|
|
470
477
|
onEntityIndex,
|
|
471
478
|
sourceFingerprint,
|
|
479
|
+
signal,
|
|
480
|
+
hungJobTimeoutMs,
|
|
481
|
+
stallPhaseHandle,
|
|
472
482
|
// Issue #540: forward the merge-layers preference snapshotted
|
|
473
483
|
// at construction time. processParallel posts `set-merge-layers`
|
|
474
484
|
// to every spawned worker right after `init`.
|
|
@@ -554,7 +564,7 @@ export class GeometryProcessor {
|
|
|
554
564
|
&& typeof navigator !== 'undefined'
|
|
555
565
|
&& (navigator.hardwareConcurrency ?? 1) > 1;
|
|
556
566
|
if (useParallel) {
|
|
557
|
-
yield* this.processParallel(buffer, options.sharedRtcOffset, options.existingSab, options.onEntityIndex, options.wasmUrls, options.workerCountOverride, options.sourceFingerprint);
|
|
567
|
+
yield* this.processParallel(buffer, options.sharedRtcOffset, options.existingSab, options.onEntityIndex, options.wasmUrls, options.workerCountOverride, options.sourceFingerprint, options.signal, options.hungJobTimeoutMs, options.stallPhaseHandle);
|
|
558
568
|
}
|
|
559
569
|
else {
|
|
560
570
|
yield* this.processStreaming(buffer, options.entityIndex, batchConfig, options.sharedRtcOffset);
|