@camstack/system 1.2.414 → 1.2.416
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/addon-runner.js +1 -1
- package/dist/addon-runner.mjs +1 -1
- package/dist/addon-utils.js +1 -1
- package/dist/addon-utils.mjs +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
- package/dist/builtins/calendars/calendars.addon.js +1 -1
- package/dist/builtins/calendars/calendars.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/composer/composer.addon.js +2 -2
- package/dist/builtins/composer/composer.addon.mjs +2 -2
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
- package/dist/builtins/device-manager/device-manager.addon.js +2 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/keychain/index.js +3 -3
- package/dist/builtins/keychain/index.mjs +3 -3
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +9 -8
- package/dist/builtins/local-auth/local-auth.addon.mjs +4 -3
- package/dist/builtins/local-network/hub-mdns-ciao.d.ts +7 -0
- package/dist/builtins/local-network/hub-mdns.d.ts +58 -0
- package/dist/builtins/local-network/local-network.addon.d.ts +11 -0
- package/dist/builtins/local-network/local-network.addon.js +194 -3
- package/dist/builtins/local-network/local-network.addon.mjs +195 -3
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
- package/dist/builtins/storage-orchestrator/storage-location-band-monitor.d.ts +43 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +6 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +112 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +112 -1
- package/dist/builtins/system-config/system-config.addon.js +80 -785
- package/dist/builtins/system-config/system-config.addon.mjs +52 -757
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{child-cap-dispatch-fnYkJDjG.js → child-cap-dispatch-B87B0FrC.js} +1 -1
- package/dist/{child-cap-dispatch-CpYnlLNt.mjs → child-cap-dispatch-CmfT-OR2.mjs} +1 -1
- package/dist/{composition-sources-BX6Caql_.js → composition-sources-DBcOVpGn.js} +1 -1
- package/dist/{composition-sources-QndhKNb5.mjs → composition-sources-DEZqZLPT.mjs} +1 -1
- package/dist/{constants-vMEWqCqG.mjs → constants-BSBtmzm3.mjs} +1 -1
- package/dist/{constants-CMXQ1QIC.js → constants-C4jZO_qO.js} +1 -1
- package/dist/{dist-ItJ3qAAA.mjs → dist-DwE9yHdk.mjs} +67 -3
- package/dist/{dist-BcnmH70Z.js → dist-DxiDI8hZ.js} +78 -2
- package/dist/{event-loop-stall-monitor-DoFaUgFf.js → event-loop-stall-monitor-E2hFvhDg.js} +1 -1
- package/dist/{event-loop-stall-monitor-CogzcENb.mjs → event-loop-stall-monitor-LBZskC1S.mjs} +1 -1
- package/dist/index.js +7 -7
- package/dist/index.mjs +7 -7
- package/dist/{jwt-signing-key-CST1LdM6.js → jwt-signing-key-CsC-FxSm.js} +1 -1
- package/dist/{jwt-signing-key-CpMSrZuI.mjs → jwt-signing-key-DLbjTIuA.mjs} +1 -1
- package/dist/lib-B_R6sPC3.mjs +7106 -0
- package/dist/lib-DOJ5yyWA.js +7110 -0
- package/dist/{ms-DlIWNkkk.mjs → ms-CgH2OFlD.mjs} +2 -42
- package/dist/{ms-t68_FaqE.js → ms-LB3giGoU.js} +1 -48
- package/dist/{restore-archive-pSlTKRgU.js → restore-archive-BtKjaVua.js} +1 -1
- package/dist/{restore-archive-8F_M_wW0.mjs → restore-archive-CImzbuRo.mjs} +1 -1
- package/dist/{retired-settings-keys-D3E47aR_.js → retired-settings-keys-Cl1tnkmq.js} +1 -1
- package/dist/{retired-settings-keys-CbkMnFXg.mjs → retired-settings-keys-D1WsCdUY.mjs} +1 -1
- package/dist/safe-buffer-B1OjL1I9.mjs +42 -0
- package/dist/safe-buffer-D3aoa-7X.js +46 -0
- package/dist/src-CnAqG6EF.js +714 -0
- package/dist/src-hG4grMU4.mjs +709 -0
- package/dist/{tls-BWpwU-d5.js → tls-C0TRPfqc.js} +1 -1
- package/dist/{tls-C2NT-Orr.mjs → tls-D-2dPY-5.mjs} +1 -1
- package/dist/{x509.es-Xf3K_brW.mjs → x509.es-CAjSsrkk.mjs} +643 -2
- package/dist/{x509.es-BhTzcFhZ.js → x509.es-Dzl0BbmG.js} +653 -0
- package/package.json +2 -1
|
@@ -4,6 +4,7 @@ interface StorageOrchestratorConfig extends Record<string, unknown> {}
|
|
|
4
4
|
export declare class StorageOrchestratorAddon extends BaseAddon<StorageOrchestratorConfig> {
|
|
5
5
|
private service;
|
|
6
6
|
private pressureManager;
|
|
7
|
+
private readonly locationBandMonitor;
|
|
7
8
|
/**
|
|
8
9
|
* How much of each location CamStack itself holds (D388).
|
|
9
10
|
*
|
|
@@ -100,6 +101,11 @@ export declare class StorageOrchestratorAddon extends BaseAddon<StorageOrchestra
|
|
|
100
101
|
/** Single-flighted pressure sweep — never overlaps a slow eviction round. */
|
|
101
102
|
private runPressureSweep;
|
|
102
103
|
/**
|
|
104
|
+
* Sample free space for every managed location and emit NC band edges.
|
|
105
|
+
* A failed capacity read stays `null` (critical) — never folded to 0 (D393).
|
|
106
|
+
*/
|
|
107
|
+
private emitLocationBandEvents;
|
|
108
|
+
/**
|
|
103
109
|
* locationId → resolved `minFreePercent`. The policy is intrinsic to the
|
|
104
110
|
* location's provider (`shouldSaveDiskSpace` gates the guard, `minFreePercent`
|
|
105
111
|
* is the default), overridable per-location via `config.minFreePercent`.
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-DxiDI8hZ.js");
|
|
7
7
|
const require_hub_cap_forward = require("../../hub-cap-forward-W8oEm4ME.js");
|
|
8
8
|
let zod = require("zod");
|
|
9
9
|
let node_crypto = require("node:crypto");
|
|
@@ -3342,6 +3342,64 @@ var StoragePressureManager = class {
|
|
|
3342
3342
|
}
|
|
3343
3343
|
};
|
|
3344
3344
|
//#endregion
|
|
3345
|
+
//#region src/builtins/storage-orchestrator/storage-location-band-monitor.ts
|
|
3346
|
+
var DEFAULT_STORAGE_LOCATION_BAND_CONFIG = {
|
|
3347
|
+
lowPercent: 15,
|
|
3348
|
+
criticalPercent: 5
|
|
3349
|
+
};
|
|
3350
|
+
function bandOf(freePercent, config) {
|
|
3351
|
+
if (freePercent === null) return {
|
|
3352
|
+
band: "critical",
|
|
3353
|
+
reason: "capacity-unreadable"
|
|
3354
|
+
};
|
|
3355
|
+
if (freePercent <= config.criticalPercent) return {
|
|
3356
|
+
band: "critical",
|
|
3357
|
+
reason: "free-below-critical"
|
|
3358
|
+
};
|
|
3359
|
+
if (freePercent <= config.lowPercent) return {
|
|
3360
|
+
band: "low",
|
|
3361
|
+
reason: "free-below-warn"
|
|
3362
|
+
};
|
|
3363
|
+
return {
|
|
3364
|
+
band: "ok",
|
|
3365
|
+
reason: "free-ok"
|
|
3366
|
+
};
|
|
3367
|
+
}
|
|
3368
|
+
var StorageLocationBandMonitor = class {
|
|
3369
|
+
config;
|
|
3370
|
+
band = /* @__PURE__ */ new Map();
|
|
3371
|
+
constructor(config = DEFAULT_STORAGE_LOCATION_BAND_CONFIG) {
|
|
3372
|
+
this.config = config;
|
|
3373
|
+
}
|
|
3374
|
+
/**
|
|
3375
|
+
* Observe one sweep of managed locations. Locations missing from `samples`
|
|
3376
|
+
* drop their episode without emitting `ok` (disabled / removed).
|
|
3377
|
+
*/
|
|
3378
|
+
observe(samples) {
|
|
3379
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3380
|
+
const out = [];
|
|
3381
|
+
for (const sample of samples) {
|
|
3382
|
+
seen.add(sample.locationId);
|
|
3383
|
+
const { band, reason } = bandOf(sample.freePercent, this.config);
|
|
3384
|
+
const previous = this.band.get(sample.locationId) ?? null;
|
|
3385
|
+
if (previous === band) continue;
|
|
3386
|
+
this.band.set(sample.locationId, band);
|
|
3387
|
+
if (previous === null && band === "ok") continue;
|
|
3388
|
+
out.push({
|
|
3389
|
+
locationId: sample.locationId,
|
|
3390
|
+
...sample.nodeId !== void 0 ? { nodeId: sample.nodeId } : {},
|
|
3391
|
+
...sample.locationName !== void 0 ? { locationName: sample.locationName } : {},
|
|
3392
|
+
band,
|
|
3393
|
+
freePercent: sample.freePercent,
|
|
3394
|
+
reason,
|
|
3395
|
+
previous
|
|
3396
|
+
});
|
|
3397
|
+
}
|
|
3398
|
+
for (const id of [...this.band.keys()]) if (!seen.has(id)) this.band.delete(id);
|
|
3399
|
+
return out;
|
|
3400
|
+
}
|
|
3401
|
+
};
|
|
3402
|
+
//#endregion
|
|
3345
3403
|
//#region src/builtins/storage-orchestrator/storage-orchestrator.addon.ts
|
|
3346
3404
|
/**
|
|
3347
3405
|
* `storage-orchestrator` builtin — singleton owner of the consumer-
|
|
@@ -3386,6 +3444,7 @@ var CAP_PROVIDER_REGISTERED_CATEGORY = "capability:provider-registered";
|
|
|
3386
3444
|
var StorageOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
3387
3445
|
service = null;
|
|
3388
3446
|
pressureManager = null;
|
|
3447
|
+
locationBandMonitor = new StorageLocationBandMonitor();
|
|
3389
3448
|
/**
|
|
3390
3449
|
* How much of each location CamStack itself holds (D388).
|
|
3391
3450
|
*
|
|
@@ -3888,6 +3947,7 @@ var StorageOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
|
3888
3947
|
this.pressureSweepInFlight = true;
|
|
3889
3948
|
try {
|
|
3890
3949
|
await this.pressureManager.sweep();
|
|
3950
|
+
await this.emitLocationBandEvents();
|
|
3891
3951
|
} catch (err) {
|
|
3892
3952
|
this.ctxIfReady?.logger.warn("storage pressure sweep failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
3893
3953
|
} finally {
|
|
@@ -3895,6 +3955,57 @@ var StorageOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
|
3895
3955
|
}
|
|
3896
3956
|
}
|
|
3897
3957
|
/**
|
|
3958
|
+
* Sample free space for every managed location and emit NC band edges.
|
|
3959
|
+
* A failed capacity read stays `null` (critical) — never folded to 0 (D393).
|
|
3960
|
+
*/
|
|
3961
|
+
async emitLocationBandEvents() {
|
|
3962
|
+
const svc = this.service;
|
|
3963
|
+
const ctx = this.ctxIfReady;
|
|
3964
|
+
if (!svc || !ctx) return;
|
|
3965
|
+
const thresholds = await this.resolveLocationThresholds();
|
|
3966
|
+
const byId = new Map(svc.listLocations().map((loc) => [loc.id, loc]));
|
|
3967
|
+
const samples = await Promise.all([...thresholds.keys()].map(async (locationId) => {
|
|
3968
|
+
const loc = byId.get(locationId);
|
|
3969
|
+
if (loc === void 0 || !require_dist.mayReadLocation(loc)) return {
|
|
3970
|
+
locationId,
|
|
3971
|
+
freePercent: null
|
|
3972
|
+
};
|
|
3973
|
+
const capacity = await this.volumeCapacityOf(locationId).catch(() => null);
|
|
3974
|
+
const freePercent = capacity === null ? null : freePercentOf(capacity);
|
|
3975
|
+
return {
|
|
3976
|
+
locationId,
|
|
3977
|
+
nodeId: loc.nodeId,
|
|
3978
|
+
locationName: loc.displayName,
|
|
3979
|
+
freePercent
|
|
3980
|
+
};
|
|
3981
|
+
}));
|
|
3982
|
+
for (const edge of this.locationBandMonitor.observe(samples)) {
|
|
3983
|
+
const category = edge.band === "low" ? require_dist.EventCategory.StorageLocationLow : edge.band === "critical" ? require_dist.EventCategory.StorageLocationCritical : require_dist.EventCategory.StorageLocationOk;
|
|
3984
|
+
ctx.logger.info("storage: location band changed", { meta: {
|
|
3985
|
+
locationId: edge.locationId,
|
|
3986
|
+
band: edge.band,
|
|
3987
|
+
freePercent: edge.freePercent,
|
|
3988
|
+
reason: edge.reason
|
|
3989
|
+
} });
|
|
3990
|
+
ctx.eventBus.emit({
|
|
3991
|
+
id: (0, node_crypto.randomUUID)(),
|
|
3992
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
3993
|
+
source: {
|
|
3994
|
+
type: "addon",
|
|
3995
|
+
id: this.ctx.id
|
|
3996
|
+
},
|
|
3997
|
+
category,
|
|
3998
|
+
data: {
|
|
3999
|
+
locationId: edge.locationId,
|
|
4000
|
+
...edge.nodeId !== void 0 ? { nodeId: edge.nodeId } : {},
|
|
4001
|
+
...edge.locationName !== void 0 ? { locationName: edge.locationName } : {},
|
|
4002
|
+
freePercent: edge.freePercent,
|
|
4003
|
+
reason: edge.reason
|
|
4004
|
+
}
|
|
4005
|
+
});
|
|
4006
|
+
}
|
|
4007
|
+
}
|
|
4008
|
+
/**
|
|
3898
4009
|
* locationId → resolved `minFreePercent`. The policy is intrinsic to the
|
|
3899
4010
|
* location's provider (`shouldSaveDiskSpace` gates the guard, `minFreePercent`
|
|
3900
4011
|
* is the default), overridable per-location via `config.minFreePercent`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $r as secretTreeFromPaths, A as LegacyStorageLocationDefaultSchema, At as evictionPolicyOfLocation, Br as isSecretMarker, Dn as resolveLocationMode, Er as collectSecretConfigKeys, G as StorageMigrationJobSchema, Gr as parseJsonObject, H as StorageCleanupJobSchema, Ln as storageCapability, Lt as gbToBytes, Pn as settingsStoreCapability, Rn as storageMigrationCapability, U as StorageLocationModeSchema, Ut as isLocationEnabled, W as StorageLocationTypeSchema, Xn as withLocationMode, Xr as resolveSecretMarkers, Xt as legacyModeOf, _r as REDACTED_SECRET, ai as EventCategory, an as mayWriteToLocation, cn as modeMayWrite, ii as transformSecretWrite, in as mayReadLocation, pr as BaseAddon } from "../../dist-DwE9yHdk.mjs";
|
|
2
2
|
import { t as HUB_CAP_FWD_ACTION } from "../../hub-cap-forward-CDiN1p98.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
@@ -3337,6 +3337,64 @@ var StoragePressureManager = class {
|
|
|
3337
3337
|
}
|
|
3338
3338
|
};
|
|
3339
3339
|
//#endregion
|
|
3340
|
+
//#region src/builtins/storage-orchestrator/storage-location-band-monitor.ts
|
|
3341
|
+
var DEFAULT_STORAGE_LOCATION_BAND_CONFIG = {
|
|
3342
|
+
lowPercent: 15,
|
|
3343
|
+
criticalPercent: 5
|
|
3344
|
+
};
|
|
3345
|
+
function bandOf(freePercent, config) {
|
|
3346
|
+
if (freePercent === null) return {
|
|
3347
|
+
band: "critical",
|
|
3348
|
+
reason: "capacity-unreadable"
|
|
3349
|
+
};
|
|
3350
|
+
if (freePercent <= config.criticalPercent) return {
|
|
3351
|
+
band: "critical",
|
|
3352
|
+
reason: "free-below-critical"
|
|
3353
|
+
};
|
|
3354
|
+
if (freePercent <= config.lowPercent) return {
|
|
3355
|
+
band: "low",
|
|
3356
|
+
reason: "free-below-warn"
|
|
3357
|
+
};
|
|
3358
|
+
return {
|
|
3359
|
+
band: "ok",
|
|
3360
|
+
reason: "free-ok"
|
|
3361
|
+
};
|
|
3362
|
+
}
|
|
3363
|
+
var StorageLocationBandMonitor = class {
|
|
3364
|
+
config;
|
|
3365
|
+
band = /* @__PURE__ */ new Map();
|
|
3366
|
+
constructor(config = DEFAULT_STORAGE_LOCATION_BAND_CONFIG) {
|
|
3367
|
+
this.config = config;
|
|
3368
|
+
}
|
|
3369
|
+
/**
|
|
3370
|
+
* Observe one sweep of managed locations. Locations missing from `samples`
|
|
3371
|
+
* drop their episode without emitting `ok` (disabled / removed).
|
|
3372
|
+
*/
|
|
3373
|
+
observe(samples) {
|
|
3374
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3375
|
+
const out = [];
|
|
3376
|
+
for (const sample of samples) {
|
|
3377
|
+
seen.add(sample.locationId);
|
|
3378
|
+
const { band, reason } = bandOf(sample.freePercent, this.config);
|
|
3379
|
+
const previous = this.band.get(sample.locationId) ?? null;
|
|
3380
|
+
if (previous === band) continue;
|
|
3381
|
+
this.band.set(sample.locationId, band);
|
|
3382
|
+
if (previous === null && band === "ok") continue;
|
|
3383
|
+
out.push({
|
|
3384
|
+
locationId: sample.locationId,
|
|
3385
|
+
...sample.nodeId !== void 0 ? { nodeId: sample.nodeId } : {},
|
|
3386
|
+
...sample.locationName !== void 0 ? { locationName: sample.locationName } : {},
|
|
3387
|
+
band,
|
|
3388
|
+
freePercent: sample.freePercent,
|
|
3389
|
+
reason,
|
|
3390
|
+
previous
|
|
3391
|
+
});
|
|
3392
|
+
}
|
|
3393
|
+
for (const id of [...this.band.keys()]) if (!seen.has(id)) this.band.delete(id);
|
|
3394
|
+
return out;
|
|
3395
|
+
}
|
|
3396
|
+
};
|
|
3397
|
+
//#endregion
|
|
3340
3398
|
//#region src/builtins/storage-orchestrator/storage-orchestrator.addon.ts
|
|
3341
3399
|
/**
|
|
3342
3400
|
* `storage-orchestrator` builtin — singleton owner of the consumer-
|
|
@@ -3381,6 +3439,7 @@ var CAP_PROVIDER_REGISTERED_CATEGORY = "capability:provider-registered";
|
|
|
3381
3439
|
var StorageOrchestratorAddon = class extends BaseAddon {
|
|
3382
3440
|
service = null;
|
|
3383
3441
|
pressureManager = null;
|
|
3442
|
+
locationBandMonitor = new StorageLocationBandMonitor();
|
|
3384
3443
|
/**
|
|
3385
3444
|
* How much of each location CamStack itself holds (D388).
|
|
3386
3445
|
*
|
|
@@ -3883,6 +3942,7 @@ var StorageOrchestratorAddon = class extends BaseAddon {
|
|
|
3883
3942
|
this.pressureSweepInFlight = true;
|
|
3884
3943
|
try {
|
|
3885
3944
|
await this.pressureManager.sweep();
|
|
3945
|
+
await this.emitLocationBandEvents();
|
|
3886
3946
|
} catch (err) {
|
|
3887
3947
|
this.ctxIfReady?.logger.warn("storage pressure sweep failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
3888
3948
|
} finally {
|
|
@@ -3890,6 +3950,57 @@ var StorageOrchestratorAddon = class extends BaseAddon {
|
|
|
3890
3950
|
}
|
|
3891
3951
|
}
|
|
3892
3952
|
/**
|
|
3953
|
+
* Sample free space for every managed location and emit NC band edges.
|
|
3954
|
+
* A failed capacity read stays `null` (critical) — never folded to 0 (D393).
|
|
3955
|
+
*/
|
|
3956
|
+
async emitLocationBandEvents() {
|
|
3957
|
+
const svc = this.service;
|
|
3958
|
+
const ctx = this.ctxIfReady;
|
|
3959
|
+
if (!svc || !ctx) return;
|
|
3960
|
+
const thresholds = await this.resolveLocationThresholds();
|
|
3961
|
+
const byId = new Map(svc.listLocations().map((loc) => [loc.id, loc]));
|
|
3962
|
+
const samples = await Promise.all([...thresholds.keys()].map(async (locationId) => {
|
|
3963
|
+
const loc = byId.get(locationId);
|
|
3964
|
+
if (loc === void 0 || !mayReadLocation(loc)) return {
|
|
3965
|
+
locationId,
|
|
3966
|
+
freePercent: null
|
|
3967
|
+
};
|
|
3968
|
+
const capacity = await this.volumeCapacityOf(locationId).catch(() => null);
|
|
3969
|
+
const freePercent = capacity === null ? null : freePercentOf(capacity);
|
|
3970
|
+
return {
|
|
3971
|
+
locationId,
|
|
3972
|
+
nodeId: loc.nodeId,
|
|
3973
|
+
locationName: loc.displayName,
|
|
3974
|
+
freePercent
|
|
3975
|
+
};
|
|
3976
|
+
}));
|
|
3977
|
+
for (const edge of this.locationBandMonitor.observe(samples)) {
|
|
3978
|
+
const category = edge.band === "low" ? EventCategory.StorageLocationLow : edge.band === "critical" ? EventCategory.StorageLocationCritical : EventCategory.StorageLocationOk;
|
|
3979
|
+
ctx.logger.info("storage: location band changed", { meta: {
|
|
3980
|
+
locationId: edge.locationId,
|
|
3981
|
+
band: edge.band,
|
|
3982
|
+
freePercent: edge.freePercent,
|
|
3983
|
+
reason: edge.reason
|
|
3984
|
+
} });
|
|
3985
|
+
ctx.eventBus.emit({
|
|
3986
|
+
id: randomUUID(),
|
|
3987
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
3988
|
+
source: {
|
|
3989
|
+
type: "addon",
|
|
3990
|
+
id: this.ctx.id
|
|
3991
|
+
},
|
|
3992
|
+
category,
|
|
3993
|
+
data: {
|
|
3994
|
+
locationId: edge.locationId,
|
|
3995
|
+
...edge.nodeId !== void 0 ? { nodeId: edge.nodeId } : {},
|
|
3996
|
+
...edge.locationName !== void 0 ? { locationName: edge.locationName } : {},
|
|
3997
|
+
freePercent: edge.freePercent,
|
|
3998
|
+
reason: edge.reason
|
|
3999
|
+
}
|
|
4000
|
+
});
|
|
4001
|
+
}
|
|
4002
|
+
}
|
|
4003
|
+
/**
|
|
3893
4004
|
* locationId → resolved `minFreePercent`. The policy is intrinsic to the
|
|
3894
4005
|
* location's provider (`shouldSaveDiskSpace` gates the guard, `minFreePercent`
|
|
3895
4006
|
* is the default), overridable per-location via `config.minFreePercent`.
|