@camstack/addon-pipeline 1.2.38 → 1.2.40
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/audio-analyzer/index.js +1 -1
- package/dist/audio-analyzer/index.mjs +1 -1
- package/dist/detection-pipeline/index.js +145 -175
- package/dist/detection-pipeline/index.mjs +120 -150
- package/dist/{dist-Du7_SNiR.mjs → dist-C6p8jcji.mjs} +495 -113
- package/dist/{dist-BvFLZyhW.js → dist-DcMBfoCg.js} +495 -113
- package/dist/{step-definitions-C8tk9fPJ.mjs → event-loop-stall-monitor-BHqCesa1.mjs} +139 -2
- package/dist/{step-definitions-i8O-hxyI.js → event-loop-stall-monitor-oL9xanvX.js} +150 -1
- package/dist/lazy-sharp-B-mb8uWx.mjs +20 -0
- package/dist/lazy-sharp-CcYuXtsa.js +25 -0
- package/dist/motion-wasm/index.js +3 -3
- package/dist/motion-wasm/index.mjs +3 -3
- package/dist/pipeline-runner/index.js +3316 -2428
- package/dist/pipeline-runner/index.mjs +3315 -2428
- package/dist/recorder/index.js +102 -664
- package/dist/recorder/index.mjs +102 -658
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-ByuMjhL3.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-Bt1YkfUW.mjs} +2 -2
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DJnh97n9.mjs +26 -0
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BsNhZnfZ.mjs +26 -0
- package/dist/stream-broker/{hostInit-CfC64ye2.mjs → hostInit-Dyj8Vaql.mjs} +2 -2
- package/dist/stream-broker/index.js +723 -214
- package/dist/stream-broker/index.mjs +723 -214
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-Dx-Vrpyt.js → MaskShapeCanvas-DI4BY7W2-m1RaK_7F.js} +1 -1
- package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-9D-BWwQP.js → MotionZonesSettings-NcxxQN8r-C00UIgFo.js} +1 -1
- package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-HvAetfA4.js → PrivacyMaskSettings-APgPLF7p-DWYllToj.js} +1 -1
- package/embed-dist/assets/index-4fJzjj4H.css +2 -0
- package/embed-dist/assets/index-BaUgbxWl.js +112 -0
- package/embed-dist/index.html +2 -2
- package/package.json +2 -2
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-ByHi7ZAe.mjs +0 -26
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CscpvIRR.mjs +0 -26
- package/embed-dist/assets/index-9Ob2YrIf.js +0 -343
- package/embed-dist/assets/index-CAe6Dg-X.css +0 -2
- package/python/__pycache__/inference_pool.cpython-312.pyc +0 -0
- package/python/__pycache__/inference_pool.cpython-313.pyc +0 -0
- package/python/__pycache__/inference_pool.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_backpressure.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_coreml_cache.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_device_selection.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_layout.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_preprocess.cpython-314.pyc +0 -0
- package/python/__pycache__/yamnet_audio.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/__init__.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/__init__.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/_safety.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/arcface.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/arcface.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/arcface.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/clip.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/clip.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/clip.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/ctc.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/ctc.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/ctc.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/saliency.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/saliency.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/saliency.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/scrfd.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/scrfd.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/scrfd.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/softmax.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/softmax.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/softmax.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/ssd.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/ssd.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/ssd.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/test_clip.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_clip.cpython-313-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_ctc.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_ctc.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/test_ctc.cpython-313-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_ctc.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/test_saliency.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_saliency.cpython-313-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_softmax.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_yolo_nms.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_yolo_nms.cpython-39.pyc +0 -0
- package/python/postprocessors/__pycache__/yamnet.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/yamnet.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/yamnet.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo.cpython-39.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo_seg.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo_seg.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo_seg.cpython-314.pyc +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { D as hfModelUrl, a as COCO_TO_MACRO, i as COCO_80_LABELS, r as AUDIO_MACRO_LABELS } from "./dist-
|
|
1
|
+
import { D as hfModelUrl, a as COCO_TO_MACRO, i as COCO_80_LABELS, r as AUDIO_MACRO_LABELS } from "./dist-C6p8jcji.mjs";
|
|
2
|
+
import { PerformanceObserver } from "node:perf_hooks";
|
|
2
3
|
//#region src/detection-pipeline/registry/model-catalogs.ts
|
|
3
4
|
var HF_REPO = "camstack/camstack-models";
|
|
4
5
|
var HF_SCRYPTED = "scrypted/plugin-models";
|
|
@@ -1807,4 +1808,140 @@ function resolveModelForFormat(stepId, chosenModelId, format) {
|
|
|
1807
1808
|
return getDefaultModelForFormat(stepId, format);
|
|
1808
1809
|
}
|
|
1809
1810
|
//#endregion
|
|
1810
|
-
|
|
1811
|
+
//#region src/detection-pipeline/diagnostics/event-loop-stall-monitor.ts
|
|
1812
|
+
/**
|
|
1813
|
+
* event-loop-stall-monitor — names the thing that freezes the detection process.
|
|
1814
|
+
*
|
|
1815
|
+
* ## What this exists to settle
|
|
1816
|
+
*
|
|
1817
|
+
* On 2026-08-01/02 inference across the whole fleet stalled in bursts: 759
|
|
1818
|
+
* calls in 90 minutes crossed the runner's 20s deadline, p50 41s and max 80s,
|
|
1819
|
+
* and EVERY one of them eventually resolved. Six explanations were killed with
|
|
1820
|
+
* telemetry alone:
|
|
1821
|
+
*
|
|
1822
|
+
* - not a slow GPU or a wedged pool — the work completes, just enormously late;
|
|
1823
|
+
* - not CPU starvation — hosts sat at 8-48% during the freezes;
|
|
1824
|
+
* - not swap — `pswpin/pswpout` are flat zero on every host;
|
|
1825
|
+
* - not a logging artifact — Loki's timestamp trails the in-process one by
|
|
1826
|
+
* 0.1-1.0s at p95, so the gaps are real, not buffered delivery;
|
|
1827
|
+
* - not the v1.2.30 release — the stalls predate it by a day;
|
|
1828
|
+
* - not only the idle-pool recompile — that is real and hub-side, but the
|
|
1829
|
+
* agent stalls with no eviction and no compile at all.
|
|
1830
|
+
*
|
|
1831
|
+
* What IS established: the 10s stats timer — which touches no inference code —
|
|
1832
|
+
* stops firing for 22-88s and resumes at the same instant the abandoned calls
|
|
1833
|
+
* settle. The event loop itself freezes. From outside the process, GC and a
|
|
1834
|
+
* synchronous block are indistinguishable, and guessing between them is how
|
|
1835
|
+
* this investigation would go wrong. So measure it.
|
|
1836
|
+
*
|
|
1837
|
+
* ## How
|
|
1838
|
+
*
|
|
1839
|
+
* A 1s interval whose LATENESS is the freeze: a tick that arrives 40s late means
|
|
1840
|
+
* the loop was blocked ~39s, whatever blocked it. In the same window the GC
|
|
1841
|
+
* observer accumulates pause time. The two numbers together answer the question
|
|
1842
|
+
* outright:
|
|
1843
|
+
*
|
|
1844
|
+
* - `gcMs` ≈ `stallMs` → garbage collection. Look at heap growth.
|
|
1845
|
+
* - `gcMs` ≈ 0 → something SYNCHRONOUS blocked the loop, and GC is innocent.
|
|
1846
|
+
*
|
|
1847
|
+
* Heap and RSS ride along because if it is GC, the next question is always
|
|
1848
|
+
* "growing since when?".
|
|
1849
|
+
*
|
|
1850
|
+
* Deliberately not a histogram (`monitorEventLoopDelay`): that reports a
|
|
1851
|
+
* distribution, and the question here is about ONE outlier and what coincided
|
|
1852
|
+
* with it.
|
|
1853
|
+
*/
|
|
1854
|
+
/** Tick period. Small enough to bound attribution error, large enough to cost
|
|
1855
|
+
* nothing on a process already doing frame work. */
|
|
1856
|
+
var STALL_TICK_MS = 1e3;
|
|
1857
|
+
/**
|
|
1858
|
+
* Report a freeze only past this. The runner's own inference deadline is 20s
|
|
1859
|
+
* and the observed freezes run 22-88s, so this is far below the signal while
|
|
1860
|
+
* staying clear of ordinary scheduling jitter (a busy frame path routinely
|
|
1861
|
+
* overruns a 1s timer by tens of ms).
|
|
1862
|
+
*/
|
|
1863
|
+
var STALL_REPORT_MS = 2e3;
|
|
1864
|
+
/**
|
|
1865
|
+
* Attribute a freeze. Pure, because this is the ONE judgement the whole module
|
|
1866
|
+
* exists to make and it must be testable without freezing a real event loop.
|
|
1867
|
+
*
|
|
1868
|
+
* `gc` when garbage collection accounts for most of the stall; a
|
|
1869
|
+
* `synchronous-block` when it accounts for almost none — that verdict points
|
|
1870
|
+
* away from the heap entirely and at whatever ran without yielding.
|
|
1871
|
+
*/
|
|
1872
|
+
function attributeStall(stallMs, gcMs, gcCount, longestGcMs) {
|
|
1873
|
+
const share = stallMs > 0 ? gcMs / stallMs : 0;
|
|
1874
|
+
return {
|
|
1875
|
+
stallMs,
|
|
1876
|
+
gcMs,
|
|
1877
|
+
gcCount,
|
|
1878
|
+
longestGcMs,
|
|
1879
|
+
cause: share >= .7 ? "gc" : share <= .2 ? "synchronous-block" : "mixed"
|
|
1880
|
+
};
|
|
1881
|
+
}
|
|
1882
|
+
/**
|
|
1883
|
+
* Start watching. Returns a stop function; safe to call twice.
|
|
1884
|
+
*
|
|
1885
|
+
* Never throws into the caller: a diagnostic that can take the detection
|
|
1886
|
+
* process down is worse than no diagnostic. `PerformanceObserver` for `gc` is
|
|
1887
|
+
* unavailable in some embedded runtimes, and that must degrade to
|
|
1888
|
+
* stall-detection-without-attribution rather than a boot failure.
|
|
1889
|
+
*/
|
|
1890
|
+
function startEventLoopStallMonitor(logger, reportThresholdMs = STALL_REPORT_MS) {
|
|
1891
|
+
let gc = {
|
|
1892
|
+
totalMs: 0,
|
|
1893
|
+
count: 0,
|
|
1894
|
+
longestMs: 0
|
|
1895
|
+
};
|
|
1896
|
+
let observer = null;
|
|
1897
|
+
try {
|
|
1898
|
+
observer = new PerformanceObserver((list) => {
|
|
1899
|
+
for (const entry of list.getEntries()) {
|
|
1900
|
+
gc.totalMs += entry.duration;
|
|
1901
|
+
gc.count += 1;
|
|
1902
|
+
if (entry.duration > gc.longestMs) gc.longestMs = entry.duration;
|
|
1903
|
+
}
|
|
1904
|
+
});
|
|
1905
|
+
observer.observe({ entryTypes: ["gc"] });
|
|
1906
|
+
} catch {
|
|
1907
|
+
observer = null;
|
|
1908
|
+
}
|
|
1909
|
+
let expected = Date.now() + STALL_TICK_MS;
|
|
1910
|
+
const timer = setInterval(() => {
|
|
1911
|
+
const now = Date.now();
|
|
1912
|
+
const lateBy = now - expected;
|
|
1913
|
+
const window = gc;
|
|
1914
|
+
gc = {
|
|
1915
|
+
totalMs: 0,
|
|
1916
|
+
count: 0,
|
|
1917
|
+
longestMs: 0
|
|
1918
|
+
};
|
|
1919
|
+
expected = now + STALL_TICK_MS;
|
|
1920
|
+
if (lateBy < reportThresholdMs) return;
|
|
1921
|
+
const verdict = attributeStall(lateBy, Math.round(window.totalMs), window.count, Math.round(window.longestMs));
|
|
1922
|
+
const mem = process.memoryUsage();
|
|
1923
|
+
logger.warn("event loop stalled", { meta: {
|
|
1924
|
+
stallMs: verdict.stallMs,
|
|
1925
|
+
cause: verdict.cause,
|
|
1926
|
+
gcMs: verdict.gcMs,
|
|
1927
|
+
gcCount: verdict.gcCount,
|
|
1928
|
+
longestGcMs: verdict.longestGcMs,
|
|
1929
|
+
gcObserved: observer !== null,
|
|
1930
|
+
heapUsedMb: Math.round(mem.heapUsed / 1e6),
|
|
1931
|
+
heapTotalMb: Math.round(mem.heapTotal / 1e6),
|
|
1932
|
+
rssMb: Math.round(mem.rss / 1e6),
|
|
1933
|
+
externalMb: Math.round(mem.external / 1e6),
|
|
1934
|
+
arrayBuffersMb: Math.round(mem.arrayBuffers / 1e6)
|
|
1935
|
+
} });
|
|
1936
|
+
}, STALL_TICK_MS);
|
|
1937
|
+
timer.unref?.();
|
|
1938
|
+
let stopped = false;
|
|
1939
|
+
return () => {
|
|
1940
|
+
if (stopped) return;
|
|
1941
|
+
stopped = true;
|
|
1942
|
+
clearInterval(timer);
|
|
1943
|
+
observer?.disconnect();
|
|
1944
|
+
};
|
|
1945
|
+
}
|
|
1946
|
+
//#endregion
|
|
1947
|
+
export { getDefaultModelForFormat as a, getStepDefinition as c, ALL_STEPS as i, resolveModelForFormat as l, startEventLoopStallMonitor as n, getDefaultModelForFormatFromDef as o, ALL_PIPELINE_STEPS as r, getStep as s, attributeStall as t };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
const require_dist = require("./dist-
|
|
1
|
+
const require_dist = require("./dist-DcMBfoCg.js");
|
|
2
|
+
let node_perf_hooks = require("node:perf_hooks");
|
|
2
3
|
//#region src/detection-pipeline/registry/model-catalogs.ts
|
|
3
4
|
var HF_REPO = "camstack/camstack-models";
|
|
4
5
|
var HF_SCRYPTED = "scrypted/plugin-models";
|
|
@@ -1807,6 +1808,142 @@ function resolveModelForFormat(stepId, chosenModelId, format) {
|
|
|
1807
1808
|
return getDefaultModelForFormat(stepId, format);
|
|
1808
1809
|
}
|
|
1809
1810
|
//#endregion
|
|
1811
|
+
//#region src/detection-pipeline/diagnostics/event-loop-stall-monitor.ts
|
|
1812
|
+
/**
|
|
1813
|
+
* event-loop-stall-monitor — names the thing that freezes the detection process.
|
|
1814
|
+
*
|
|
1815
|
+
* ## What this exists to settle
|
|
1816
|
+
*
|
|
1817
|
+
* On 2026-08-01/02 inference across the whole fleet stalled in bursts: 759
|
|
1818
|
+
* calls in 90 minutes crossed the runner's 20s deadline, p50 41s and max 80s,
|
|
1819
|
+
* and EVERY one of them eventually resolved. Six explanations were killed with
|
|
1820
|
+
* telemetry alone:
|
|
1821
|
+
*
|
|
1822
|
+
* - not a slow GPU or a wedged pool — the work completes, just enormously late;
|
|
1823
|
+
* - not CPU starvation — hosts sat at 8-48% during the freezes;
|
|
1824
|
+
* - not swap — `pswpin/pswpout` are flat zero on every host;
|
|
1825
|
+
* - not a logging artifact — Loki's timestamp trails the in-process one by
|
|
1826
|
+
* 0.1-1.0s at p95, so the gaps are real, not buffered delivery;
|
|
1827
|
+
* - not the v1.2.30 release — the stalls predate it by a day;
|
|
1828
|
+
* - not only the idle-pool recompile — that is real and hub-side, but the
|
|
1829
|
+
* agent stalls with no eviction and no compile at all.
|
|
1830
|
+
*
|
|
1831
|
+
* What IS established: the 10s stats timer — which touches no inference code —
|
|
1832
|
+
* stops firing for 22-88s and resumes at the same instant the abandoned calls
|
|
1833
|
+
* settle. The event loop itself freezes. From outside the process, GC and a
|
|
1834
|
+
* synchronous block are indistinguishable, and guessing between them is how
|
|
1835
|
+
* this investigation would go wrong. So measure it.
|
|
1836
|
+
*
|
|
1837
|
+
* ## How
|
|
1838
|
+
*
|
|
1839
|
+
* A 1s interval whose LATENESS is the freeze: a tick that arrives 40s late means
|
|
1840
|
+
* the loop was blocked ~39s, whatever blocked it. In the same window the GC
|
|
1841
|
+
* observer accumulates pause time. The two numbers together answer the question
|
|
1842
|
+
* outright:
|
|
1843
|
+
*
|
|
1844
|
+
* - `gcMs` ≈ `stallMs` → garbage collection. Look at heap growth.
|
|
1845
|
+
* - `gcMs` ≈ 0 → something SYNCHRONOUS blocked the loop, and GC is innocent.
|
|
1846
|
+
*
|
|
1847
|
+
* Heap and RSS ride along because if it is GC, the next question is always
|
|
1848
|
+
* "growing since when?".
|
|
1849
|
+
*
|
|
1850
|
+
* Deliberately not a histogram (`monitorEventLoopDelay`): that reports a
|
|
1851
|
+
* distribution, and the question here is about ONE outlier and what coincided
|
|
1852
|
+
* with it.
|
|
1853
|
+
*/
|
|
1854
|
+
/** Tick period. Small enough to bound attribution error, large enough to cost
|
|
1855
|
+
* nothing on a process already doing frame work. */
|
|
1856
|
+
var STALL_TICK_MS = 1e3;
|
|
1857
|
+
/**
|
|
1858
|
+
* Report a freeze only past this. The runner's own inference deadline is 20s
|
|
1859
|
+
* and the observed freezes run 22-88s, so this is far below the signal while
|
|
1860
|
+
* staying clear of ordinary scheduling jitter (a busy frame path routinely
|
|
1861
|
+
* overruns a 1s timer by tens of ms).
|
|
1862
|
+
*/
|
|
1863
|
+
var STALL_REPORT_MS = 2e3;
|
|
1864
|
+
/**
|
|
1865
|
+
* Attribute a freeze. Pure, because this is the ONE judgement the whole module
|
|
1866
|
+
* exists to make and it must be testable without freezing a real event loop.
|
|
1867
|
+
*
|
|
1868
|
+
* `gc` when garbage collection accounts for most of the stall; a
|
|
1869
|
+
* `synchronous-block` when it accounts for almost none — that verdict points
|
|
1870
|
+
* away from the heap entirely and at whatever ran without yielding.
|
|
1871
|
+
*/
|
|
1872
|
+
function attributeStall(stallMs, gcMs, gcCount, longestGcMs) {
|
|
1873
|
+
const share = stallMs > 0 ? gcMs / stallMs : 0;
|
|
1874
|
+
return {
|
|
1875
|
+
stallMs,
|
|
1876
|
+
gcMs,
|
|
1877
|
+
gcCount,
|
|
1878
|
+
longestGcMs,
|
|
1879
|
+
cause: share >= .7 ? "gc" : share <= .2 ? "synchronous-block" : "mixed"
|
|
1880
|
+
};
|
|
1881
|
+
}
|
|
1882
|
+
/**
|
|
1883
|
+
* Start watching. Returns a stop function; safe to call twice.
|
|
1884
|
+
*
|
|
1885
|
+
* Never throws into the caller: a diagnostic that can take the detection
|
|
1886
|
+
* process down is worse than no diagnostic. `PerformanceObserver` for `gc` is
|
|
1887
|
+
* unavailable in some embedded runtimes, and that must degrade to
|
|
1888
|
+
* stall-detection-without-attribution rather than a boot failure.
|
|
1889
|
+
*/
|
|
1890
|
+
function startEventLoopStallMonitor(logger, reportThresholdMs = STALL_REPORT_MS) {
|
|
1891
|
+
let gc = {
|
|
1892
|
+
totalMs: 0,
|
|
1893
|
+
count: 0,
|
|
1894
|
+
longestMs: 0
|
|
1895
|
+
};
|
|
1896
|
+
let observer = null;
|
|
1897
|
+
try {
|
|
1898
|
+
observer = new node_perf_hooks.PerformanceObserver((list) => {
|
|
1899
|
+
for (const entry of list.getEntries()) {
|
|
1900
|
+
gc.totalMs += entry.duration;
|
|
1901
|
+
gc.count += 1;
|
|
1902
|
+
if (entry.duration > gc.longestMs) gc.longestMs = entry.duration;
|
|
1903
|
+
}
|
|
1904
|
+
});
|
|
1905
|
+
observer.observe({ entryTypes: ["gc"] });
|
|
1906
|
+
} catch {
|
|
1907
|
+
observer = null;
|
|
1908
|
+
}
|
|
1909
|
+
let expected = Date.now() + STALL_TICK_MS;
|
|
1910
|
+
const timer = setInterval(() => {
|
|
1911
|
+
const now = Date.now();
|
|
1912
|
+
const lateBy = now - expected;
|
|
1913
|
+
const window = gc;
|
|
1914
|
+
gc = {
|
|
1915
|
+
totalMs: 0,
|
|
1916
|
+
count: 0,
|
|
1917
|
+
longestMs: 0
|
|
1918
|
+
};
|
|
1919
|
+
expected = now + STALL_TICK_MS;
|
|
1920
|
+
if (lateBy < reportThresholdMs) return;
|
|
1921
|
+
const verdict = attributeStall(lateBy, Math.round(window.totalMs), window.count, Math.round(window.longestMs));
|
|
1922
|
+
const mem = process.memoryUsage();
|
|
1923
|
+
logger.warn("event loop stalled", { meta: {
|
|
1924
|
+
stallMs: verdict.stallMs,
|
|
1925
|
+
cause: verdict.cause,
|
|
1926
|
+
gcMs: verdict.gcMs,
|
|
1927
|
+
gcCount: verdict.gcCount,
|
|
1928
|
+
longestGcMs: verdict.longestGcMs,
|
|
1929
|
+
gcObserved: observer !== null,
|
|
1930
|
+
heapUsedMb: Math.round(mem.heapUsed / 1e6),
|
|
1931
|
+
heapTotalMb: Math.round(mem.heapTotal / 1e6),
|
|
1932
|
+
rssMb: Math.round(mem.rss / 1e6),
|
|
1933
|
+
externalMb: Math.round(mem.external / 1e6),
|
|
1934
|
+
arrayBuffersMb: Math.round(mem.arrayBuffers / 1e6)
|
|
1935
|
+
} });
|
|
1936
|
+
}, STALL_TICK_MS);
|
|
1937
|
+
timer.unref?.();
|
|
1938
|
+
let stopped = false;
|
|
1939
|
+
return () => {
|
|
1940
|
+
if (stopped) return;
|
|
1941
|
+
stopped = true;
|
|
1942
|
+
clearInterval(timer);
|
|
1943
|
+
observer?.disconnect();
|
|
1944
|
+
};
|
|
1945
|
+
}
|
|
1946
|
+
//#endregion
|
|
1810
1947
|
Object.defineProperty(exports, "ALL_PIPELINE_STEPS", {
|
|
1811
1948
|
enumerable: true,
|
|
1812
1949
|
get: function() {
|
|
@@ -1819,6 +1956,12 @@ Object.defineProperty(exports, "ALL_STEPS", {
|
|
|
1819
1956
|
return ALL_STEPS;
|
|
1820
1957
|
}
|
|
1821
1958
|
});
|
|
1959
|
+
Object.defineProperty(exports, "attributeStall", {
|
|
1960
|
+
enumerable: true,
|
|
1961
|
+
get: function() {
|
|
1962
|
+
return attributeStall;
|
|
1963
|
+
}
|
|
1964
|
+
});
|
|
1822
1965
|
Object.defineProperty(exports, "getDefaultModelForFormat", {
|
|
1823
1966
|
enumerable: true,
|
|
1824
1967
|
get: function() {
|
|
@@ -1849,3 +1992,9 @@ Object.defineProperty(exports, "resolveModelForFormat", {
|
|
|
1849
1992
|
return resolveModelForFormat;
|
|
1850
1993
|
}
|
|
1851
1994
|
});
|
|
1995
|
+
Object.defineProperty(exports, "startEventLoopStallMonitor", {
|
|
1996
|
+
enumerable: true,
|
|
1997
|
+
get: function() {
|
|
1998
|
+
return startEventLoopStallMonitor;
|
|
1999
|
+
}
|
|
2000
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/shared/lazy-sharp.ts
|
|
2
|
+
/** Loaded on first use, then reused. `null` until someone asks. */
|
|
3
|
+
var sharpPromise = null;
|
|
4
|
+
/**
|
|
5
|
+
* The `sharp` factory, resolved once per process.
|
|
6
|
+
*
|
|
7
|
+
* On failure the memo is CLEARED so a later call retries. A single transient
|
|
8
|
+
* failure (a partially-installed native dep during a deploy) must not poison
|
|
9
|
+
* the encoder for the process's whole lifetime — that would turn a blip into a
|
|
10
|
+
* camera that never produces media again.
|
|
11
|
+
*/
|
|
12
|
+
async function getSharp() {
|
|
13
|
+
if (sharpPromise === null) sharpPromise = import("sharp").then((m) => m.default, (err) => {
|
|
14
|
+
sharpPromise = null;
|
|
15
|
+
throw err;
|
|
16
|
+
});
|
|
17
|
+
return sharpPromise;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { getSharp as t };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/shared/lazy-sharp.ts
|
|
2
|
+
/** Loaded on first use, then reused. `null` until someone asks. */
|
|
3
|
+
var sharpPromise = null;
|
|
4
|
+
/**
|
|
5
|
+
* The `sharp` factory, resolved once per process.
|
|
6
|
+
*
|
|
7
|
+
* On failure the memo is CLEARED so a later call retries. A single transient
|
|
8
|
+
* failure (a partially-installed native dep during a deploy) must not poison
|
|
9
|
+
* the encoder for the process's whole lifetime — that would turn a blip into a
|
|
10
|
+
* camera that never produces media again.
|
|
11
|
+
*/
|
|
12
|
+
async function getSharp() {
|
|
13
|
+
if (sharpPromise === null) sharpPromise = import("sharp").then((m) => m.default, (err) => {
|
|
14
|
+
sharpPromise = null;
|
|
15
|
+
throw err;
|
|
16
|
+
});
|
|
17
|
+
return sharpPromise;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
Object.defineProperty(exports, "getSharp", {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
get: function() {
|
|
23
|
+
return getSharp;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
@@ -2,7 +2,8 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
5
|
+
const require_dist = require("../dist-DcMBfoCg.js");
|
|
6
|
+
const require_lazy_sharp = require("../lazy-sharp-CcYuXtsa.js");
|
|
6
7
|
let node_fs = require("node:fs");
|
|
7
8
|
let node_path = require("node:path");
|
|
8
9
|
//#region src/motion-wasm/wasm-motion-detector.ts
|
|
@@ -226,8 +227,7 @@ var MotionWasmAddon = class MotionWasmAddon extends require_dist.BaseAddon {
|
|
|
226
227
|
let width;
|
|
227
228
|
let height;
|
|
228
229
|
if (frame.format === "jpeg") {
|
|
229
|
-
const
|
|
230
|
-
const { data, info } = await sharp(Buffer.from(frame.data)).grayscale().raw().toBuffer({ resolveWithObject: true });
|
|
230
|
+
const { data, info } = await (await require_lazy_sharp.getSharp())(Buffer.from(frame.data)).grayscale().raw().toBuffer({ resolveWithObject: true });
|
|
231
231
|
gray = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
232
232
|
width = info.width;
|
|
233
233
|
height = info.height;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { A as motionDetectionCapability, E as evaluateZoneRules, K as hydrateSchema, V as BaseAddon, W as DeviceType } from "../dist-
|
|
1
|
+
import { A as motionDetectionCapability, E as evaluateZoneRules, K as hydrateSchema, V as BaseAddon, W as DeviceType } from "../dist-C6p8jcji.mjs";
|
|
2
|
+
import { t as getSharp } from "../lazy-sharp-B-mb8uWx.mjs";
|
|
2
3
|
import { readFileSync } from "node:fs";
|
|
3
4
|
import { join } from "node:path";
|
|
4
5
|
//#region src/motion-wasm/wasm-motion-detector.ts
|
|
@@ -222,8 +223,7 @@ var MotionWasmAddon = class MotionWasmAddon extends BaseAddon {
|
|
|
222
223
|
let width;
|
|
223
224
|
let height;
|
|
224
225
|
if (frame.format === "jpeg") {
|
|
225
|
-
const
|
|
226
|
-
const { data, info } = await sharp(Buffer.from(frame.data)).grayscale().raw().toBuffer({ resolveWithObject: true });
|
|
226
|
+
const { data, info } = await (await getSharp())(Buffer.from(frame.data)).grayscale().raw().toBuffer({ resolveWithObject: true });
|
|
227
227
|
gray = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
228
228
|
width = info.width;
|
|
229
229
|
height = info.height;
|