@camstack/addon-pipeline 1.2.269 → 1.2.270
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/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CbUvu4Jn.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DZlxPoTV.mjs} +1 -1
- package/dist/stream-broker/{hostInit-9ZN1ghaZ.mjs → hostInit-DFerKhvZ.mjs} +1 -1
- package/dist/stream-broker/index.js +84 -3
- package/dist/stream-broker/index.mjs +84 -3
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/package.json +1 -1
|
@@ -13088,6 +13088,15 @@ var StreamBroker = class StreamBroker {
|
|
|
13088
13088
|
* H.264 video is 30fps → 80pps minimum on a working stream) while a
|
|
13089
13089
|
* real stall is detected before Chrome's ~15s ICE-disconnect timer
|
|
13090
13090
|
* has any chance to fire. */
|
|
13091
|
+
/** How many times a resume re-asks the registry before it stops asking. */
|
|
13092
|
+
static RESUME_RETRY_MAX = 5;
|
|
13093
|
+
/** Spacing of those asks — long enough for a catalog reconcile to land. */
|
|
13094
|
+
static RESUME_RETRY_DELAY_MS = 3e3;
|
|
13095
|
+
resumeRetryTimer;
|
|
13096
|
+
resumeRetryAttempts = 0;
|
|
13097
|
+
resumeRetryExhausted = false;
|
|
13098
|
+
/** One line per suspension when packets arrive with no watchdog armed. */
|
|
13099
|
+
suspendedActivityNoted = false;
|
|
13091
13100
|
static RTP_ACTIVITY_TIMEOUT_MS = 8e3;
|
|
13092
13101
|
/**
|
|
13093
13102
|
* How often the single sweep timer checks {@link lastRtpActivityAt}.
|
|
@@ -13598,6 +13607,54 @@ var StreamBroker = class StreamBroker {
|
|
|
13598
13607
|
this.scheduleReconnect();
|
|
13599
13608
|
}
|
|
13600
13609
|
/**
|
|
13610
|
+
* Ask again for a source the registry did not have yet — bounded.
|
|
13611
|
+
*
|
|
13612
|
+
* Demand exists and nothing can be dialled, so waiting for the NEXT demand
|
|
13613
|
+
* edge is waiting for something that may never come: the consumer is already
|
|
13614
|
+
* attached. The retry is what turns "nothing happened" back into either a
|
|
13615
|
+
* stream or a stated failure, and the bound is what stops a camera that
|
|
13616
|
+
* genuinely publishes nothing from spinning for the life of the process.
|
|
13617
|
+
*/
|
|
13618
|
+
scheduleResumeRetry() {
|
|
13619
|
+
if (this.resumeRetryTimer !== void 0) return;
|
|
13620
|
+
if (this.resumeRetryAttempts >= StreamBroker.RESUME_RETRY_MAX) {
|
|
13621
|
+
if (!this.resumeRetryExhausted) {
|
|
13622
|
+
this.resumeRetryExhausted = true;
|
|
13623
|
+
this.logger?.warn("demand is waiting and this broker still has no source — giving up until something changes", { meta: {
|
|
13624
|
+
brokerId: this.deviceId,
|
|
13625
|
+
attempts: this.resumeRetryAttempts,
|
|
13626
|
+
...this.numericDeviceId === null ? {} : { deviceId: this.numericDeviceId }
|
|
13627
|
+
} });
|
|
13628
|
+
}
|
|
13629
|
+
return;
|
|
13630
|
+
}
|
|
13631
|
+
this.resumeRetryAttempts += 1;
|
|
13632
|
+
this.logger?.warn("demand detected but no source could be resolved — retrying", {
|
|
13633
|
+
...this.numericDeviceId === null ? {} : { tags: { deviceId: this.numericDeviceId } },
|
|
13634
|
+
meta: {
|
|
13635
|
+
brokerId: this.deviceId,
|
|
13636
|
+
attempt: this.resumeRetryAttempts,
|
|
13637
|
+
ofMax: StreamBroker.RESUME_RETRY_MAX
|
|
13638
|
+
}
|
|
13639
|
+
});
|
|
13640
|
+
this.resumeRetryTimer = setTimeout(() => {
|
|
13641
|
+
this.resumeRetryTimer = void 0;
|
|
13642
|
+
if (this.manualStop || this.stopping || !this._suspended) return;
|
|
13643
|
+
if (!this.hasLiveIntent()) return;
|
|
13644
|
+
this.checkDemand();
|
|
13645
|
+
}, StreamBroker.RESUME_RETRY_DELAY_MS);
|
|
13646
|
+
this.resumeRetryTimer.unref?.();
|
|
13647
|
+
}
|
|
13648
|
+
/** A resume that SUCCEEDED clears the episode, counter included. */
|
|
13649
|
+
cancelResumeRetry() {
|
|
13650
|
+
if (this.resumeRetryTimer !== void 0) {
|
|
13651
|
+
clearTimeout(this.resumeRetryTimer);
|
|
13652
|
+
this.resumeRetryTimer = void 0;
|
|
13653
|
+
}
|
|
13654
|
+
this.resumeRetryAttempts = 0;
|
|
13655
|
+
this.resumeRetryExhausted = false;
|
|
13656
|
+
}
|
|
13657
|
+
/**
|
|
13601
13658
|
* Resolve the source to use for the next dial attempt. Prefers the
|
|
13602
13659
|
* manager-supplied resolver — re-derives from the cam-stream
|
|
13603
13660
|
* registry, so a re-publish that updated the URL is honoured on the
|
|
@@ -14106,6 +14163,7 @@ var StreamBroker = class StreamBroker {
|
|
|
14106
14163
|
if (this._suspended) {
|
|
14107
14164
|
const fresh = this.resolveCurrentSource();
|
|
14108
14165
|
if (fresh) {
|
|
14166
|
+
this.cancelResumeRetry();
|
|
14109
14167
|
this._suspended = false;
|
|
14110
14168
|
this.logger?.info("demand detected — resuming stream");
|
|
14111
14169
|
this.start(fresh).catch((err) => {
|
|
@@ -14113,7 +14171,7 @@ var StreamBroker = class StreamBroker {
|
|
|
14113
14171
|
this._suspended = true;
|
|
14114
14172
|
this._status = "idle";
|
|
14115
14173
|
});
|
|
14116
|
-
}
|
|
14174
|
+
} else this.scheduleResumeRetry();
|
|
14117
14175
|
}
|
|
14118
14176
|
} else if (!this._suspended) {
|
|
14119
14177
|
if (!this.suspendTimer) this.suspendTimer = setTimeout(() => {
|
|
@@ -15813,7 +15871,20 @@ var StreamBroker = class StreamBroker {
|
|
|
15813
15871
|
* operations on the highest-frequency path in the busiest process.
|
|
15814
15872
|
*/
|
|
15815
15873
|
kickRtpActivityWatchdog() {
|
|
15816
|
-
if (this.manualStop || this.stopping || this._suspended)
|
|
15874
|
+
if (this.manualStop || this.stopping || this._suspended) {
|
|
15875
|
+
if (this._suspended && !this.suspendedActivityNoted) {
|
|
15876
|
+
this.suspendedActivityNoted = true;
|
|
15877
|
+
this.logger?.warn("source RTP is arriving while this broker is suspended — the stall watchdog is NOT armed for it", {
|
|
15878
|
+
...this.numericDeviceId === null ? {} : { tags: { deviceId: this.numericDeviceId } },
|
|
15879
|
+
meta: {
|
|
15880
|
+
brokerId: this.deviceId,
|
|
15881
|
+
status: this._status
|
|
15882
|
+
}
|
|
15883
|
+
});
|
|
15884
|
+
}
|
|
15885
|
+
return;
|
|
15886
|
+
}
|
|
15887
|
+
this.suspendedActivityNoted = false;
|
|
15817
15888
|
this.lastRtpActivityAt = Date.now();
|
|
15818
15889
|
if (this.rtpActivitySweep !== void 0) return;
|
|
15819
15890
|
this.rtpActivitySweep = setInterval(() => {
|
|
@@ -15853,7 +15924,17 @@ var StreamBroker = class StreamBroker {
|
|
|
15853
15924
|
*/
|
|
15854
15925
|
onRtpActivityWatchdogExpired() {
|
|
15855
15926
|
this.rtpActivityWatchdogFiredCount++;
|
|
15856
|
-
if (this.manualStop || this.stopping || this._suspended)
|
|
15927
|
+
if (this.manualStop || this.stopping || this._suspended) {
|
|
15928
|
+
if (this._suspended) this.logger?.warn("source RTP went silent on a suspended broker — the watchdog is disarmed and nothing will reconnect it", {
|
|
15929
|
+
...this.numericDeviceId === null ? {} : { tags: { deviceId: this.numericDeviceId } },
|
|
15930
|
+
meta: {
|
|
15931
|
+
brokerId: this.deviceId,
|
|
15932
|
+
timeoutMs: StreamBroker.RTP_ACTIVITY_TIMEOUT_MS,
|
|
15933
|
+
firedCount: this.rtpActivityWatchdogFiredCount
|
|
15934
|
+
}
|
|
15935
|
+
});
|
|
15936
|
+
return;
|
|
15937
|
+
}
|
|
15857
15938
|
const meta = {
|
|
15858
15939
|
timeoutMs: StreamBroker.RTP_ACTIVITY_TIMEOUT_MS,
|
|
15859
15940
|
...this.sourceMetaForLog()
|
|
@@ -13084,6 +13084,15 @@ var StreamBroker = class StreamBroker {
|
|
|
13084
13084
|
* H.264 video is 30fps → 80pps minimum on a working stream) while a
|
|
13085
13085
|
* real stall is detected before Chrome's ~15s ICE-disconnect timer
|
|
13086
13086
|
* has any chance to fire. */
|
|
13087
|
+
/** How many times a resume re-asks the registry before it stops asking. */
|
|
13088
|
+
static RESUME_RETRY_MAX = 5;
|
|
13089
|
+
/** Spacing of those asks — long enough for a catalog reconcile to land. */
|
|
13090
|
+
static RESUME_RETRY_DELAY_MS = 3e3;
|
|
13091
|
+
resumeRetryTimer;
|
|
13092
|
+
resumeRetryAttempts = 0;
|
|
13093
|
+
resumeRetryExhausted = false;
|
|
13094
|
+
/** One line per suspension when packets arrive with no watchdog armed. */
|
|
13095
|
+
suspendedActivityNoted = false;
|
|
13087
13096
|
static RTP_ACTIVITY_TIMEOUT_MS = 8e3;
|
|
13088
13097
|
/**
|
|
13089
13098
|
* How often the single sweep timer checks {@link lastRtpActivityAt}.
|
|
@@ -13594,6 +13603,54 @@ var StreamBroker = class StreamBroker {
|
|
|
13594
13603
|
this.scheduleReconnect();
|
|
13595
13604
|
}
|
|
13596
13605
|
/**
|
|
13606
|
+
* Ask again for a source the registry did not have yet — bounded.
|
|
13607
|
+
*
|
|
13608
|
+
* Demand exists and nothing can be dialled, so waiting for the NEXT demand
|
|
13609
|
+
* edge is waiting for something that may never come: the consumer is already
|
|
13610
|
+
* attached. The retry is what turns "nothing happened" back into either a
|
|
13611
|
+
* stream or a stated failure, and the bound is what stops a camera that
|
|
13612
|
+
* genuinely publishes nothing from spinning for the life of the process.
|
|
13613
|
+
*/
|
|
13614
|
+
scheduleResumeRetry() {
|
|
13615
|
+
if (this.resumeRetryTimer !== void 0) return;
|
|
13616
|
+
if (this.resumeRetryAttempts >= StreamBroker.RESUME_RETRY_MAX) {
|
|
13617
|
+
if (!this.resumeRetryExhausted) {
|
|
13618
|
+
this.resumeRetryExhausted = true;
|
|
13619
|
+
this.logger?.warn("demand is waiting and this broker still has no source — giving up until something changes", { meta: {
|
|
13620
|
+
brokerId: this.deviceId,
|
|
13621
|
+
attempts: this.resumeRetryAttempts,
|
|
13622
|
+
...this.numericDeviceId === null ? {} : { deviceId: this.numericDeviceId }
|
|
13623
|
+
} });
|
|
13624
|
+
}
|
|
13625
|
+
return;
|
|
13626
|
+
}
|
|
13627
|
+
this.resumeRetryAttempts += 1;
|
|
13628
|
+
this.logger?.warn("demand detected but no source could be resolved — retrying", {
|
|
13629
|
+
...this.numericDeviceId === null ? {} : { tags: { deviceId: this.numericDeviceId } },
|
|
13630
|
+
meta: {
|
|
13631
|
+
brokerId: this.deviceId,
|
|
13632
|
+
attempt: this.resumeRetryAttempts,
|
|
13633
|
+
ofMax: StreamBroker.RESUME_RETRY_MAX
|
|
13634
|
+
}
|
|
13635
|
+
});
|
|
13636
|
+
this.resumeRetryTimer = setTimeout(() => {
|
|
13637
|
+
this.resumeRetryTimer = void 0;
|
|
13638
|
+
if (this.manualStop || this.stopping || !this._suspended) return;
|
|
13639
|
+
if (!this.hasLiveIntent()) return;
|
|
13640
|
+
this.checkDemand();
|
|
13641
|
+
}, StreamBroker.RESUME_RETRY_DELAY_MS);
|
|
13642
|
+
this.resumeRetryTimer.unref?.();
|
|
13643
|
+
}
|
|
13644
|
+
/** A resume that SUCCEEDED clears the episode, counter included. */
|
|
13645
|
+
cancelResumeRetry() {
|
|
13646
|
+
if (this.resumeRetryTimer !== void 0) {
|
|
13647
|
+
clearTimeout(this.resumeRetryTimer);
|
|
13648
|
+
this.resumeRetryTimer = void 0;
|
|
13649
|
+
}
|
|
13650
|
+
this.resumeRetryAttempts = 0;
|
|
13651
|
+
this.resumeRetryExhausted = false;
|
|
13652
|
+
}
|
|
13653
|
+
/**
|
|
13597
13654
|
* Resolve the source to use for the next dial attempt. Prefers the
|
|
13598
13655
|
* manager-supplied resolver — re-derives from the cam-stream
|
|
13599
13656
|
* registry, so a re-publish that updated the URL is honoured on the
|
|
@@ -14102,6 +14159,7 @@ var StreamBroker = class StreamBroker {
|
|
|
14102
14159
|
if (this._suspended) {
|
|
14103
14160
|
const fresh = this.resolveCurrentSource();
|
|
14104
14161
|
if (fresh) {
|
|
14162
|
+
this.cancelResumeRetry();
|
|
14105
14163
|
this._suspended = false;
|
|
14106
14164
|
this.logger?.info("demand detected — resuming stream");
|
|
14107
14165
|
this.start(fresh).catch((err) => {
|
|
@@ -14109,7 +14167,7 @@ var StreamBroker = class StreamBroker {
|
|
|
14109
14167
|
this._suspended = true;
|
|
14110
14168
|
this._status = "idle";
|
|
14111
14169
|
});
|
|
14112
|
-
}
|
|
14170
|
+
} else this.scheduleResumeRetry();
|
|
14113
14171
|
}
|
|
14114
14172
|
} else if (!this._suspended) {
|
|
14115
14173
|
if (!this.suspendTimer) this.suspendTimer = setTimeout(() => {
|
|
@@ -15809,7 +15867,20 @@ var StreamBroker = class StreamBroker {
|
|
|
15809
15867
|
* operations on the highest-frequency path in the busiest process.
|
|
15810
15868
|
*/
|
|
15811
15869
|
kickRtpActivityWatchdog() {
|
|
15812
|
-
if (this.manualStop || this.stopping || this._suspended)
|
|
15870
|
+
if (this.manualStop || this.stopping || this._suspended) {
|
|
15871
|
+
if (this._suspended && !this.suspendedActivityNoted) {
|
|
15872
|
+
this.suspendedActivityNoted = true;
|
|
15873
|
+
this.logger?.warn("source RTP is arriving while this broker is suspended — the stall watchdog is NOT armed for it", {
|
|
15874
|
+
...this.numericDeviceId === null ? {} : { tags: { deviceId: this.numericDeviceId } },
|
|
15875
|
+
meta: {
|
|
15876
|
+
brokerId: this.deviceId,
|
|
15877
|
+
status: this._status
|
|
15878
|
+
}
|
|
15879
|
+
});
|
|
15880
|
+
}
|
|
15881
|
+
return;
|
|
15882
|
+
}
|
|
15883
|
+
this.suspendedActivityNoted = false;
|
|
15813
15884
|
this.lastRtpActivityAt = Date.now();
|
|
15814
15885
|
if (this.rtpActivitySweep !== void 0) return;
|
|
15815
15886
|
this.rtpActivitySweep = setInterval(() => {
|
|
@@ -15849,7 +15920,17 @@ var StreamBroker = class StreamBroker {
|
|
|
15849
15920
|
*/
|
|
15850
15921
|
onRtpActivityWatchdogExpired() {
|
|
15851
15922
|
this.rtpActivityWatchdogFiredCount++;
|
|
15852
|
-
if (this.manualStop || this.stopping || this._suspended)
|
|
15923
|
+
if (this.manualStop || this.stopping || this._suspended) {
|
|
15924
|
+
if (this._suspended) this.logger?.warn("source RTP went silent on a suspended broker — the watchdog is disarmed and nothing will reconnect it", {
|
|
15925
|
+
...this.numericDeviceId === null ? {} : { tags: { deviceId: this.numericDeviceId } },
|
|
15926
|
+
meta: {
|
|
15927
|
+
brokerId: this.deviceId,
|
|
15928
|
+
timeoutMs: StreamBroker.RTP_ACTIVITY_TIMEOUT_MS,
|
|
15929
|
+
firedCount: this.rtpActivityWatchdogFiredCount
|
|
15930
|
+
}
|
|
15931
|
+
});
|
|
15932
|
+
return;
|
|
15933
|
+
}
|
|
15853
15934
|
const meta = {
|
|
15854
15935
|
timeoutMs: StreamBroker.RTP_ACTIVITY_TIMEOUT_MS,
|
|
15855
15936
|
...this.sourceMetaForLog()
|
|
@@ -30,7 +30,7 @@ async function d(e) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
async function f() {
|
|
33
|
-
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-
|
|
33
|
+
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DZlxPoTV.mjs")).catch((e) => {
|
|
34
34
|
throw l = void 0, e;
|
|
35
35
|
}), l;
|
|
36
36
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-pipeline",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.270",
|
|
4
4
|
"description": "Pipeline bundle — runner, detection, motion, audio + stream broker. Multi-entry npm package shipping pipeline addons under a single bundle.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|