@camstack/addon-pipeline 1.2.262 → 1.2.264
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/recorder/index.js +76 -2
- package/dist/recorder/index.mjs +76 -2
- package/package.json +1 -1
package/dist/recorder/index.js
CHANGED
|
@@ -11928,6 +11928,31 @@ function pendingMovesSignature(moves) {
|
|
|
11928
11928
|
return moves.map((m) => `${String(m.deviceId)}:${m.profile}>${m.plannedFor}`).join(",");
|
|
11929
11929
|
}
|
|
11930
11930
|
//#endregion
|
|
11931
|
+
//#region src/recorder/addon/hour-adoption-catchup.ts
|
|
11932
|
+
/**
|
|
11933
|
+
* @returns true when the run stopped with work still to do — the caller should
|
|
11934
|
+
* come back SOON rather than at the next daily tick. A repair that knows it
|
|
11935
|
+
* is unfinished and waits a day is how an archive stays short for months.
|
|
11936
|
+
*/
|
|
11937
|
+
async function runAdoptionCatchUp(deps) {
|
|
11938
|
+
const startedAt = deps.now();
|
|
11939
|
+
const spent = () => deps.now() - startedAt;
|
|
11940
|
+
for (const locationId of deps.locationIds) for (;;) {
|
|
11941
|
+
if (spent() >= deps.budgetMs) return true;
|
|
11942
|
+
let report;
|
|
11943
|
+
try {
|
|
11944
|
+
report = await deps.sweep({ locationId });
|
|
11945
|
+
} catch (error) {
|
|
11946
|
+
deps.onError?.(locationId, error);
|
|
11947
|
+
break;
|
|
11948
|
+
}
|
|
11949
|
+
if (!report.bounded) break;
|
|
11950
|
+
if (spent() >= deps.budgetMs) return true;
|
|
11951
|
+
await deps.pace();
|
|
11952
|
+
}
|
|
11953
|
+
return false;
|
|
11954
|
+
}
|
|
11955
|
+
//#endregion
|
|
11931
11956
|
//#region src/recorder/addon/hour-adoption-sweep.ts
|
|
11932
11957
|
var HOUR_MS$1 = 36e5;
|
|
11933
11958
|
/** The profile trees a camera directory is allowed to have. Everything else
|
|
@@ -12196,12 +12221,16 @@ function startPeriodicPass(deps) {
|
|
|
12196
12221
|
};
|
|
12197
12222
|
const timer = setInterval(fire, deps.intervalMs);
|
|
12198
12223
|
timer.unref?.();
|
|
12224
|
+
const firstRun = deps.firstRunDelayMs === void 0 ? null : setTimeout(fire, deps.firstRunDelayMs);
|
|
12225
|
+
firstRun?.unref?.();
|
|
12199
12226
|
return {
|
|
12200
12227
|
stop() {
|
|
12201
12228
|
stopped = true;
|
|
12202
12229
|
clearInterval(timer);
|
|
12230
|
+
if (firstRun !== null) clearTimeout(firstRun);
|
|
12203
12231
|
},
|
|
12204
|
-
isRunning: () => startedAt !== null
|
|
12232
|
+
isRunning: () => startedAt !== null,
|
|
12233
|
+
fireNow: fire
|
|
12205
12234
|
};
|
|
12206
12235
|
}
|
|
12207
12236
|
//#endregion
|
|
@@ -17793,6 +17822,29 @@ var LEDGER_WALK_PAUSE_MS = 100;
|
|
|
17793
17822
|
* are already contending for that array.
|
|
17794
17823
|
*/
|
|
17795
17824
|
var HOUR_ADOPTION_INTERVAL_MS = 1440 * 6e4;
|
|
17825
|
+
/**
|
|
17826
|
+
* How long after boot the first adoption pass runs.
|
|
17827
|
+
*
|
|
17828
|
+
* Long enough that it is not competing with everything else a starting recorder
|
|
17829
|
+
* does (locations resolving, writers attaching, the ledger warming), short
|
|
17830
|
+
* enough that a hub restarted twice in an evening still repairs its archive.
|
|
17831
|
+
*/
|
|
17832
|
+
var HOUR_ADOPTION_FIRST_RUN_DELAY_MS = 3 * 6e4;
|
|
17833
|
+
/**
|
|
17834
|
+
* How long one adoption run may keep sweeping bounded locations.
|
|
17835
|
+
*
|
|
17836
|
+
* Long enough to make real progress on a damaged archive (the first pass here
|
|
17837
|
+
* moved ~29 k segments in about twenty seconds of listings), short enough that
|
|
17838
|
+
* the array is not being walked continuously — every listing is a `readdir` on
|
|
17839
|
+
* a spinning disk shared with live writers.
|
|
17840
|
+
*/
|
|
17841
|
+
var HOUR_ADOPTION_CATCHUP_BUDGET_MS = 10 * 6e4;
|
|
17842
|
+
/**
|
|
17843
|
+
* How long the recorder waits before resuming an adoption run that stopped on
|
|
17844
|
+
* its budget. Enough of a gap that the array is not walked back-to-back;
|
|
17845
|
+
* nothing like a day.
|
|
17846
|
+
*/
|
|
17847
|
+
var HOUR_ADOPTION_RESUME_MS = 5 * 6e4;
|
|
17796
17848
|
/** An adoption pass longer than this is reported with its duration. Bounded
|
|
17797
17849
|
* work (512 hour listings, paced) — minutes is normal, an hour is not. */
|
|
17798
17850
|
var HOUR_ADOPTION_SLOW_AFTER_MS = 10 * 6e4;
|
|
@@ -18021,6 +18073,7 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
|
|
|
18021
18073
|
* the storage record no longer has. Armed in `onHubReachable`. */
|
|
18022
18074
|
ghostLocationPass = null;
|
|
18023
18075
|
hourAdoptionPass = null;
|
|
18076
|
+
hourAdoptionResume;
|
|
18024
18077
|
/** Reversible migration pause lease; never reflected in RecordingConfig. */
|
|
18025
18078
|
storageMigrationLeaseId = null;
|
|
18026
18079
|
/**
|
|
@@ -18920,9 +18973,30 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
|
|
|
18920
18973
|
this.hourAdoptionPass = startPeriodicPass({
|
|
18921
18974
|
name: "hour-adoption",
|
|
18922
18975
|
intervalMs: HOUR_ADOPTION_INTERVAL_MS,
|
|
18976
|
+
firstRunDelayMs: HOUR_ADOPTION_FIRST_RUN_DELAY_MS,
|
|
18923
18977
|
slowAfterMs: HOUR_ADOPTION_SLOW_AFTER_MS,
|
|
18924
18978
|
run: async () => {
|
|
18925
|
-
|
|
18979
|
+
if (await runAdoptionCatchUp({
|
|
18980
|
+
locationIds: this.resolvedLocations.map((location) => location.id),
|
|
18981
|
+
sweep: (input) => adopter.sweep(input),
|
|
18982
|
+
budgetMs: HOUR_ADOPTION_CATCHUP_BUDGET_MS,
|
|
18983
|
+
now: () => Date.now(),
|
|
18984
|
+
pace: () => require_dist.sleep(LEDGER_WALK_PAUSE_MS),
|
|
18985
|
+
onError: (locationId, error) => {
|
|
18986
|
+
this.ctx.logger.warn("recorder: hour adoption could not sweep a location", { meta: {
|
|
18987
|
+
locationId,
|
|
18988
|
+
error: require_dist.errMsg(error)
|
|
18989
|
+
} });
|
|
18990
|
+
}
|
|
18991
|
+
})) {
|
|
18992
|
+
this.ctx.logger.info("recorder: hour adoption stopped on its budget with work left — resuming shortly", { meta: { resumeInMs: HOUR_ADOPTION_RESUME_MS } });
|
|
18993
|
+
this.hourAdoptionResume?.unref?.();
|
|
18994
|
+
clearTimeout(this.hourAdoptionResume);
|
|
18995
|
+
this.hourAdoptionResume = setTimeout(() => {
|
|
18996
|
+
this.hourAdoptionPass?.fireNow();
|
|
18997
|
+
}, HOUR_ADOPTION_RESUME_MS);
|
|
18998
|
+
this.hourAdoptionResume.unref?.();
|
|
18999
|
+
}
|
|
18926
19000
|
},
|
|
18927
19001
|
logger: this.ctx.logger
|
|
18928
19002
|
});
|
package/dist/recorder/index.mjs
CHANGED
|
@@ -11921,6 +11921,31 @@ function pendingMovesSignature(moves) {
|
|
|
11921
11921
|
return moves.map((m) => `${String(m.deviceId)}:${m.profile}>${m.plannedFor}`).join(",");
|
|
11922
11922
|
}
|
|
11923
11923
|
//#endregion
|
|
11924
|
+
//#region src/recorder/addon/hour-adoption-catchup.ts
|
|
11925
|
+
/**
|
|
11926
|
+
* @returns true when the run stopped with work still to do — the caller should
|
|
11927
|
+
* come back SOON rather than at the next daily tick. A repair that knows it
|
|
11928
|
+
* is unfinished and waits a day is how an archive stays short for months.
|
|
11929
|
+
*/
|
|
11930
|
+
async function runAdoptionCatchUp(deps) {
|
|
11931
|
+
const startedAt = deps.now();
|
|
11932
|
+
const spent = () => deps.now() - startedAt;
|
|
11933
|
+
for (const locationId of deps.locationIds) for (;;) {
|
|
11934
|
+
if (spent() >= deps.budgetMs) return true;
|
|
11935
|
+
let report;
|
|
11936
|
+
try {
|
|
11937
|
+
report = await deps.sweep({ locationId });
|
|
11938
|
+
} catch (error) {
|
|
11939
|
+
deps.onError?.(locationId, error);
|
|
11940
|
+
break;
|
|
11941
|
+
}
|
|
11942
|
+
if (!report.bounded) break;
|
|
11943
|
+
if (spent() >= deps.budgetMs) return true;
|
|
11944
|
+
await deps.pace();
|
|
11945
|
+
}
|
|
11946
|
+
return false;
|
|
11947
|
+
}
|
|
11948
|
+
//#endregion
|
|
11924
11949
|
//#region src/recorder/addon/hour-adoption-sweep.ts
|
|
11925
11950
|
var HOUR_MS$1 = 36e5;
|
|
11926
11951
|
/** The profile trees a camera directory is allowed to have. Everything else
|
|
@@ -12189,12 +12214,16 @@ function startPeriodicPass(deps) {
|
|
|
12189
12214
|
};
|
|
12190
12215
|
const timer = setInterval(fire, deps.intervalMs);
|
|
12191
12216
|
timer.unref?.();
|
|
12217
|
+
const firstRun = deps.firstRunDelayMs === void 0 ? null : setTimeout(fire, deps.firstRunDelayMs);
|
|
12218
|
+
firstRun?.unref?.();
|
|
12192
12219
|
return {
|
|
12193
12220
|
stop() {
|
|
12194
12221
|
stopped = true;
|
|
12195
12222
|
clearInterval(timer);
|
|
12223
|
+
if (firstRun !== null) clearTimeout(firstRun);
|
|
12196
12224
|
},
|
|
12197
|
-
isRunning: () => startedAt !== null
|
|
12225
|
+
isRunning: () => startedAt !== null,
|
|
12226
|
+
fireNow: fire
|
|
12198
12227
|
};
|
|
12199
12228
|
}
|
|
12200
12229
|
//#endregion
|
|
@@ -17786,6 +17815,29 @@ var LEDGER_WALK_PAUSE_MS = 100;
|
|
|
17786
17815
|
* are already contending for that array.
|
|
17787
17816
|
*/
|
|
17788
17817
|
var HOUR_ADOPTION_INTERVAL_MS = 1440 * 6e4;
|
|
17818
|
+
/**
|
|
17819
|
+
* How long after boot the first adoption pass runs.
|
|
17820
|
+
*
|
|
17821
|
+
* Long enough that it is not competing with everything else a starting recorder
|
|
17822
|
+
* does (locations resolving, writers attaching, the ledger warming), short
|
|
17823
|
+
* enough that a hub restarted twice in an evening still repairs its archive.
|
|
17824
|
+
*/
|
|
17825
|
+
var HOUR_ADOPTION_FIRST_RUN_DELAY_MS = 3 * 6e4;
|
|
17826
|
+
/**
|
|
17827
|
+
* How long one adoption run may keep sweeping bounded locations.
|
|
17828
|
+
*
|
|
17829
|
+
* Long enough to make real progress on a damaged archive (the first pass here
|
|
17830
|
+
* moved ~29 k segments in about twenty seconds of listings), short enough that
|
|
17831
|
+
* the array is not being walked continuously — every listing is a `readdir` on
|
|
17832
|
+
* a spinning disk shared with live writers.
|
|
17833
|
+
*/
|
|
17834
|
+
var HOUR_ADOPTION_CATCHUP_BUDGET_MS = 10 * 6e4;
|
|
17835
|
+
/**
|
|
17836
|
+
* How long the recorder waits before resuming an adoption run that stopped on
|
|
17837
|
+
* its budget. Enough of a gap that the array is not walked back-to-back;
|
|
17838
|
+
* nothing like a day.
|
|
17839
|
+
*/
|
|
17840
|
+
var HOUR_ADOPTION_RESUME_MS = 5 * 6e4;
|
|
17789
17841
|
/** An adoption pass longer than this is reported with its duration. Bounded
|
|
17790
17842
|
* work (512 hour listings, paced) — minutes is normal, an hour is not. */
|
|
17791
17843
|
var HOUR_ADOPTION_SLOW_AFTER_MS = 10 * 6e4;
|
|
@@ -18014,6 +18066,7 @@ var RecorderV2Addon = class extends BaseAddon {
|
|
|
18014
18066
|
* the storage record no longer has. Armed in `onHubReachable`. */
|
|
18015
18067
|
ghostLocationPass = null;
|
|
18016
18068
|
hourAdoptionPass = null;
|
|
18069
|
+
hourAdoptionResume;
|
|
18017
18070
|
/** Reversible migration pause lease; never reflected in RecordingConfig. */
|
|
18018
18071
|
storageMigrationLeaseId = null;
|
|
18019
18072
|
/**
|
|
@@ -18913,9 +18966,30 @@ var RecorderV2Addon = class extends BaseAddon {
|
|
|
18913
18966
|
this.hourAdoptionPass = startPeriodicPass({
|
|
18914
18967
|
name: "hour-adoption",
|
|
18915
18968
|
intervalMs: HOUR_ADOPTION_INTERVAL_MS,
|
|
18969
|
+
firstRunDelayMs: HOUR_ADOPTION_FIRST_RUN_DELAY_MS,
|
|
18916
18970
|
slowAfterMs: HOUR_ADOPTION_SLOW_AFTER_MS,
|
|
18917
18971
|
run: async () => {
|
|
18918
|
-
|
|
18972
|
+
if (await runAdoptionCatchUp({
|
|
18973
|
+
locationIds: this.resolvedLocations.map((location) => location.id),
|
|
18974
|
+
sweep: (input) => adopter.sweep(input),
|
|
18975
|
+
budgetMs: HOUR_ADOPTION_CATCHUP_BUDGET_MS,
|
|
18976
|
+
now: () => Date.now(),
|
|
18977
|
+
pace: () => sleep$1(LEDGER_WALK_PAUSE_MS),
|
|
18978
|
+
onError: (locationId, error) => {
|
|
18979
|
+
this.ctx.logger.warn("recorder: hour adoption could not sweep a location", { meta: {
|
|
18980
|
+
locationId,
|
|
18981
|
+
error: errMsg(error)
|
|
18982
|
+
} });
|
|
18983
|
+
}
|
|
18984
|
+
})) {
|
|
18985
|
+
this.ctx.logger.info("recorder: hour adoption stopped on its budget with work left — resuming shortly", { meta: { resumeInMs: HOUR_ADOPTION_RESUME_MS } });
|
|
18986
|
+
this.hourAdoptionResume?.unref?.();
|
|
18987
|
+
clearTimeout(this.hourAdoptionResume);
|
|
18988
|
+
this.hourAdoptionResume = setTimeout(() => {
|
|
18989
|
+
this.hourAdoptionPass?.fireNow();
|
|
18990
|
+
}, HOUR_ADOPTION_RESUME_MS);
|
|
18991
|
+
this.hourAdoptionResume.unref?.();
|
|
18992
|
+
}
|
|
18919
18993
|
},
|
|
18920
18994
|
logger: this.ctx.logger
|
|
18921
18995
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-pipeline",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.264",
|
|
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",
|