@camstack/system 1.2.202 → 1.2.203
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/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/backup-orchestrator/backup-orchestrator.addon.d.ts +12 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +37 -3
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +37 -3
- 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 +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
- 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/doorbell/virtual-doorbell.addon.js +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- 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 +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- 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/drain-ratchet.d.ts +104 -0
- package/dist/builtins/storage-orchestrator/drain-state-store.d.ts +13 -0
- package/dist/builtins/storage-orchestrator/location-occupancy-slice.d.ts +47 -0
- package/dist/builtins/storage-orchestrator/location-protection.d.ts +20 -0
- package/dist/builtins/storage-orchestrator/location-root-collision.d.ts +44 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +47 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +714 -58
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +714 -58
- package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts +32 -11
- package/dist/builtins/storage-orchestrator/storage-pressure-manager.d.ts +45 -0
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{dist-jZb-HKI5.js → dist-BFvWv_bz.js} +730 -372
- package/dist/{dist-CiHYspij.mjs → dist-DcMUcdeq.mjs} +671 -373
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{retired-settings-keys-DeRxo3vg.mjs → retired-settings-keys-CJfgnUSb.mjs} +1 -1
- package/dist/{retired-settings-keys-Dxv9S_lO.js → retired-settings-keys-Dd7K3K3r.js} +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { IScopedLogger, IStorageOccupancyProvider } from '@camstack/types';
|
|
2
|
+
/** What one location's owners hold there, merged. */
|
|
3
|
+
export interface LocationOwnedBytes {
|
|
4
|
+
readonly bytes: number;
|
|
5
|
+
/** The OLDEST contributing measurement — honest about the whole figure
|
|
6
|
+
* rather than about its freshest part. */
|
|
7
|
+
readonly measuredAtMs: number;
|
|
8
|
+
}
|
|
9
|
+
export interface OccupancySliceDeps {
|
|
10
|
+
readonly logger: IScopedLogger;
|
|
11
|
+
/** Registered `storage-occupancy` providers (cross-process proxies). */
|
|
12
|
+
readonly getProviders: () => readonly IStorageOccupancyProvider[];
|
|
13
|
+
/** Every location worth asking about, at refresh time. */
|
|
14
|
+
readonly locationIds: () => readonly string[];
|
|
15
|
+
readonly now: () => number;
|
|
16
|
+
/** How long a figure stays servable before a refresh is kicked. */
|
|
17
|
+
readonly staleAfterMs?: number;
|
|
18
|
+
}
|
|
19
|
+
export declare class LocationOccupancySlice {
|
|
20
|
+
private readonly deps;
|
|
21
|
+
private slice;
|
|
22
|
+
private refreshing;
|
|
23
|
+
private lastRefreshMs;
|
|
24
|
+
constructor(deps: OccupancySliceDeps);
|
|
25
|
+
/**
|
|
26
|
+
* What the last completed refresh saw for this location, or `undefined` when
|
|
27
|
+
* nothing has reported for it. There is deliberately no fallback: unknown is
|
|
28
|
+
* the truth about a location nobody owns bytes on.
|
|
29
|
+
*/
|
|
30
|
+
ownedFor(locationId: string): LocationOwnedBytes | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Serve-and-revalidate. Called by every read: it returns immediately, and
|
|
33
|
+
* kicks a background refresh when the slice is older than the window. A read
|
|
34
|
+
* never awaits, and never joins a refresh already in flight (D224).
|
|
35
|
+
*/
|
|
36
|
+
serveAndRevalidate(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Ask every provider once and replace the slice.
|
|
39
|
+
*
|
|
40
|
+
* A provider that throws contributes NOTHING and is logged — it does not
|
|
41
|
+
* contribute a zero, and it does not take the other providers' answers down
|
|
42
|
+
* with it. A location that ends up with no contribution at all simply stays
|
|
43
|
+
* out of the slice, which is what makes it read back as unknown.
|
|
44
|
+
*/
|
|
45
|
+
refresh(): Promise<void>;
|
|
46
|
+
private runRefresh;
|
|
47
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** statfs of the location's volume, when this node could take it. */
|
|
2
|
+
export interface LocationVolumeCapacity {
|
|
3
|
+
readonly totalBytes: number;
|
|
4
|
+
readonly availableBytes: number;
|
|
5
|
+
}
|
|
6
|
+
/** One line, at most once per location per process. */
|
|
7
|
+
export type ProtectionNotice = (message: string, meta: Record<string, unknown>) => void;
|
|
8
|
+
/**
|
|
9
|
+
* The free-space percentage the guard enforces for one location.
|
|
10
|
+
*
|
|
11
|
+
* Order:
|
|
12
|
+
* 1. `config.minFreeGb`, converted against the volume total — the operator's
|
|
13
|
+
* criterion in the unit they set it in.
|
|
14
|
+
* 2. `config.minFreePercent` — the legacy per-location override, and the
|
|
15
|
+
* fallback when `minFreeGb` cannot be converted (no volume total: a
|
|
16
|
+
* remote-node or unstattable location). Falling back is the right
|
|
17
|
+
* direction — the alternative is a location with no guard at all.
|
|
18
|
+
* 3. the provider's declared default.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveMinFreePercent(config: Readonly<Record<string, unknown>>, providerDefaultPercent: number, capacity: LocationVolumeCapacity | null, notice: ProtectionNotice): number;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { PhysicalRoot } from '@camstack/types/node';
|
|
2
|
+
/** The minimum a row must expose for this check. */
|
|
3
|
+
export interface RootCollisionCandidate {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly type: string;
|
|
6
|
+
/** Which node the path lives on. Two locations on DIFFERENT nodes can never
|
|
7
|
+
* collide, however identical their paths look. */
|
|
8
|
+
readonly nodeId?: string;
|
|
9
|
+
readonly config: Readonly<Record<string, unknown>>;
|
|
10
|
+
}
|
|
11
|
+
/** How this location's physical root was derived, or that it could not be. */
|
|
12
|
+
export type ResolveRoot = (basePath: string) => PhysicalRoot;
|
|
13
|
+
/** A same-type root collision, with everything the message needs to name it. */
|
|
14
|
+
export interface RootCollision {
|
|
15
|
+
readonly otherId: string;
|
|
16
|
+
readonly type: string;
|
|
17
|
+
readonly sharedRoot: string;
|
|
18
|
+
/** `equal` — the same directory. `nested` — one inside the other's tree. */
|
|
19
|
+
readonly kind: 'equal' | 'nested';
|
|
20
|
+
}
|
|
21
|
+
/** Why the check could not be made. Never a refusal — the caller warns. */
|
|
22
|
+
export interface RootCollisionUnknown {
|
|
23
|
+
readonly reason: 'no-base-path' | 'unresolvable';
|
|
24
|
+
readonly detail: string;
|
|
25
|
+
}
|
|
26
|
+
export type RootCollisionVerdict = {
|
|
27
|
+
readonly outcome: 'clear';
|
|
28
|
+
} | {
|
|
29
|
+
readonly outcome: 'collides';
|
|
30
|
+
readonly collision: RootCollision;
|
|
31
|
+
} | {
|
|
32
|
+
readonly outcome: 'unknown';
|
|
33
|
+
readonly unknown: RootCollisionUnknown;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Does `next` collide with anything already stored?
|
|
37
|
+
*
|
|
38
|
+
* `existing` is every other location; the row being EDITED is excluded by id,
|
|
39
|
+
* so re-saving a location without moving its root never refuses itself.
|
|
40
|
+
*/
|
|
41
|
+
export declare function findRootCollision(next: RootCollisionCandidate, existing: Iterable<RootCollisionCandidate>, resolveRoot: ResolveRoot, storedSelf?: RootCollisionCandidate): RootCollisionVerdict;
|
|
42
|
+
/** The operator-facing refusal. Names the location it collides with and the
|
|
43
|
+
* shared root — a refusal that says only "conflict" makes the operator hunt. */
|
|
44
|
+
export declare function rootCollisionMessage(id: string, collision: RootCollision): string;
|
|
@@ -4,6 +4,15 @@ interface StorageOrchestratorConfig extends Record<string, unknown> {
|
|
|
4
4
|
export declare class StorageOrchestratorAddon extends BaseAddon<StorageOrchestratorConfig> {
|
|
5
5
|
private service;
|
|
6
6
|
private pressureManager;
|
|
7
|
+
/**
|
|
8
|
+
* How much of each location CamStack itself holds (D388).
|
|
9
|
+
*
|
|
10
|
+
* Built on first use rather than in a field initializer: `this.ctx` does not
|
|
11
|
+
* exist until `initialize()` runs, and a field initializer touching it throws
|
|
12
|
+
* in the constructor.
|
|
13
|
+
*/
|
|
14
|
+
private occupancySlice;
|
|
15
|
+
private get occupancy();
|
|
7
16
|
private pressureTimer;
|
|
8
17
|
private pressureSweepInFlight;
|
|
9
18
|
private migration;
|
|
@@ -98,6 +107,25 @@ export declare class StorageOrchestratorAddon extends BaseAddon<StorageOrchestra
|
|
|
98
107
|
* the recorder so disk-pressure is a single core concern.
|
|
99
108
|
*/
|
|
100
109
|
private resolveLocationThresholds;
|
|
110
|
+
/** Location ids that have already logged the `minFreeGb` / `minFreePercent`
|
|
111
|
+
* redundancy. The pressure sweep runs on a timer; the notice is worth
|
|
112
|
+
* exactly one line per location per process, not one per minute. */
|
|
113
|
+
private readonly minFreeRedundancyLogged;
|
|
114
|
+
private logMinFreeRedundancyOnce;
|
|
115
|
+
/**
|
|
116
|
+
* The draining locations and the ACTIVE peers of their class whose growth
|
|
117
|
+
* paces them (D386). Rebuilt every sweep from the live mode of every
|
|
118
|
+
* location, so this is also what STOPS a drain: a location the operator
|
|
119
|
+
* switched back simply stops appearing.
|
|
120
|
+
*/
|
|
121
|
+
private drainStore;
|
|
122
|
+
/** The drain ratchet's durable home, once a data-store engine exists. Same
|
|
123
|
+
* late-wiring window as the location table — on an agent it is never. */
|
|
124
|
+
private resolveDrainStore;
|
|
125
|
+
private drainPlanRefusalLogged;
|
|
126
|
+
private resolveDrainPlan;
|
|
127
|
+
/** Drain progress for every draining location, as of the last sweep. */
|
|
128
|
+
private drainProgress;
|
|
101
129
|
/**
|
|
102
130
|
* What the provider's own schema declared secret, or `undefined` when this
|
|
103
131
|
* node has never heard from that provider. The distinction is the whole
|
|
@@ -106,6 +134,25 @@ export declare class StorageOrchestratorAddon extends BaseAddon<StorageOrchestra
|
|
|
106
134
|
private declaredSecretKeys;
|
|
107
135
|
/** Which keys of a given stored config must never leave this process. */
|
|
108
136
|
private secretKeysFor;
|
|
137
|
+
/**
|
|
138
|
+
* Ring the doorbell: the SET of storage locations changed (D387).
|
|
139
|
+
*
|
|
140
|
+
* A consumer that resolves locations at boot had no way to learn that the
|
|
141
|
+
* operator added, edited or removed one — the recorder kept writing to the
|
|
142
|
+
* disk set it resolved hours ago, and an operator who added a second
|
|
143
|
+
* recordings disk in the admin UI got nothing until something unrelated
|
|
144
|
+
* happened to re-resolve.
|
|
145
|
+
*
|
|
146
|
+
* Telemetry, and deliberately so (D8/D11): it carries no row, it is allowed
|
|
147
|
+
* to be dropped, and every consumer re-reads `listLocations` for itself and
|
|
148
|
+
* converges on its own periodic path anyway. A bulk edit rings it once per
|
|
149
|
+
* row — coalescing is the consumer's job, not this one's.
|
|
150
|
+
*
|
|
151
|
+
* Never throws into the mutation that produced it: the location IS saved,
|
|
152
|
+
* and a bus that will not take a telemetry event must not turn that into a
|
|
153
|
+
* failed upsert.
|
|
154
|
+
*/
|
|
155
|
+
private announceLocationsChanged;
|
|
109
156
|
/** A location with its provider's declared secrets replaced by the sentinel. */
|
|
110
157
|
private redacted;
|
|
111
158
|
/**
|