@camstack/addon-post-analysis 1.2.361 → 1.2.363
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/pipeline-analytics/index.js +159 -29
- package/dist/pipeline-analytics/index.mjs +159 -29
- package/package.json +1 -1
|
@@ -64653,6 +64653,11 @@ var LATE_ABSORBED_WORK_SAMPLE_MS = 6e4;
|
|
|
64653
64653
|
/** Absorbed ids remembered after their survivor closed, so late work for
|
|
64654
64654
|
* them is refused rather than resurrected (oldest forgotten first). */
|
|
64655
64655
|
var MAX_RETIRED_ABSORBED_IDS = 4096;
|
|
64656
|
+
/** Closed track ids remembered (oldest forgotten first) so an async completion
|
|
64657
|
+
* settling AFTER `close` is refused instead of re-creating a resident nothing
|
|
64658
|
+
* would ever close. Track ids are unique per birth; 16384 covers hours of
|
|
64659
|
+
* settling at the busiest observed birth rate. */
|
|
64660
|
+
var MAX_CLOSED_TRACK_IDS = 16384;
|
|
64656
64661
|
var TrackResidentState = class {
|
|
64657
64662
|
hooks;
|
|
64658
64663
|
residents = /* @__PURE__ */ new Map();
|
|
@@ -64694,6 +64699,8 @@ var TrackResidentState = class {
|
|
|
64694
64699
|
bestShotHolder = /* @__PURE__ */ new Map();
|
|
64695
64700
|
/** Absorbed id → survivor id, for survivors that already closed (bounded). */
|
|
64696
64701
|
retired = /* @__PURE__ */ new Map();
|
|
64702
|
+
/** Ids closed by `close` (bounded FIFO). Only `open` — a birth — clears one. */
|
|
64703
|
+
closedIds = /* @__PURE__ */ new Set();
|
|
64697
64704
|
/** Per device: start of the current late-work sample window, and how many
|
|
64698
64705
|
* refusals it has swallowed since the last sampled call. */
|
|
64699
64706
|
lateWorkSample = /* @__PURE__ */ new Map();
|
|
@@ -64707,7 +64714,13 @@ var TrackResidentState = class {
|
|
|
64707
64714
|
/** Idempotently create the track's resident record (deviceId travels with
|
|
64708
64715
|
* it so device teardown can enumerate its tracks). */
|
|
64709
64716
|
open(deviceId, trackId) {
|
|
64710
|
-
this.
|
|
64717
|
+
this.closedIds.delete(trackId);
|
|
64718
|
+
this.ensure(deviceId, trackId, "general", "open");
|
|
64719
|
+
}
|
|
64720
|
+
/** True while the track owns a live resident (its survivor's, when absorbed).
|
|
64721
|
+
* Async completions check this before doing work for a track. */
|
|
64722
|
+
isLive(trackId) {
|
|
64723
|
+
return this.residents.has(this.canonical(trackId));
|
|
64711
64724
|
}
|
|
64712
64725
|
/**
|
|
64713
64726
|
* Get-or-create the resident record (every mutator routes through this so
|
|
@@ -64718,15 +64731,19 @@ var TrackResidentState = class {
|
|
|
64718
64731
|
* An absorbed id whose survivor already closed is refused. `undefined` =
|
|
64719
64732
|
* refused (sampled through `onLateAbsorbedWork`); nothing is created.
|
|
64720
64733
|
*/
|
|
64721
|
-
ensure(deviceId, trackId, kind = "general") {
|
|
64734
|
+
ensure(deviceId, trackId, kind = "general", write = "ensure") {
|
|
64722
64735
|
const retiredInto = this.retired.get(trackId);
|
|
64723
64736
|
if (retiredInto !== void 0) {
|
|
64724
|
-
this.refuseLateWork(deviceId, trackId, retiredInto, "survivor-closed");
|
|
64737
|
+
this.refuseLateWork(deviceId, trackId, retiredInto, "survivor-closed", write);
|
|
64738
|
+
return;
|
|
64739
|
+
}
|
|
64740
|
+
if (this.closedIds.has(trackId)) {
|
|
64741
|
+
this.refuseLateWork(deviceId, trackId, trackId, "track-closed", write);
|
|
64725
64742
|
return;
|
|
64726
64743
|
}
|
|
64727
64744
|
const survivorId = this.aliases.get(trackId);
|
|
64728
64745
|
if (survivorId !== void 0 && kind === "bestShot" && (this.bestShotHolder.get(survivorId) ?? survivorId) !== trackId) {
|
|
64729
|
-
this.refuseLateWork(deviceId, trackId, survivorId, "losing-shot");
|
|
64746
|
+
this.refuseLateWork(deviceId, trackId, survivorId, "losing-shot", write);
|
|
64730
64747
|
return;
|
|
64731
64748
|
}
|
|
64732
64749
|
const id = survivorId ?? trackId;
|
|
@@ -64741,10 +64758,10 @@ var TrackResidentState = class {
|
|
|
64741
64758
|
liveId(deviceId, trackId) {
|
|
64742
64759
|
const retiredInto = this.retired.get(trackId);
|
|
64743
64760
|
if (retiredInto === void 0) return this.canonical(trackId);
|
|
64744
|
-
this.refuseLateWork(deviceId, trackId, retiredInto, "survivor-closed");
|
|
64761
|
+
this.refuseLateWork(deviceId, trackId, retiredInto, "survivor-closed", "liveId");
|
|
64745
64762
|
}
|
|
64746
64763
|
/** Count a refused late write; hand the host one sampled line per window. */
|
|
64747
|
-
refuseLateWork(deviceId, trackId, survivorId, reason) {
|
|
64764
|
+
refuseLateWork(deviceId, trackId, survivorId, reason, write) {
|
|
64748
64765
|
const now = Date.now();
|
|
64749
64766
|
const sample = this.lateWorkSample.get(deviceId);
|
|
64750
64767
|
if (sample !== void 0 && now - sample.at < LATE_ABSORBED_WORK_SAMPLE_MS) {
|
|
@@ -64761,7 +64778,8 @@ var TrackResidentState = class {
|
|
|
64761
64778
|
trackId,
|
|
64762
64779
|
survivorId,
|
|
64763
64780
|
reason,
|
|
64764
|
-
refused
|
|
64781
|
+
refused,
|
|
64782
|
+
write
|
|
64765
64783
|
});
|
|
64766
64784
|
}
|
|
64767
64785
|
/**
|
|
@@ -64781,6 +64799,12 @@ var TrackResidentState = class {
|
|
|
64781
64799
|
mediaId: resident.keyFrameMediaId
|
|
64782
64800
|
});
|
|
64783
64801
|
this.hooks.onClose?.(trackId);
|
|
64802
|
+
this.closedIds.add(trackId);
|
|
64803
|
+
while (this.closedIds.size > MAX_CLOSED_TRACK_IDS) {
|
|
64804
|
+
const oldest = this.closedIds.values().next().value;
|
|
64805
|
+
if (oldest === void 0) break;
|
|
64806
|
+
this.closedIds.delete(oldest);
|
|
64807
|
+
}
|
|
64784
64808
|
const absorbed = this.absorbedBy.get(trackId);
|
|
64785
64809
|
this.bestShotHolder.delete(trackId);
|
|
64786
64810
|
if (absorbed !== void 0) {
|
|
@@ -64848,11 +64872,28 @@ var TrackResidentState = class {
|
|
|
64848
64872
|
this.aliases.clear();
|
|
64849
64873
|
this.bestShotHolder.clear();
|
|
64850
64874
|
this.retired.clear();
|
|
64875
|
+
this.closedIds.clear();
|
|
64851
64876
|
this.lateWorkSample.clear();
|
|
64852
64877
|
}
|
|
64853
64878
|
size() {
|
|
64854
64879
|
return this.residents.size;
|
|
64855
64880
|
}
|
|
64881
|
+
/** Residents whose last frame stamp is older than `olderThanMs` (a resident
|
|
64882
|
+
* never stamped is not listed: it carries no clock to judge). The host
|
|
64883
|
+
* subtracts the ids a live tracker still carries — what remains is a record
|
|
64884
|
+
* nothing will ever close. */
|
|
64885
|
+
idleResidents(olderThanMs) {
|
|
64886
|
+
const idle = [];
|
|
64887
|
+
for (const [trackId, resident] of this.residents) {
|
|
64888
|
+
const at = resident.lastFrameAt;
|
|
64889
|
+
if (at !== void 0 && at < olderThanMs) idle.push({
|
|
64890
|
+
trackId,
|
|
64891
|
+
deviceId: resident.deviceId,
|
|
64892
|
+
lastFrameAt: at
|
|
64893
|
+
});
|
|
64894
|
+
}
|
|
64895
|
+
return idle;
|
|
64896
|
+
}
|
|
64856
64897
|
trackIdsForDevice(deviceId) {
|
|
64857
64898
|
const ids = [];
|
|
64858
64899
|
for (const [trackId, resident] of this.residents) if (resident.deviceId === deviceId) ids.push(trackId);
|
|
@@ -64863,7 +64904,7 @@ var TrackResidentState = class {
|
|
|
64863
64904
|
observeBestFrame(deviceId, trackId, confidence, timestamp, edgeClear, centerScore, containment, sizeScore, squareFraction, semantic, canvasFill) {
|
|
64864
64905
|
const id = this.liveId(deviceId, trackId);
|
|
64865
64906
|
if (id === void 0) return false;
|
|
64866
|
-
this.
|
|
64907
|
+
if (this.ensure(deviceId, id, "bestShot", "observeBestFrame") === void 0) return false;
|
|
64867
64908
|
const isNewBest = this.bestFrameTracker.observe(id, confidence, timestamp, edgeClear, centerScore, containment, sizeScore, squareFraction, semantic, canvasFill);
|
|
64868
64909
|
if (isNewBest) this.bestShotHolder.delete(id);
|
|
64869
64910
|
return isNewBest;
|
|
@@ -64930,7 +64971,7 @@ var TrackResidentState = class {
|
|
|
64930
64971
|
...observed,
|
|
64931
64972
|
trackId: id
|
|
64932
64973
|
};
|
|
64933
|
-
this.
|
|
64974
|
+
if (this.ensure(deviceId, id, "general", "observeObjectEmbeddingBest") === void 0) return false;
|
|
64934
64975
|
const modelId = obs.embeddingModelId ?? "";
|
|
64935
64976
|
let selector = this.objectEmbeddingBestSelectors.get(modelId);
|
|
64936
64977
|
if (selector === void 0) {
|
|
@@ -64947,7 +64988,7 @@ var TrackResidentState = class {
|
|
|
64947
64988
|
return this.residents.get(this.canonical(trackId))?.keyFrameMediaId ?? this.deferredKeyFrameKeys.get(trackId)?.mediaId;
|
|
64948
64989
|
}
|
|
64949
64990
|
setKeyFrameMediaId(deviceId, trackId, mediaId) {
|
|
64950
|
-
const resident = this.ensure(deviceId, trackId, "bestShot");
|
|
64991
|
+
const resident = this.ensure(deviceId, trackId, "bestShot", "setKeyFrameMediaId");
|
|
64951
64992
|
if (resident !== void 0) resident.keyFrameMediaId = mediaId;
|
|
64952
64993
|
}
|
|
64953
64994
|
/** Settle the keyFrame-id drop (called once the face recognizer's
|
|
@@ -64963,7 +65004,7 @@ var TrackResidentState = class {
|
|
|
64963
65004
|
return this.residents.get(this.canonical(trackId))?.lastFrameAt;
|
|
64964
65005
|
}
|
|
64965
65006
|
setLastFrameAt(deviceId, trackId, atMs) {
|
|
64966
|
-
const resident = this.ensure(deviceId, trackId);
|
|
65007
|
+
const resident = this.ensure(deviceId, trackId, "general", "setLastFrameAt");
|
|
64967
65008
|
if (resident !== void 0) resident.lastFrameAt = atMs;
|
|
64968
65009
|
}
|
|
64969
65010
|
anyFirstFramePending() {
|
|
@@ -64983,7 +65024,7 @@ var TrackResidentState = class {
|
|
|
64983
65024
|
}
|
|
64984
65025
|
/** A `firstFrame` write landed for this track (see {@link TrackResident.firstFrameLanded}). */
|
|
64985
65026
|
markFirstFrameLanded(deviceId, trackId) {
|
|
64986
|
-
const resident = this.ensure(deviceId, trackId);
|
|
65027
|
+
const resident = this.ensure(deviceId, trackId, "general", "markFirstFrameLanded");
|
|
64987
65028
|
if (resident !== void 0) resident.firstFrameLanded = true;
|
|
64988
65029
|
}
|
|
64989
65030
|
isFirstFrameLanded(trackId) {
|
|
@@ -64993,7 +65034,7 @@ var TrackResidentState = class {
|
|
|
64993
65034
|
return this.residents.get(this.canonical(trackId))?.thumbnailLanded ?? false;
|
|
64994
65035
|
}
|
|
64995
65036
|
markThumbnailLanded(deviceId, trackId) {
|
|
64996
|
-
const resident = this.ensure(deviceId, trackId, "bestShot");
|
|
65037
|
+
const resident = this.ensure(deviceId, trackId, "bestShot", "markThumbnailLanded");
|
|
64997
65038
|
if (resident !== void 0) resident.thumbnailLanded = true;
|
|
64998
65039
|
}
|
|
64999
65040
|
/**
|
|
@@ -65040,14 +65081,14 @@ var TrackResidentState = class {
|
|
|
65040
65081
|
* spend one of the track's three retries.
|
|
65041
65082
|
*/
|
|
65042
65083
|
noteKeyFrameAttempt(deviceId, trackId, atMs, retry) {
|
|
65043
|
-
const resident = this.ensure(deviceId, trackId, "bestShot");
|
|
65084
|
+
const resident = this.ensure(deviceId, trackId, "bestShot", "noteKeyFrameAttempt");
|
|
65044
65085
|
if (resident === void 0) return;
|
|
65045
65086
|
resident.keyFrameLastAttemptAt = atMs;
|
|
65046
65087
|
if (retry) resident.keyFrameRetries += 1;
|
|
65047
65088
|
}
|
|
65048
65089
|
/** A `keyFrame` write landed — sticky, and the end of the retry path. */
|
|
65049
65090
|
markKeyFrameLanded(deviceId, trackId) {
|
|
65050
|
-
const resident = this.ensure(deviceId, trackId, "bestShot");
|
|
65091
|
+
const resident = this.ensure(deviceId, trackId, "bestShot", "markKeyFrameLanded");
|
|
65051
65092
|
if (resident !== void 0) resident.keyFrameLanded = true;
|
|
65052
65093
|
}
|
|
65053
65094
|
lifecycleUpdateMem(trackId) {
|
|
@@ -65100,7 +65141,7 @@ var TrackResidentState = class {
|
|
|
65100
65141
|
/** Retain the FIRST detection-raster crop per track (zero-media fallback);
|
|
65101
65142
|
* a later frame never overwrites an existing one. */
|
|
65102
65143
|
retainRasterFallback(deviceId, trackId, fallback) {
|
|
65103
|
-
const resident = this.ensure(deviceId, trackId);
|
|
65144
|
+
const resident = this.ensure(deviceId, trackId, "general", "retainRasterFallback");
|
|
65104
65145
|
if (resident !== void 0 && resident.rasterFallback === void 0) resident.rasterFallback = fallback;
|
|
65105
65146
|
}
|
|
65106
65147
|
};
|
|
@@ -93462,6 +93503,8 @@ function planeRunsStationary(source) {
|
|
|
93462
93503
|
*/
|
|
93463
93504
|
var SuppressedBirthRegistry = class {
|
|
93464
93505
|
byDevice = /* @__PURE__ */ new Map();
|
|
93506
|
+
/** Rejected ids whose per-frame skip has already been reported once. */
|
|
93507
|
+
skipReported = /* @__PURE__ */ new Map();
|
|
93465
93508
|
/** Record that this birth was rejected; later frames must not re-upsert it. */
|
|
93466
93509
|
reject(deviceKey, trackId) {
|
|
93467
93510
|
let ids = this.byDevice.get(deviceKey);
|
|
@@ -93475,12 +93518,31 @@ var SuppressedBirthRegistry = class {
|
|
|
93475
93518
|
return this.byDevice.get(deviceKey)?.has(trackId) === true;
|
|
93476
93519
|
}
|
|
93477
93520
|
/**
|
|
93521
|
+
* True the FIRST time a rejected id's frame work is skipped (so the host logs
|
|
93522
|
+
* one line per id, not one per frame); false afterwards.
|
|
93523
|
+
*/
|
|
93524
|
+
firstSkip(deviceKey, trackId) {
|
|
93525
|
+
let ids = this.skipReported.get(deviceKey);
|
|
93526
|
+
if (!ids) {
|
|
93527
|
+
ids = /* @__PURE__ */ new Set();
|
|
93528
|
+
this.skipReported.set(deviceKey, ids);
|
|
93529
|
+
}
|
|
93530
|
+
if (ids.has(trackId)) return false;
|
|
93531
|
+
ids.add(trackId);
|
|
93532
|
+
return true;
|
|
93533
|
+
}
|
|
93534
|
+
/**
|
|
93478
93535
|
* Forget every rejected id the tracker is no longer carrying.
|
|
93479
93536
|
*
|
|
93480
93537
|
* Called once per frame with the ids present THIS frame. An id absent from
|
|
93481
93538
|
* that set can never be upserted again, so holding it serves nothing.
|
|
93482
93539
|
*/
|
|
93483
93540
|
retain(deviceKey, currentTrackIds) {
|
|
93541
|
+
const reported = this.skipReported.get(deviceKey);
|
|
93542
|
+
if (reported) {
|
|
93543
|
+
for (const id of reported) if (!currentTrackIds.has(id)) reported.delete(id);
|
|
93544
|
+
if (reported.size === 0) this.skipReported.delete(deviceKey);
|
|
93545
|
+
}
|
|
93484
93546
|
const ids = this.byDevice.get(deviceKey);
|
|
93485
93547
|
if (!ids) return;
|
|
93486
93548
|
for (const id of ids) if (!currentTrackIds.has(id)) ids.delete(id);
|
|
@@ -93493,6 +93555,7 @@ var SuppressedBirthRegistry = class {
|
|
|
93493
93555
|
/** Drop a device's memory wholesale (device removed / pipeline reset). */
|
|
93494
93556
|
clearDevice(deviceKey) {
|
|
93495
93557
|
this.byDevice.delete(deviceKey);
|
|
93558
|
+
this.skipReported.delete(deviceKey);
|
|
93496
93559
|
}
|
|
93497
93560
|
};
|
|
93498
93561
|
//#endregion
|
|
@@ -110773,6 +110836,10 @@ var NO_PUBLICATION = {
|
|
|
110773
110836
|
url: null,
|
|
110774
110837
|
artifactId: null
|
|
110775
110838
|
};
|
|
110839
|
+
/** How often the resident-vs-live-track heartbeat line is written. */
|
|
110840
|
+
var RESIDENT_HEARTBEAT_INTERVAL_MS = 5 * 6e4;
|
|
110841
|
+
/** A resident idle this long that nothing carries is an orphan. */
|
|
110842
|
+
var RESIDENT_ORPHAN_IDLE_MS = 2 * 6e4;
|
|
110776
110843
|
/**
|
|
110777
110844
|
* A tRPC-shaped router or procedure reached by DYNAMIC name off `ctx.api`.
|
|
110778
110845
|
*
|
|
@@ -111853,12 +111920,13 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
111853
111920
|
this.parkedFrames?.adopt(survivorId, absorbedId, bestShotFrom);
|
|
111854
111921
|
},
|
|
111855
111922
|
onLateAbsorbedWork: (work) => {
|
|
111856
|
-
this.ctx.logger.info("track resident: late work
|
|
111923
|
+
this.ctx.logger.info("track resident: late work after close refused", {
|
|
111857
111924
|
tags: { deviceId: work.deviceId },
|
|
111858
111925
|
meta: {
|
|
111859
111926
|
trackId: work.trackId,
|
|
111860
111927
|
survivorId: work.survivorId,
|
|
111861
111928
|
reason: work.reason,
|
|
111929
|
+
kind: work.write,
|
|
111862
111930
|
refused: work.refused
|
|
111863
111931
|
}
|
|
111864
111932
|
});
|
|
@@ -115322,11 +115390,47 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
115322
115390
|
this.releaseProxy(deviceId);
|
|
115323
115391
|
this.notificationCenter?.onDeviceDeleted(deviceId);
|
|
115324
115392
|
}
|
|
115393
|
+
/** Wall-clock of the last resident heartbeat line. */
|
|
115394
|
+
residentHeartbeatAt = 0;
|
|
115395
|
+
/**
|
|
115396
|
+
* Resident records vs live tracks, once per interval: a resident count that
|
|
115397
|
+
* climbs past the live-track count is the signature of a record nothing
|
|
115398
|
+
* closes (the late-completion ghost fixed 2026-10-14).
|
|
115399
|
+
*/
|
|
115400
|
+
logResidentHeartbeat(now) {
|
|
115401
|
+
if (now - this.residentHeartbeatAt < RESIDENT_HEARTBEAT_INTERVAL_MS) return;
|
|
115402
|
+
this.residentHeartbeatAt = now;
|
|
115403
|
+
let liveTracks = 0;
|
|
115404
|
+
for (const ids of this.lastActiveTrackIds.values()) liveTracks += ids.size;
|
|
115405
|
+
const orphans = this.orphanResidents(now);
|
|
115406
|
+
const mem = process.memoryUsage();
|
|
115407
|
+
this.ctx.logger.info("analytics resident heartbeat", { meta: {
|
|
115408
|
+
residents: this.residents.size(),
|
|
115409
|
+
liveTracks,
|
|
115410
|
+
orphans: orphans.length,
|
|
115411
|
+
orphanSamples: orphans.slice(0, 3).map((o) => ({
|
|
115412
|
+
trackId: o.trackId,
|
|
115413
|
+
deviceId: o.deviceId
|
|
115414
|
+
})),
|
|
115415
|
+
externalNonBufferMb: Math.max(0, Math.round((mem.external - mem.arrayBuffers) / 1048576))
|
|
115416
|
+
} });
|
|
115417
|
+
}
|
|
115418
|
+
/** Residents neither active in the TrackStore nor carried by the tracker
|
|
115419
|
+
* (`lastActiveTrackIds`) whose last frame is older than the orphan window:
|
|
115420
|
+
* a record no sweep can ever close. Healthy value: 0. */
|
|
115421
|
+
orphanResidents(now) {
|
|
115422
|
+
return this.residents.idleResidents(now - RESIDENT_ORPHAN_IDLE_MS).filter((r) => {
|
|
115423
|
+
if (this.trackStore?.peekActive(r.trackId) !== null) return false;
|
|
115424
|
+
for (const ids of this.lastActiveTrackIds.values()) if (ids.has(r.trackId)) return false;
|
|
115425
|
+
return true;
|
|
115426
|
+
});
|
|
115427
|
+
}
|
|
115325
115428
|
/** Periodic sweeps — TTL promotion + retention/stationary aging. */
|
|
115326
115429
|
startSweepTimers() {
|
|
115327
115430
|
this.ttlSweepTimer = setInterval(() => {
|
|
115328
115431
|
this.sweepExpiredTracks();
|
|
115329
115432
|
this.runPackageStillnessSweep(Date.now());
|
|
115433
|
+
this.logResidentHeartbeat(Date.now());
|
|
115330
115434
|
}, TTL_SWEEP_INTERVAL_MS);
|
|
115331
115435
|
this.faceReembedAutoTimer = setInterval(() => {
|
|
115332
115436
|
this.maybeAutoReembedFaces().then(() => this.faceAlignmentJobs?.maybeAutoRunPhotoPass());
|
|
@@ -116441,7 +116545,10 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
116441
116545
|
}
|
|
116442
116546
|
if (result.rawTrackedDetections.length > 0) {
|
|
116443
116547
|
const { minHits } = await this.resolveDeviceDetectionSensitivitySettings(deviceId);
|
|
116444
|
-
for (const rt of result.rawTrackedDetections)
|
|
116548
|
+
for (const rt of result.rawTrackedDetections) {
|
|
116549
|
+
if (this.suppressedBirths.isRejected(key, rt.trackId)) continue;
|
|
116550
|
+
if (rt.trackAge >= minHits) this.residents.markConfirmed(deviceId, rt.trackId);
|
|
116551
|
+
}
|
|
116445
116552
|
}
|
|
116446
116553
|
const log = this.ctx.logger.withTags({ deviceId });
|
|
116447
116554
|
const prevIds = this.lastActiveTrackIds.get(key) ?? /* @__PURE__ */ new Set();
|
|
@@ -116727,6 +116834,25 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
116727
116834
|
this.deferredBirths.retain(key, currentTrackIds);
|
|
116728
116835
|
this.birthEvidence.retain(key, currentTrackIds);
|
|
116729
116836
|
this.lastActiveTrackIds.set(key, currentTrackIds);
|
|
116837
|
+
const rejectedThisFrame = /* @__PURE__ */ new Set();
|
|
116838
|
+
for (const t of result.tracked) {
|
|
116839
|
+
if (!this.suppressedBirths.isRejected(key, t.trackId)) continue;
|
|
116840
|
+
rejectedThisFrame.add(t.trackId);
|
|
116841
|
+
if (this.suppressedBirths.firstSkip(key, t.trackId)) log.info("frame work skipped — the track birth was suppressed", {
|
|
116842
|
+
tags: { deviceId },
|
|
116843
|
+
meta: {
|
|
116844
|
+
trackId: t.trackId,
|
|
116845
|
+
className: t.className
|
|
116846
|
+
}
|
|
116847
|
+
});
|
|
116848
|
+
}
|
|
116849
|
+
if (rejectedThisFrame.size > 0) result = {
|
|
116850
|
+
...result,
|
|
116851
|
+
tracked: result.tracked.filter((t) => !rejectedThisFrame.has(t.trackId)),
|
|
116852
|
+
rawTrackedDetections: result.rawTrackedDetections.filter((rt) => !rejectedThisFrame.has(rt.trackId)),
|
|
116853
|
+
objectEvents: result.objectEvents.filter((e) => e.trackId === void 0 || !rejectedThisFrame.has(e.trackId)),
|
|
116854
|
+
appearanceEvents: result.appearanceEvents.filter((e) => e.trackId === void 0 || !rejectedThisFrame.has(e.trackId))
|
|
116855
|
+
};
|
|
116730
116856
|
if (currentTrackIds.size > 0) this.lastTrackActivityMs.set(deviceId, Date.now());
|
|
116731
116857
|
const stationarySettings = this.stationarySettingsFromCache(deviceId);
|
|
116732
116858
|
const packageSettings = this.packageDropSettingsFromCache(deviceId);
|
|
@@ -116986,17 +117112,21 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
|
|
|
116986
117112
|
}),
|
|
116987
117113
|
holdKeys: heldCaptureKeys,
|
|
116988
117114
|
staleAfterMs: ENRICHMENT_CAPTURE_STALE_MS,
|
|
116989
|
-
exec: () => pinnedFramePromise.then((pinnedFrame) =>
|
|
116990
|
-
|
|
116991
|
-
|
|
116992
|
-
|
|
116993
|
-
|
|
116994
|
-
|
|
116995
|
-
|
|
116996
|
-
|
|
116997
|
-
|
|
116998
|
-
|
|
116999
|
-
|
|
117115
|
+
exec: () => pinnedFramePromise.then((pinnedFrame) => {
|
|
117116
|
+
const liveWanted = /* @__PURE__ */ new Set();
|
|
117117
|
+
for (const id of rasterFallbackWantedTrackIds) if (this.residents.isLive(id)) liveWanted.add(id);
|
|
117118
|
+
return dispatcher.captureForFrame({
|
|
117119
|
+
deviceId,
|
|
117120
|
+
frameHandle,
|
|
117121
|
+
events: eventTargets,
|
|
117122
|
+
trackFrames: firstFrameTargets,
|
|
117123
|
+
snapshots: snapshotTargets,
|
|
117124
|
+
cropPadding: mediaSettings.cropPadding,
|
|
117125
|
+
rasterFallbackWantedTrackIds: liveWanted,
|
|
117126
|
+
rasterFallbackCandidates: rasterFallbackCandidates.filter((c) => this.residents.isLive(c.trackId)),
|
|
117127
|
+
...pinnedFrame !== null ? { pinnedFrame } : {}
|
|
117128
|
+
});
|
|
117129
|
+
}).then((res) => {
|
|
117000
117130
|
for (const rf of res.rasterFallbacks) this.residents.retainRasterFallback(deviceId, rf.trackId, {
|
|
117001
117131
|
jpeg: rf.jpeg,
|
|
117002
117132
|
timestamp: rf.timestamp
|
|
@@ -64609,6 +64609,11 @@ var LATE_ABSORBED_WORK_SAMPLE_MS = 6e4;
|
|
|
64609
64609
|
/** Absorbed ids remembered after their survivor closed, so late work for
|
|
64610
64610
|
* them is refused rather than resurrected (oldest forgotten first). */
|
|
64611
64611
|
var MAX_RETIRED_ABSORBED_IDS = 4096;
|
|
64612
|
+
/** Closed track ids remembered (oldest forgotten first) so an async completion
|
|
64613
|
+
* settling AFTER `close` is refused instead of re-creating a resident nothing
|
|
64614
|
+
* would ever close. Track ids are unique per birth; 16384 covers hours of
|
|
64615
|
+
* settling at the busiest observed birth rate. */
|
|
64616
|
+
var MAX_CLOSED_TRACK_IDS = 16384;
|
|
64612
64617
|
var TrackResidentState = class {
|
|
64613
64618
|
hooks;
|
|
64614
64619
|
residents = /* @__PURE__ */ new Map();
|
|
@@ -64650,6 +64655,8 @@ var TrackResidentState = class {
|
|
|
64650
64655
|
bestShotHolder = /* @__PURE__ */ new Map();
|
|
64651
64656
|
/** Absorbed id → survivor id, for survivors that already closed (bounded). */
|
|
64652
64657
|
retired = /* @__PURE__ */ new Map();
|
|
64658
|
+
/** Ids closed by `close` (bounded FIFO). Only `open` — a birth — clears one. */
|
|
64659
|
+
closedIds = /* @__PURE__ */ new Set();
|
|
64653
64660
|
/** Per device: start of the current late-work sample window, and how many
|
|
64654
64661
|
* refusals it has swallowed since the last sampled call. */
|
|
64655
64662
|
lateWorkSample = /* @__PURE__ */ new Map();
|
|
@@ -64663,7 +64670,13 @@ var TrackResidentState = class {
|
|
|
64663
64670
|
/** Idempotently create the track's resident record (deviceId travels with
|
|
64664
64671
|
* it so device teardown can enumerate its tracks). */
|
|
64665
64672
|
open(deviceId, trackId) {
|
|
64666
|
-
this.
|
|
64673
|
+
this.closedIds.delete(trackId);
|
|
64674
|
+
this.ensure(deviceId, trackId, "general", "open");
|
|
64675
|
+
}
|
|
64676
|
+
/** True while the track owns a live resident (its survivor's, when absorbed).
|
|
64677
|
+
* Async completions check this before doing work for a track. */
|
|
64678
|
+
isLive(trackId) {
|
|
64679
|
+
return this.residents.has(this.canonical(trackId));
|
|
64667
64680
|
}
|
|
64668
64681
|
/**
|
|
64669
64682
|
* Get-or-create the resident record (every mutator routes through this so
|
|
@@ -64674,15 +64687,19 @@ var TrackResidentState = class {
|
|
|
64674
64687
|
* An absorbed id whose survivor already closed is refused. `undefined` =
|
|
64675
64688
|
* refused (sampled through `onLateAbsorbedWork`); nothing is created.
|
|
64676
64689
|
*/
|
|
64677
|
-
ensure(deviceId, trackId, kind = "general") {
|
|
64690
|
+
ensure(deviceId, trackId, kind = "general", write = "ensure") {
|
|
64678
64691
|
const retiredInto = this.retired.get(trackId);
|
|
64679
64692
|
if (retiredInto !== void 0) {
|
|
64680
|
-
this.refuseLateWork(deviceId, trackId, retiredInto, "survivor-closed");
|
|
64693
|
+
this.refuseLateWork(deviceId, trackId, retiredInto, "survivor-closed", write);
|
|
64694
|
+
return;
|
|
64695
|
+
}
|
|
64696
|
+
if (this.closedIds.has(trackId)) {
|
|
64697
|
+
this.refuseLateWork(deviceId, trackId, trackId, "track-closed", write);
|
|
64681
64698
|
return;
|
|
64682
64699
|
}
|
|
64683
64700
|
const survivorId = this.aliases.get(trackId);
|
|
64684
64701
|
if (survivorId !== void 0 && kind === "bestShot" && (this.bestShotHolder.get(survivorId) ?? survivorId) !== trackId) {
|
|
64685
|
-
this.refuseLateWork(deviceId, trackId, survivorId, "losing-shot");
|
|
64702
|
+
this.refuseLateWork(deviceId, trackId, survivorId, "losing-shot", write);
|
|
64686
64703
|
return;
|
|
64687
64704
|
}
|
|
64688
64705
|
const id = survivorId ?? trackId;
|
|
@@ -64697,10 +64714,10 @@ var TrackResidentState = class {
|
|
|
64697
64714
|
liveId(deviceId, trackId) {
|
|
64698
64715
|
const retiredInto = this.retired.get(trackId);
|
|
64699
64716
|
if (retiredInto === void 0) return this.canonical(trackId);
|
|
64700
|
-
this.refuseLateWork(deviceId, trackId, retiredInto, "survivor-closed");
|
|
64717
|
+
this.refuseLateWork(deviceId, trackId, retiredInto, "survivor-closed", "liveId");
|
|
64701
64718
|
}
|
|
64702
64719
|
/** Count a refused late write; hand the host one sampled line per window. */
|
|
64703
|
-
refuseLateWork(deviceId, trackId, survivorId, reason) {
|
|
64720
|
+
refuseLateWork(deviceId, trackId, survivorId, reason, write) {
|
|
64704
64721
|
const now = Date.now();
|
|
64705
64722
|
const sample = this.lateWorkSample.get(deviceId);
|
|
64706
64723
|
if (sample !== void 0 && now - sample.at < LATE_ABSORBED_WORK_SAMPLE_MS) {
|
|
@@ -64717,7 +64734,8 @@ var TrackResidentState = class {
|
|
|
64717
64734
|
trackId,
|
|
64718
64735
|
survivorId,
|
|
64719
64736
|
reason,
|
|
64720
|
-
refused
|
|
64737
|
+
refused,
|
|
64738
|
+
write
|
|
64721
64739
|
});
|
|
64722
64740
|
}
|
|
64723
64741
|
/**
|
|
@@ -64737,6 +64755,12 @@ var TrackResidentState = class {
|
|
|
64737
64755
|
mediaId: resident.keyFrameMediaId
|
|
64738
64756
|
});
|
|
64739
64757
|
this.hooks.onClose?.(trackId);
|
|
64758
|
+
this.closedIds.add(trackId);
|
|
64759
|
+
while (this.closedIds.size > MAX_CLOSED_TRACK_IDS) {
|
|
64760
|
+
const oldest = this.closedIds.values().next().value;
|
|
64761
|
+
if (oldest === void 0) break;
|
|
64762
|
+
this.closedIds.delete(oldest);
|
|
64763
|
+
}
|
|
64740
64764
|
const absorbed = this.absorbedBy.get(trackId);
|
|
64741
64765
|
this.bestShotHolder.delete(trackId);
|
|
64742
64766
|
if (absorbed !== void 0) {
|
|
@@ -64804,11 +64828,28 @@ var TrackResidentState = class {
|
|
|
64804
64828
|
this.aliases.clear();
|
|
64805
64829
|
this.bestShotHolder.clear();
|
|
64806
64830
|
this.retired.clear();
|
|
64831
|
+
this.closedIds.clear();
|
|
64807
64832
|
this.lateWorkSample.clear();
|
|
64808
64833
|
}
|
|
64809
64834
|
size() {
|
|
64810
64835
|
return this.residents.size;
|
|
64811
64836
|
}
|
|
64837
|
+
/** Residents whose last frame stamp is older than `olderThanMs` (a resident
|
|
64838
|
+
* never stamped is not listed: it carries no clock to judge). The host
|
|
64839
|
+
* subtracts the ids a live tracker still carries — what remains is a record
|
|
64840
|
+
* nothing will ever close. */
|
|
64841
|
+
idleResidents(olderThanMs) {
|
|
64842
|
+
const idle = [];
|
|
64843
|
+
for (const [trackId, resident] of this.residents) {
|
|
64844
|
+
const at = resident.lastFrameAt;
|
|
64845
|
+
if (at !== void 0 && at < olderThanMs) idle.push({
|
|
64846
|
+
trackId,
|
|
64847
|
+
deviceId: resident.deviceId,
|
|
64848
|
+
lastFrameAt: at
|
|
64849
|
+
});
|
|
64850
|
+
}
|
|
64851
|
+
return idle;
|
|
64852
|
+
}
|
|
64812
64853
|
trackIdsForDevice(deviceId) {
|
|
64813
64854
|
const ids = [];
|
|
64814
64855
|
for (const [trackId, resident] of this.residents) if (resident.deviceId === deviceId) ids.push(trackId);
|
|
@@ -64819,7 +64860,7 @@ var TrackResidentState = class {
|
|
|
64819
64860
|
observeBestFrame(deviceId, trackId, confidence, timestamp, edgeClear, centerScore, containment, sizeScore, squareFraction, semantic, canvasFill) {
|
|
64820
64861
|
const id = this.liveId(deviceId, trackId);
|
|
64821
64862
|
if (id === void 0) return false;
|
|
64822
|
-
this.
|
|
64863
|
+
if (this.ensure(deviceId, id, "bestShot", "observeBestFrame") === void 0) return false;
|
|
64823
64864
|
const isNewBest = this.bestFrameTracker.observe(id, confidence, timestamp, edgeClear, centerScore, containment, sizeScore, squareFraction, semantic, canvasFill);
|
|
64824
64865
|
if (isNewBest) this.bestShotHolder.delete(id);
|
|
64825
64866
|
return isNewBest;
|
|
@@ -64886,7 +64927,7 @@ var TrackResidentState = class {
|
|
|
64886
64927
|
...observed,
|
|
64887
64928
|
trackId: id
|
|
64888
64929
|
};
|
|
64889
|
-
this.
|
|
64930
|
+
if (this.ensure(deviceId, id, "general", "observeObjectEmbeddingBest") === void 0) return false;
|
|
64890
64931
|
const modelId = obs.embeddingModelId ?? "";
|
|
64891
64932
|
let selector = this.objectEmbeddingBestSelectors.get(modelId);
|
|
64892
64933
|
if (selector === void 0) {
|
|
@@ -64903,7 +64944,7 @@ var TrackResidentState = class {
|
|
|
64903
64944
|
return this.residents.get(this.canonical(trackId))?.keyFrameMediaId ?? this.deferredKeyFrameKeys.get(trackId)?.mediaId;
|
|
64904
64945
|
}
|
|
64905
64946
|
setKeyFrameMediaId(deviceId, trackId, mediaId) {
|
|
64906
|
-
const resident = this.ensure(deviceId, trackId, "bestShot");
|
|
64947
|
+
const resident = this.ensure(deviceId, trackId, "bestShot", "setKeyFrameMediaId");
|
|
64907
64948
|
if (resident !== void 0) resident.keyFrameMediaId = mediaId;
|
|
64908
64949
|
}
|
|
64909
64950
|
/** Settle the keyFrame-id drop (called once the face recognizer's
|
|
@@ -64919,7 +64960,7 @@ var TrackResidentState = class {
|
|
|
64919
64960
|
return this.residents.get(this.canonical(trackId))?.lastFrameAt;
|
|
64920
64961
|
}
|
|
64921
64962
|
setLastFrameAt(deviceId, trackId, atMs) {
|
|
64922
|
-
const resident = this.ensure(deviceId, trackId);
|
|
64963
|
+
const resident = this.ensure(deviceId, trackId, "general", "setLastFrameAt");
|
|
64923
64964
|
if (resident !== void 0) resident.lastFrameAt = atMs;
|
|
64924
64965
|
}
|
|
64925
64966
|
anyFirstFramePending() {
|
|
@@ -64939,7 +64980,7 @@ var TrackResidentState = class {
|
|
|
64939
64980
|
}
|
|
64940
64981
|
/** A `firstFrame` write landed for this track (see {@link TrackResident.firstFrameLanded}). */
|
|
64941
64982
|
markFirstFrameLanded(deviceId, trackId) {
|
|
64942
|
-
const resident = this.ensure(deviceId, trackId);
|
|
64983
|
+
const resident = this.ensure(deviceId, trackId, "general", "markFirstFrameLanded");
|
|
64943
64984
|
if (resident !== void 0) resident.firstFrameLanded = true;
|
|
64944
64985
|
}
|
|
64945
64986
|
isFirstFrameLanded(trackId) {
|
|
@@ -64949,7 +64990,7 @@ var TrackResidentState = class {
|
|
|
64949
64990
|
return this.residents.get(this.canonical(trackId))?.thumbnailLanded ?? false;
|
|
64950
64991
|
}
|
|
64951
64992
|
markThumbnailLanded(deviceId, trackId) {
|
|
64952
|
-
const resident = this.ensure(deviceId, trackId, "bestShot");
|
|
64993
|
+
const resident = this.ensure(deviceId, trackId, "bestShot", "markThumbnailLanded");
|
|
64953
64994
|
if (resident !== void 0) resident.thumbnailLanded = true;
|
|
64954
64995
|
}
|
|
64955
64996
|
/**
|
|
@@ -64996,14 +65037,14 @@ var TrackResidentState = class {
|
|
|
64996
65037
|
* spend one of the track's three retries.
|
|
64997
65038
|
*/
|
|
64998
65039
|
noteKeyFrameAttempt(deviceId, trackId, atMs, retry) {
|
|
64999
|
-
const resident = this.ensure(deviceId, trackId, "bestShot");
|
|
65040
|
+
const resident = this.ensure(deviceId, trackId, "bestShot", "noteKeyFrameAttempt");
|
|
65000
65041
|
if (resident === void 0) return;
|
|
65001
65042
|
resident.keyFrameLastAttemptAt = atMs;
|
|
65002
65043
|
if (retry) resident.keyFrameRetries += 1;
|
|
65003
65044
|
}
|
|
65004
65045
|
/** A `keyFrame` write landed — sticky, and the end of the retry path. */
|
|
65005
65046
|
markKeyFrameLanded(deviceId, trackId) {
|
|
65006
|
-
const resident = this.ensure(deviceId, trackId, "bestShot");
|
|
65047
|
+
const resident = this.ensure(deviceId, trackId, "bestShot", "markKeyFrameLanded");
|
|
65007
65048
|
if (resident !== void 0) resident.keyFrameLanded = true;
|
|
65008
65049
|
}
|
|
65009
65050
|
lifecycleUpdateMem(trackId) {
|
|
@@ -65056,7 +65097,7 @@ var TrackResidentState = class {
|
|
|
65056
65097
|
/** Retain the FIRST detection-raster crop per track (zero-media fallback);
|
|
65057
65098
|
* a later frame never overwrites an existing one. */
|
|
65058
65099
|
retainRasterFallback(deviceId, trackId, fallback) {
|
|
65059
|
-
const resident = this.ensure(deviceId, trackId);
|
|
65100
|
+
const resident = this.ensure(deviceId, trackId, "general", "retainRasterFallback");
|
|
65060
65101
|
if (resident !== void 0 && resident.rasterFallback === void 0) resident.rasterFallback = fallback;
|
|
65061
65102
|
}
|
|
65062
65103
|
};
|
|
@@ -93367,6 +93408,8 @@ function planeRunsStationary(source) {
|
|
|
93367
93408
|
*/
|
|
93368
93409
|
var SuppressedBirthRegistry = class {
|
|
93369
93410
|
byDevice = /* @__PURE__ */ new Map();
|
|
93411
|
+
/** Rejected ids whose per-frame skip has already been reported once. */
|
|
93412
|
+
skipReported = /* @__PURE__ */ new Map();
|
|
93370
93413
|
/** Record that this birth was rejected; later frames must not re-upsert it. */
|
|
93371
93414
|
reject(deviceKey, trackId) {
|
|
93372
93415
|
let ids = this.byDevice.get(deviceKey);
|
|
@@ -93380,12 +93423,31 @@ var SuppressedBirthRegistry = class {
|
|
|
93380
93423
|
return this.byDevice.get(deviceKey)?.has(trackId) === true;
|
|
93381
93424
|
}
|
|
93382
93425
|
/**
|
|
93426
|
+
* True the FIRST time a rejected id's frame work is skipped (so the host logs
|
|
93427
|
+
* one line per id, not one per frame); false afterwards.
|
|
93428
|
+
*/
|
|
93429
|
+
firstSkip(deviceKey, trackId) {
|
|
93430
|
+
let ids = this.skipReported.get(deviceKey);
|
|
93431
|
+
if (!ids) {
|
|
93432
|
+
ids = /* @__PURE__ */ new Set();
|
|
93433
|
+
this.skipReported.set(deviceKey, ids);
|
|
93434
|
+
}
|
|
93435
|
+
if (ids.has(trackId)) return false;
|
|
93436
|
+
ids.add(trackId);
|
|
93437
|
+
return true;
|
|
93438
|
+
}
|
|
93439
|
+
/**
|
|
93383
93440
|
* Forget every rejected id the tracker is no longer carrying.
|
|
93384
93441
|
*
|
|
93385
93442
|
* Called once per frame with the ids present THIS frame. An id absent from
|
|
93386
93443
|
* that set can never be upserted again, so holding it serves nothing.
|
|
93387
93444
|
*/
|
|
93388
93445
|
retain(deviceKey, currentTrackIds) {
|
|
93446
|
+
const reported = this.skipReported.get(deviceKey);
|
|
93447
|
+
if (reported) {
|
|
93448
|
+
for (const id of reported) if (!currentTrackIds.has(id)) reported.delete(id);
|
|
93449
|
+
if (reported.size === 0) this.skipReported.delete(deviceKey);
|
|
93450
|
+
}
|
|
93389
93451
|
const ids = this.byDevice.get(deviceKey);
|
|
93390
93452
|
if (!ids) return;
|
|
93391
93453
|
for (const id of ids) if (!currentTrackIds.has(id)) ids.delete(id);
|
|
@@ -93398,6 +93460,7 @@ var SuppressedBirthRegistry = class {
|
|
|
93398
93460
|
/** Drop a device's memory wholesale (device removed / pipeline reset). */
|
|
93399
93461
|
clearDevice(deviceKey) {
|
|
93400
93462
|
this.byDevice.delete(deviceKey);
|
|
93463
|
+
this.skipReported.delete(deviceKey);
|
|
93401
93464
|
}
|
|
93402
93465
|
};
|
|
93403
93466
|
//#endregion
|
|
@@ -110678,6 +110741,10 @@ var NO_PUBLICATION = {
|
|
|
110678
110741
|
url: null,
|
|
110679
110742
|
artifactId: null
|
|
110680
110743
|
};
|
|
110744
|
+
/** How often the resident-vs-live-track heartbeat line is written. */
|
|
110745
|
+
var RESIDENT_HEARTBEAT_INTERVAL_MS = 5 * 6e4;
|
|
110746
|
+
/** A resident idle this long that nothing carries is an orphan. */
|
|
110747
|
+
var RESIDENT_ORPHAN_IDLE_MS = 2 * 6e4;
|
|
110681
110748
|
/**
|
|
110682
110749
|
* A tRPC-shaped router or procedure reached by DYNAMIC name off `ctx.api`.
|
|
110683
110750
|
*
|
|
@@ -111758,12 +111825,13 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
111758
111825
|
this.parkedFrames?.adopt(survivorId, absorbedId, bestShotFrom);
|
|
111759
111826
|
},
|
|
111760
111827
|
onLateAbsorbedWork: (work) => {
|
|
111761
|
-
this.ctx.logger.info("track resident: late work
|
|
111828
|
+
this.ctx.logger.info("track resident: late work after close refused", {
|
|
111762
111829
|
tags: { deviceId: work.deviceId },
|
|
111763
111830
|
meta: {
|
|
111764
111831
|
trackId: work.trackId,
|
|
111765
111832
|
survivorId: work.survivorId,
|
|
111766
111833
|
reason: work.reason,
|
|
111834
|
+
kind: work.write,
|
|
111767
111835
|
refused: work.refused
|
|
111768
111836
|
}
|
|
111769
111837
|
});
|
|
@@ -115227,11 +115295,47 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
115227
115295
|
this.releaseProxy(deviceId);
|
|
115228
115296
|
this.notificationCenter?.onDeviceDeleted(deviceId);
|
|
115229
115297
|
}
|
|
115298
|
+
/** Wall-clock of the last resident heartbeat line. */
|
|
115299
|
+
residentHeartbeatAt = 0;
|
|
115300
|
+
/**
|
|
115301
|
+
* Resident records vs live tracks, once per interval: a resident count that
|
|
115302
|
+
* climbs past the live-track count is the signature of a record nothing
|
|
115303
|
+
* closes (the late-completion ghost fixed 2026-10-14).
|
|
115304
|
+
*/
|
|
115305
|
+
logResidentHeartbeat(now) {
|
|
115306
|
+
if (now - this.residentHeartbeatAt < RESIDENT_HEARTBEAT_INTERVAL_MS) return;
|
|
115307
|
+
this.residentHeartbeatAt = now;
|
|
115308
|
+
let liveTracks = 0;
|
|
115309
|
+
for (const ids of this.lastActiveTrackIds.values()) liveTracks += ids.size;
|
|
115310
|
+
const orphans = this.orphanResidents(now);
|
|
115311
|
+
const mem = process.memoryUsage();
|
|
115312
|
+
this.ctx.logger.info("analytics resident heartbeat", { meta: {
|
|
115313
|
+
residents: this.residents.size(),
|
|
115314
|
+
liveTracks,
|
|
115315
|
+
orphans: orphans.length,
|
|
115316
|
+
orphanSamples: orphans.slice(0, 3).map((o) => ({
|
|
115317
|
+
trackId: o.trackId,
|
|
115318
|
+
deviceId: o.deviceId
|
|
115319
|
+
})),
|
|
115320
|
+
externalNonBufferMb: Math.max(0, Math.round((mem.external - mem.arrayBuffers) / 1048576))
|
|
115321
|
+
} });
|
|
115322
|
+
}
|
|
115323
|
+
/** Residents neither active in the TrackStore nor carried by the tracker
|
|
115324
|
+
* (`lastActiveTrackIds`) whose last frame is older than the orphan window:
|
|
115325
|
+
* a record no sweep can ever close. Healthy value: 0. */
|
|
115326
|
+
orphanResidents(now) {
|
|
115327
|
+
return this.residents.idleResidents(now - RESIDENT_ORPHAN_IDLE_MS).filter((r) => {
|
|
115328
|
+
if (this.trackStore?.peekActive(r.trackId) !== null) return false;
|
|
115329
|
+
for (const ids of this.lastActiveTrackIds.values()) if (ids.has(r.trackId)) return false;
|
|
115330
|
+
return true;
|
|
115331
|
+
});
|
|
115332
|
+
}
|
|
115230
115333
|
/** Periodic sweeps — TTL promotion + retention/stationary aging. */
|
|
115231
115334
|
startSweepTimers() {
|
|
115232
115335
|
this.ttlSweepTimer = setInterval(() => {
|
|
115233
115336
|
this.sweepExpiredTracks();
|
|
115234
115337
|
this.runPackageStillnessSweep(Date.now());
|
|
115338
|
+
this.logResidentHeartbeat(Date.now());
|
|
115235
115339
|
}, TTL_SWEEP_INTERVAL_MS);
|
|
115236
115340
|
this.faceReembedAutoTimer = setInterval(() => {
|
|
115237
115341
|
this.maybeAutoReembedFaces().then(() => this.faceAlignmentJobs?.maybeAutoRunPhotoPass());
|
|
@@ -116346,7 +116450,10 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
116346
116450
|
}
|
|
116347
116451
|
if (result.rawTrackedDetections.length > 0) {
|
|
116348
116452
|
const { minHits } = await this.resolveDeviceDetectionSensitivitySettings(deviceId);
|
|
116349
|
-
for (const rt of result.rawTrackedDetections)
|
|
116453
|
+
for (const rt of result.rawTrackedDetections) {
|
|
116454
|
+
if (this.suppressedBirths.isRejected(key, rt.trackId)) continue;
|
|
116455
|
+
if (rt.trackAge >= minHits) this.residents.markConfirmed(deviceId, rt.trackId);
|
|
116456
|
+
}
|
|
116350
116457
|
}
|
|
116351
116458
|
const log = this.ctx.logger.withTags({ deviceId });
|
|
116352
116459
|
const prevIds = this.lastActiveTrackIds.get(key) ?? /* @__PURE__ */ new Set();
|
|
@@ -116632,6 +116739,25 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
116632
116739
|
this.deferredBirths.retain(key, currentTrackIds);
|
|
116633
116740
|
this.birthEvidence.retain(key, currentTrackIds);
|
|
116634
116741
|
this.lastActiveTrackIds.set(key, currentTrackIds);
|
|
116742
|
+
const rejectedThisFrame = /* @__PURE__ */ new Set();
|
|
116743
|
+
for (const t of result.tracked) {
|
|
116744
|
+
if (!this.suppressedBirths.isRejected(key, t.trackId)) continue;
|
|
116745
|
+
rejectedThisFrame.add(t.trackId);
|
|
116746
|
+
if (this.suppressedBirths.firstSkip(key, t.trackId)) log.info("frame work skipped — the track birth was suppressed", {
|
|
116747
|
+
tags: { deviceId },
|
|
116748
|
+
meta: {
|
|
116749
|
+
trackId: t.trackId,
|
|
116750
|
+
className: t.className
|
|
116751
|
+
}
|
|
116752
|
+
});
|
|
116753
|
+
}
|
|
116754
|
+
if (rejectedThisFrame.size > 0) result = {
|
|
116755
|
+
...result,
|
|
116756
|
+
tracked: result.tracked.filter((t) => !rejectedThisFrame.has(t.trackId)),
|
|
116757
|
+
rawTrackedDetections: result.rawTrackedDetections.filter((rt) => !rejectedThisFrame.has(rt.trackId)),
|
|
116758
|
+
objectEvents: result.objectEvents.filter((e) => e.trackId === void 0 || !rejectedThisFrame.has(e.trackId)),
|
|
116759
|
+
appearanceEvents: result.appearanceEvents.filter((e) => e.trackId === void 0 || !rejectedThisFrame.has(e.trackId))
|
|
116760
|
+
};
|
|
116635
116761
|
if (currentTrackIds.size > 0) this.lastTrackActivityMs.set(deviceId, Date.now());
|
|
116636
116762
|
const stationarySettings = this.stationarySettingsFromCache(deviceId);
|
|
116637
116763
|
const packageSettings = this.packageDropSettingsFromCache(deviceId);
|
|
@@ -116891,17 +117017,21 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
116891
117017
|
}),
|
|
116892
117018
|
holdKeys: heldCaptureKeys,
|
|
116893
117019
|
staleAfterMs: ENRICHMENT_CAPTURE_STALE_MS,
|
|
116894
|
-
exec: () => pinnedFramePromise.then((pinnedFrame) =>
|
|
116895
|
-
|
|
116896
|
-
|
|
116897
|
-
|
|
116898
|
-
|
|
116899
|
-
|
|
116900
|
-
|
|
116901
|
-
|
|
116902
|
-
|
|
116903
|
-
|
|
116904
|
-
|
|
117020
|
+
exec: () => pinnedFramePromise.then((pinnedFrame) => {
|
|
117021
|
+
const liveWanted = /* @__PURE__ */ new Set();
|
|
117022
|
+
for (const id of rasterFallbackWantedTrackIds) if (this.residents.isLive(id)) liveWanted.add(id);
|
|
117023
|
+
return dispatcher.captureForFrame({
|
|
117024
|
+
deviceId,
|
|
117025
|
+
frameHandle,
|
|
117026
|
+
events: eventTargets,
|
|
117027
|
+
trackFrames: firstFrameTargets,
|
|
117028
|
+
snapshots: snapshotTargets,
|
|
117029
|
+
cropPadding: mediaSettings.cropPadding,
|
|
117030
|
+
rasterFallbackWantedTrackIds: liveWanted,
|
|
117031
|
+
rasterFallbackCandidates: rasterFallbackCandidates.filter((c) => this.residents.isLive(c.trackId)),
|
|
117032
|
+
...pinnedFrame !== null ? { pinnedFrame } : {}
|
|
117033
|
+
});
|
|
117034
|
+
}).then((res) => {
|
|
116905
117035
|
for (const rf of res.rasterFallbacks) this.residents.retainRasterFallback(deviceId, rf.trackId, {
|
|
116906
117036
|
jpeg: rf.jpeg,
|
|
116907
117037
|
timestamp: rf.timestamp
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-post-analysis",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.363",
|
|
4
4
|
"description": "Post-Analysis bundle — enrichment, embedding-encoder, pipeline-analytics. Multi-entry npm package shipping addons that consume pipeline output.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|