@camstack/server 1.2.135 → 1.2.136

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.
@@ -54,6 +54,7 @@ const prune_misplaced_addons_js_1 = require("./prune-misplaced-addons.js");
54
54
  const require_cache_js_1 = require("./require-cache.js");
55
55
  const runner_convergence_1 = require("./runner-convergence");
56
56
  const runner_spawn_fanout_js_1 = require("./runner-spawn-fanout.js");
57
+ const single_flight_refresh_js_1 = require("./single-flight-refresh.js");
57
58
  /**
58
59
  * Decide whether an in-memory addon entry should be evicted because it is no
59
60
  * longer on disk (the uninstall path in `loadNewAddons`).
@@ -1153,11 +1154,18 @@ class AddonRegistryService {
1153
1154
  }
1154
1155
  return out;
1155
1156
  };
1157
+ /** One full-fleet rebuild in flight, at most one queued behind it. Every
1158
+ * event below asks for the SAME total rebuild, so running it once per event
1159
+ * was ~1 000 rebuilds of a 974-row mirror on a boot — each one a 625 KB read
1160
+ * and parse on hub-main's event loop. No timer: the first event still
1161
+ * refreshes immediately, because this mirror backs scope enforcement.
1162
+ * See `single-flight-refresh.ts`. */
1163
+ deviceMirrorGate = (0, single_flight_refresh_js_1.createSingleFlightRefresh)(() => this.refreshDeviceParentMirror());
1156
1164
  /** Subscribe the mirror to every device-meta lifecycle event, and warm it once
1157
1165
  * the addon set (device-manager included) is up. */
1158
1166
  wireDeviceParentMirror() {
1159
1167
  const refresh = () => {
1160
- void this.refreshDeviceParentMirror();
1168
+ void this.deviceMirrorGate.request();
1161
1169
  };
1162
1170
  for (const category of [
1163
1171
  types_1.EventCategory.DeviceMetaChanged,
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSingleFlightRefresh = createSingleFlightRefresh;
4
+ /**
5
+ * @param run the total rebuild. Called with no arguments, never concurrently
6
+ * with itself.
7
+ */
8
+ function createSingleFlightRefresh(run) {
9
+ let inFlight = null;
10
+ // Set while a run is active and another request arrived. One flag, not a
11
+ // counter: N requests during one run need exactly ONE follow-up between
12
+ // them, because the follow-up reads the world as it is when it starts.
13
+ let pending = false;
14
+ let pendingPromise = null;
15
+ let releasePending = () => { };
16
+ const start = () => {
17
+ const active = (async () => {
18
+ try {
19
+ await run();
20
+ }
21
+ finally {
22
+ inFlight = null;
23
+ if (pending) {
24
+ pending = false;
25
+ const release = releasePending;
26
+ releasePending = () => { };
27
+ pendingPromise = null;
28
+ // Chain the follow-up, then settle everyone who waited for it.
29
+ void start().finally(release);
30
+ }
31
+ }
32
+ })();
33
+ inFlight = active;
34
+ return active;
35
+ };
36
+ return {
37
+ request: async () => {
38
+ if (inFlight === null) {
39
+ await start();
40
+ return;
41
+ }
42
+ if (!pending) {
43
+ pending = true;
44
+ pendingPromise = new Promise((resolve) => {
45
+ releasePending = resolve;
46
+ });
47
+ }
48
+ // `pendingPromise` is non-null whenever `pending` is set; the local
49
+ // binding keeps that visible to the type checker after the await.
50
+ const wait = pendingPromise;
51
+ if (wait !== null)
52
+ await wait;
53
+ },
54
+ };
55
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/server",
3
- "version": "1.2.135",
3
+ "version": "1.2.136",
4
4
  "private": false,
5
5
  "files": [
6
6
  "dist",
@@ -38,12 +38,12 @@
38
38
  "@camstack/addon-auth": "1.2.26",
39
39
  "@camstack/addon-decoder-nodeav": "1.2.22",
40
40
  "@camstack/addon-notifiers": "1.2.27",
41
- "@camstack/addon-pipeline": "1.2.98",
41
+ "@camstack/addon-pipeline": "1.2.99",
42
42
  "@camstack/addon-pipeline-orchestrator": "1.2.83",
43
- "@camstack/addon-post-analysis": "1.2.99",
43
+ "@camstack/addon-post-analysis": "1.2.100",
44
44
  "@camstack/sdk": "1.2.25",
45
45
  "@camstack/shm-ring": "1.1.22",
46
- "@camstack/system": "1.2.106",
46
+ "@camstack/system": "1.2.107",
47
47
  "@camstack/types": "1.2.90",
48
48
  "@camstack/ui-library": "1.2.62",
49
49
  "@fastify/compress": "^9.0.0",