@camstack/addon-pipeline 1.2.122 → 1.2.124

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.
@@ -24097,6 +24097,19 @@ var SCRUB_RECENTER_MS = 12e4;
24097
24097
  /** Hard bound on warm reads, derived from the session RAM budget. */
24098
24098
  var SCRUB_WARM_MAX_SEGMENTS = Math.max(1, Math.floor(SCRUB_FRAGMENT_CACHE_MAX_BYTES / 2e5));
24099
24099
  /**
24100
+ * Pause between two IDLE warm reads — the fill that continues AFTER a seek or
24101
+ * a scrub commit, while no finger is down.
24102
+ *
24103
+ * Idle warm exists because the cold/warm ratio on the recordings spindle is
24104
+ * 19× (531 ms vs 28 ms, measured 2026-08-25) and the operator's think-time on
24105
+ * a landed frame is the one window where the spindle is otherwise free. But
24106
+ * that same spindle carries every camera's writes and the export/event reads:
24107
+ * an UNPACED background walk would be one more saturating reader. One segment
24108
+ * read per gap keeps the fill under ~1 read/s worst case — the window fills in
24109
+ * a couple of minutes and the drag that follows lands on RAM.
24110
+ */
24111
+ var IDLE_WARM_READ_GAP_MS = 250;
24112
+ /**
24100
24113
  * Median recent read time at or above which the feeder STOPS speculating.
24101
24114
  *
24102
24115
  * Speculation is a bet that spare I/O exists. When reads are this slow there is
@@ -24363,6 +24376,13 @@ var RecordedFeeder = class {
24363
24376
  scrubReadMsWindow = [];
24364
24377
  /** Warm-up runs once per drag, from the playhead the finger went down on. */
24365
24378
  scrubWarmStarted = false;
24379
+ /**
24380
+ * True while the fill window belongs to IDLE mode — started by a seek (a
24381
+ * timeline tap or a scrub commit) rather than by a drag. An idle fill paces
24382
+ * itself ({@link IDLE_WARM_READ_GAP_MS}) and yields to any in-flight seek;
24383
+ * a drag's own warm (`beginScrub`) always takes the window over.
24384
+ */
24385
+ idleWarm = false;
24366
24386
  /** Centre of the fill currently in flight (or last completed). */
24367
24387
  scrubWarmCentreMs = null;
24368
24388
  /** Bumped to abort a fill without aborting the drag tick (`scrubToken`). */
@@ -24607,6 +24627,7 @@ var RecordedFeeder = class {
24607
24627
  bytes: loaded.bytes,
24608
24628
  loadAusMs: Math.round(loadAusMs)
24609
24629
  });
24630
+ this.startIdleWarm(this.cursorMs);
24610
24631
  return;
24611
24632
  }
24612
24633
  if (!stateAnnounced) {
@@ -24643,6 +24664,7 @@ var RecordedFeeder = class {
24643
24664
  },
24644
24665
  resumeAfterPtsMs
24645
24666
  });
24667
+ this.startIdleWarm(this.cursorMs);
24646
24668
  } catch (err) {
24647
24669
  if (!this.disposed && token === this.seekToken) {
24648
24670
  this.stopPositionReports();
@@ -24756,7 +24778,36 @@ var RecordedFeeder = class {
24756
24778
  this.stopPositionReports();
24757
24779
  this.scrubWarmStarted = false;
24758
24780
  this.scrubReadMsWindow = [];
24759
- if (this.cursorMs > 0 && this.deps.profile === SCRUB_WHOLE_SEGMENT_PROFILE) this.startScrubWarm(this.cursorMs, this.scrubToken);
24781
+ if (this.cursorMs > 0 && this.deps.profile === SCRUB_WHOLE_SEGMENT_PROFILE) {
24782
+ this.idleWarm = false;
24783
+ this.startScrubWarm(this.cursorMs, this.scrubToken, { force: true });
24784
+ }
24785
+ }
24786
+ /**
24787
+ * Start (or recentre) the IDLE fill: called after every completed seek —
24788
+ * a timeline tap or a scrub commit — with the landed cursor. The operator is
24789
+ * now LOOKING at that frame; the next gesture almost always starts near it,
24790
+ * and this is the one moment the spindle is not serving the finger. Bounds:
24791
+ * the same session cache budget as the drag warm (48 MB LRU — no new store),
24792
+ * the same {@link SCRUB_WARM_MAX_SEGMENTS} per-window cap, plus the idle
24793
+ * pacing gap. `low`-only for the same reason the drag warm is: a `high`
24794
+ * window would be hundreds of MB of reads for a profile no drag reads.
24795
+ */
24796
+ startIdleWarm(centreMs) {
24797
+ if (this.disposed || this.scrubbing) return;
24798
+ if (centreMs <= 0 || this.deps.profile !== SCRUB_WHOLE_SEGMENT_PROFILE) return;
24799
+ this.idleWarm = true;
24800
+ this.startScrubWarm(centreMs, this.scrubToken, { force: true });
24801
+ }
24802
+ /**
24803
+ * Whether the fill loop generation `dragGen` may keep working. During a drag
24804
+ * only that drag's generation runs (a commit bumps `scrubToken` and the old
24805
+ * walker exits); outside a drag the loop runs exactly while idle warm is on.
24806
+ */
24807
+ warmLoopAlive(dragGen) {
24808
+ if (this.disposed) return false;
24809
+ if (this.scrubbing) return dragGen === this.scrubToken;
24810
+ return this.idleWarm;
24760
24811
  }
24761
24812
  /**
24762
24813
  * Warm the window the drag is about to move through: {@link SCRUB_WARM_BACK_MS}
@@ -24796,19 +24847,29 @@ var RecordedFeeder = class {
24796
24847
  async runScrubFillLoop(dragGen) {
24797
24848
  let lastWorked = -1;
24798
24849
  try {
24799
- while (!this.disposed && this.scrubbing && dragGen === this.scrubToken) {
24850
+ while (this.warmLoopAlive(dragGen)) {
24800
24851
  const gen = this.scrubWarmGen;
24801
24852
  const centre = this.scrubWarmCentreMs;
24802
24853
  if (centre === null) return;
24803
- await this.warmScrubWindow(centre, dragGen, gen, this.scrubWarmBackMs, this.scrubWarmFwdMs);
24854
+ const startedAt = performance.now();
24855
+ const fetched = await this.warmScrubWindow(centre, dragGen, gen, this.scrubWarmBackMs, this.scrubWarmFwdMs);
24804
24856
  lastWorked = gen;
24805
- if (gen === this.scrubWarmGen) return;
24857
+ if (gen === this.scrubWarmGen) {
24858
+ this.deps.onLog?.("scrub-feeder:warm-done", {
24859
+ fillGen: gen,
24860
+ idle: this.idleWarm && !this.scrubbing,
24861
+ fetched,
24862
+ ms: Math.round(performance.now() - startedAt)
24863
+ });
24864
+ if (!this.scrubbing) this.idleWarm = false;
24865
+ return;
24866
+ }
24806
24867
  }
24807
24868
  } finally {
24808
24869
  this.scrubFillLoopActive = false;
24809
- if (!this.disposed && this.scrubbing && dragGen === this.scrubToken && this.scrubWarmCentreMs !== null && this.scrubWarmGen !== lastWorked) {
24870
+ if (!this.disposed && (this.scrubbing || this.idleWarm) && this.scrubWarmCentreMs !== null && this.scrubWarmGen !== lastWorked) {
24810
24871
  this.scrubFillLoopActive = true;
24811
- this.runScrubFillLoop(dragGen);
24872
+ this.runScrubFillLoop(this.scrubToken);
24812
24873
  }
24813
24874
  }
24814
24875
  }
@@ -24833,7 +24894,7 @@ var RecordedFeeder = class {
24833
24894
  }
24834
24895
  async warmScrubWindow(centreMs, dragGen, fillGen, backMs, fwdMs) {
24835
24896
  const spent = await this.warmScrubDirection(centreMs, -1, backMs, 0, dragGen, fillGen);
24836
- await this.warmScrubDirection(centreMs, 1, fwdMs, spent, dragGen, fillGen);
24897
+ return this.warmScrubDirection(centreMs, 1, fwdMs, spent, dragGen, fillGen);
24837
24898
  }
24838
24899
  /**
24839
24900
  * Walk `dir` from `fromMs` until `spanMs` of timeline is warm (or the shared
@@ -24844,7 +24905,7 @@ var RecordedFeeder = class {
24844
24905
  let read = spent;
24845
24906
  let probeMs = fromMs;
24846
24907
  for (let i = 0; i < SCRUB_WARM_MAX_SEGMENTS; i++) {
24847
- if (this.disposed || !this.scrubbing || dragGen !== this.scrubToken) return read;
24908
+ if (!this.warmLoopAlive(dragGen)) return read;
24848
24909
  if (fillGen !== this.scrubWarmGen) return read;
24849
24910
  if (read >= SCRUB_WARM_MAX_SEGMENTS) return read;
24850
24911
  if (Math.abs(probeMs - fromMs) > spanMs) return read;
@@ -24870,19 +24931,27 @@ var RecordedFeeder = class {
24870
24931
  durMs: warm.durMs,
24871
24932
  fetched: false
24872
24933
  };
24934
+ if (this.idleWarm && !this.scrubbing) {
24935
+ await new Promise((r) => setTimeout(r, this.deps.idleWarmGapMs ?? IDLE_WARM_READ_GAP_MS));
24936
+ while (this.inFlightSeekEpochMs !== null) {
24937
+ if (!this.warmLoopAlive(dragGen) || fillGen !== this.scrubWarmGen) return null;
24938
+ await new Promise((r) => setTimeout(r, 20));
24939
+ }
24940
+ if (!this.warmLoopAlive(dragGen) || fillGen !== this.scrubWarmGen) return null;
24941
+ }
24873
24942
  if (!await this.waitForTickReadIdle(fillGen)) return null;
24874
24943
  const loc = await this.withTimeout(this.deps.locate({
24875
24944
  deviceId: this.deps.deviceId,
24876
24945
  profile: this.deps.profile,
24877
24946
  epochMs: probeMs
24878
24947
  }));
24879
- if (this.disposed || !this.scrubbing || dragGen !== this.scrubToken) return null;
24948
+ if (!this.warmLoopAlive(dragGen)) return null;
24880
24949
  if (fillGen !== this.scrubWarmGen) return null;
24881
24950
  if (loc.kind !== "segment") return null;
24882
24951
  if (!await this.waitForTickReadIdle(fillGen)) return null;
24883
24952
  const load = await this.loadScrubFragment(loc, probeMs);
24884
- if (load !== null) this.scrubStats?.recordPrefetchRead(load.readBytes);
24885
- if (this.disposed || !this.scrubbing || dragGen !== this.scrubToken || load === null) return null;
24953
+ if (load !== null && this.scrubbing) this.scrubStats?.recordPrefetchRead(load.readBytes);
24954
+ if (!this.warmLoopAlive(dragGen) || load === null) return null;
24886
24955
  if (fillGen !== this.scrubWarmGen) return null;
24887
24956
  this.scrubCache.put(this.deps.profile, load.seg);
24888
24957
  this.scrubPrefetched.add(load.seg.startMs);
@@ -24899,7 +24968,8 @@ var RecordedFeeder = class {
24899
24968
  async waitForTickReadIdle(fillGen) {
24900
24969
  while (this.scrubTickReadInFlight) {
24901
24970
  await new Promise((r) => setTimeout(r, 4));
24902
- if (this.disposed || !this.scrubbing || fillGen !== this.scrubWarmGen) return false;
24971
+ if (this.disposed || fillGen !== this.scrubWarmGen) return false;
24972
+ if (!this.scrubbing && !this.idleWarm) return false;
24903
24973
  }
24904
24974
  return true;
24905
24975
  }
@@ -26085,6 +26155,7 @@ var RecordedFeeder = class {
26085
26155
  this.seekToken++;
26086
26156
  this.advanceToken++;
26087
26157
  this.scrubbing = false;
26158
+ this.idleWarm = false;
26088
26159
  this.scrubToken++;
26089
26160
  this.scrubSegment = null;
26090
26161
  this.scrubPrevTarget = null;
@@ -24092,6 +24092,19 @@ var SCRUB_RECENTER_MS = 12e4;
24092
24092
  /** Hard bound on warm reads, derived from the session RAM budget. */
24093
24093
  var SCRUB_WARM_MAX_SEGMENTS = Math.max(1, Math.floor(SCRUB_FRAGMENT_CACHE_MAX_BYTES / 2e5));
24094
24094
  /**
24095
+ * Pause between two IDLE warm reads — the fill that continues AFTER a seek or
24096
+ * a scrub commit, while no finger is down.
24097
+ *
24098
+ * Idle warm exists because the cold/warm ratio on the recordings spindle is
24099
+ * 19× (531 ms vs 28 ms, measured 2026-08-25) and the operator's think-time on
24100
+ * a landed frame is the one window where the spindle is otherwise free. But
24101
+ * that same spindle carries every camera's writes and the export/event reads:
24102
+ * an UNPACED background walk would be one more saturating reader. One segment
24103
+ * read per gap keeps the fill under ~1 read/s worst case — the window fills in
24104
+ * a couple of minutes and the drag that follows lands on RAM.
24105
+ */
24106
+ var IDLE_WARM_READ_GAP_MS = 250;
24107
+ /**
24095
24108
  * Median recent read time at or above which the feeder STOPS speculating.
24096
24109
  *
24097
24110
  * Speculation is a bet that spare I/O exists. When reads are this slow there is
@@ -24358,6 +24371,13 @@ var RecordedFeeder = class {
24358
24371
  scrubReadMsWindow = [];
24359
24372
  /** Warm-up runs once per drag, from the playhead the finger went down on. */
24360
24373
  scrubWarmStarted = false;
24374
+ /**
24375
+ * True while the fill window belongs to IDLE mode — started by a seek (a
24376
+ * timeline tap or a scrub commit) rather than by a drag. An idle fill paces
24377
+ * itself ({@link IDLE_WARM_READ_GAP_MS}) and yields to any in-flight seek;
24378
+ * a drag's own warm (`beginScrub`) always takes the window over.
24379
+ */
24380
+ idleWarm = false;
24361
24381
  /** Centre of the fill currently in flight (or last completed). */
24362
24382
  scrubWarmCentreMs = null;
24363
24383
  /** Bumped to abort a fill without aborting the drag tick (`scrubToken`). */
@@ -24602,6 +24622,7 @@ var RecordedFeeder = class {
24602
24622
  bytes: loaded.bytes,
24603
24623
  loadAusMs: Math.round(loadAusMs)
24604
24624
  });
24625
+ this.startIdleWarm(this.cursorMs);
24605
24626
  return;
24606
24627
  }
24607
24628
  if (!stateAnnounced) {
@@ -24638,6 +24659,7 @@ var RecordedFeeder = class {
24638
24659
  },
24639
24660
  resumeAfterPtsMs
24640
24661
  });
24662
+ this.startIdleWarm(this.cursorMs);
24641
24663
  } catch (err) {
24642
24664
  if (!this.disposed && token === this.seekToken) {
24643
24665
  this.stopPositionReports();
@@ -24751,7 +24773,36 @@ var RecordedFeeder = class {
24751
24773
  this.stopPositionReports();
24752
24774
  this.scrubWarmStarted = false;
24753
24775
  this.scrubReadMsWindow = [];
24754
- if (this.cursorMs > 0 && this.deps.profile === SCRUB_WHOLE_SEGMENT_PROFILE) this.startScrubWarm(this.cursorMs, this.scrubToken);
24776
+ if (this.cursorMs > 0 && this.deps.profile === SCRUB_WHOLE_SEGMENT_PROFILE) {
24777
+ this.idleWarm = false;
24778
+ this.startScrubWarm(this.cursorMs, this.scrubToken, { force: true });
24779
+ }
24780
+ }
24781
+ /**
24782
+ * Start (or recentre) the IDLE fill: called after every completed seek —
24783
+ * a timeline tap or a scrub commit — with the landed cursor. The operator is
24784
+ * now LOOKING at that frame; the next gesture almost always starts near it,
24785
+ * and this is the one moment the spindle is not serving the finger. Bounds:
24786
+ * the same session cache budget as the drag warm (48 MB LRU — no new store),
24787
+ * the same {@link SCRUB_WARM_MAX_SEGMENTS} per-window cap, plus the idle
24788
+ * pacing gap. `low`-only for the same reason the drag warm is: a `high`
24789
+ * window would be hundreds of MB of reads for a profile no drag reads.
24790
+ */
24791
+ startIdleWarm(centreMs) {
24792
+ if (this.disposed || this.scrubbing) return;
24793
+ if (centreMs <= 0 || this.deps.profile !== SCRUB_WHOLE_SEGMENT_PROFILE) return;
24794
+ this.idleWarm = true;
24795
+ this.startScrubWarm(centreMs, this.scrubToken, { force: true });
24796
+ }
24797
+ /**
24798
+ * Whether the fill loop generation `dragGen` may keep working. During a drag
24799
+ * only that drag's generation runs (a commit bumps `scrubToken` and the old
24800
+ * walker exits); outside a drag the loop runs exactly while idle warm is on.
24801
+ */
24802
+ warmLoopAlive(dragGen) {
24803
+ if (this.disposed) return false;
24804
+ if (this.scrubbing) return dragGen === this.scrubToken;
24805
+ return this.idleWarm;
24755
24806
  }
24756
24807
  /**
24757
24808
  * Warm the window the drag is about to move through: {@link SCRUB_WARM_BACK_MS}
@@ -24791,19 +24842,29 @@ var RecordedFeeder = class {
24791
24842
  async runScrubFillLoop(dragGen) {
24792
24843
  let lastWorked = -1;
24793
24844
  try {
24794
- while (!this.disposed && this.scrubbing && dragGen === this.scrubToken) {
24845
+ while (this.warmLoopAlive(dragGen)) {
24795
24846
  const gen = this.scrubWarmGen;
24796
24847
  const centre = this.scrubWarmCentreMs;
24797
24848
  if (centre === null) return;
24798
- await this.warmScrubWindow(centre, dragGen, gen, this.scrubWarmBackMs, this.scrubWarmFwdMs);
24849
+ const startedAt = performance.now();
24850
+ const fetched = await this.warmScrubWindow(centre, dragGen, gen, this.scrubWarmBackMs, this.scrubWarmFwdMs);
24799
24851
  lastWorked = gen;
24800
- if (gen === this.scrubWarmGen) return;
24852
+ if (gen === this.scrubWarmGen) {
24853
+ this.deps.onLog?.("scrub-feeder:warm-done", {
24854
+ fillGen: gen,
24855
+ idle: this.idleWarm && !this.scrubbing,
24856
+ fetched,
24857
+ ms: Math.round(performance.now() - startedAt)
24858
+ });
24859
+ if (!this.scrubbing) this.idleWarm = false;
24860
+ return;
24861
+ }
24801
24862
  }
24802
24863
  } finally {
24803
24864
  this.scrubFillLoopActive = false;
24804
- if (!this.disposed && this.scrubbing && dragGen === this.scrubToken && this.scrubWarmCentreMs !== null && this.scrubWarmGen !== lastWorked) {
24865
+ if (!this.disposed && (this.scrubbing || this.idleWarm) && this.scrubWarmCentreMs !== null && this.scrubWarmGen !== lastWorked) {
24805
24866
  this.scrubFillLoopActive = true;
24806
- this.runScrubFillLoop(dragGen);
24867
+ this.runScrubFillLoop(this.scrubToken);
24807
24868
  }
24808
24869
  }
24809
24870
  }
@@ -24828,7 +24889,7 @@ var RecordedFeeder = class {
24828
24889
  }
24829
24890
  async warmScrubWindow(centreMs, dragGen, fillGen, backMs, fwdMs) {
24830
24891
  const spent = await this.warmScrubDirection(centreMs, -1, backMs, 0, dragGen, fillGen);
24831
- await this.warmScrubDirection(centreMs, 1, fwdMs, spent, dragGen, fillGen);
24892
+ return this.warmScrubDirection(centreMs, 1, fwdMs, spent, dragGen, fillGen);
24832
24893
  }
24833
24894
  /**
24834
24895
  * Walk `dir` from `fromMs` until `spanMs` of timeline is warm (or the shared
@@ -24839,7 +24900,7 @@ var RecordedFeeder = class {
24839
24900
  let read = spent;
24840
24901
  let probeMs = fromMs;
24841
24902
  for (let i = 0; i < SCRUB_WARM_MAX_SEGMENTS; i++) {
24842
- if (this.disposed || !this.scrubbing || dragGen !== this.scrubToken) return read;
24903
+ if (!this.warmLoopAlive(dragGen)) return read;
24843
24904
  if (fillGen !== this.scrubWarmGen) return read;
24844
24905
  if (read >= SCRUB_WARM_MAX_SEGMENTS) return read;
24845
24906
  if (Math.abs(probeMs - fromMs) > spanMs) return read;
@@ -24865,19 +24926,27 @@ var RecordedFeeder = class {
24865
24926
  durMs: warm.durMs,
24866
24927
  fetched: false
24867
24928
  };
24929
+ if (this.idleWarm && !this.scrubbing) {
24930
+ await new Promise((r) => setTimeout(r, this.deps.idleWarmGapMs ?? IDLE_WARM_READ_GAP_MS));
24931
+ while (this.inFlightSeekEpochMs !== null) {
24932
+ if (!this.warmLoopAlive(dragGen) || fillGen !== this.scrubWarmGen) return null;
24933
+ await new Promise((r) => setTimeout(r, 20));
24934
+ }
24935
+ if (!this.warmLoopAlive(dragGen) || fillGen !== this.scrubWarmGen) return null;
24936
+ }
24868
24937
  if (!await this.waitForTickReadIdle(fillGen)) return null;
24869
24938
  const loc = await this.withTimeout(this.deps.locate({
24870
24939
  deviceId: this.deps.deviceId,
24871
24940
  profile: this.deps.profile,
24872
24941
  epochMs: probeMs
24873
24942
  }));
24874
- if (this.disposed || !this.scrubbing || dragGen !== this.scrubToken) return null;
24943
+ if (!this.warmLoopAlive(dragGen)) return null;
24875
24944
  if (fillGen !== this.scrubWarmGen) return null;
24876
24945
  if (loc.kind !== "segment") return null;
24877
24946
  if (!await this.waitForTickReadIdle(fillGen)) return null;
24878
24947
  const load = await this.loadScrubFragment(loc, probeMs);
24879
- if (load !== null) this.scrubStats?.recordPrefetchRead(load.readBytes);
24880
- if (this.disposed || !this.scrubbing || dragGen !== this.scrubToken || load === null) return null;
24948
+ if (load !== null && this.scrubbing) this.scrubStats?.recordPrefetchRead(load.readBytes);
24949
+ if (!this.warmLoopAlive(dragGen) || load === null) return null;
24881
24950
  if (fillGen !== this.scrubWarmGen) return null;
24882
24951
  this.scrubCache.put(this.deps.profile, load.seg);
24883
24952
  this.scrubPrefetched.add(load.seg.startMs);
@@ -24894,7 +24963,8 @@ var RecordedFeeder = class {
24894
24963
  async waitForTickReadIdle(fillGen) {
24895
24964
  while (this.scrubTickReadInFlight) {
24896
24965
  await new Promise((r) => setTimeout(r, 4));
24897
- if (this.disposed || !this.scrubbing || fillGen !== this.scrubWarmGen) return false;
24966
+ if (this.disposed || fillGen !== this.scrubWarmGen) return false;
24967
+ if (!this.scrubbing && !this.idleWarm) return false;
24898
24968
  }
24899
24969
  return true;
24900
24970
  }
@@ -26080,6 +26150,7 @@ var RecordedFeeder = class {
26080
26150
  this.seekToken++;
26081
26151
  this.advanceToken++;
26082
26152
  this.scrubbing = false;
26153
+ this.idleWarm = false;
26083
26154
  this.scrubToken++;
26084
26155
  this.scrubSegment = null;
26085
26156
  this.scrubPrevTarget = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-pipeline",
3
- "version": "1.2.122",
3
+ "version": "1.2.124",
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",
@@ -70,8 +70,7 @@
70
70
  "execution": {
71
71
  "placement": "any-node",
72
72
  "heapProfile": "heavy",
73
- "group": "detection",
74
- "maxOldSpaceMb": 0
73
+ "group": "detection"
75
74
  },
76
75
  "capabilities": [
77
76
  {
@@ -104,8 +103,7 @@
104
103
  "execution": {
105
104
  "placement": "any-node",
106
105
  "heapProfile": "heavy",
107
- "group": "detection",
108
- "maxOldSpaceMb": 0
106
+ "group": "detection"
109
107
  },
110
108
  "protected": true,
111
109
  "icon": "assets/icon.svg",
@@ -121,8 +119,7 @@
121
119
  "execution": {
122
120
  "placement": "any-node",
123
121
  "heapProfile": "heavy",
124
- "group": "detection",
125
- "maxOldSpaceMb": 0
122
+ "group": "detection"
126
123
  },
127
124
  "capabilities": [
128
125
  {
@@ -149,8 +146,7 @@
149
146
  "entry": "./dist/audio-analyzer/index.js",
150
147
  "execution": {
151
148
  "placement": "any-node",
152
- "heapProfile": "heavy",
153
- "maxOldSpaceMb": 0
149
+ "heapProfile": "heavy"
154
150
  },
155
151
  "capabilities": [
156
152
  {
@@ -172,8 +168,7 @@
172
168
  "entry": "./dist/stream-broker/index.js",
173
169
  "execution": {
174
170
  "placement": "any-node",
175
- "heapProfile": "heavy",
176
- "maxOldSpaceMb": 0
171
+ "heapProfile": "heavy"
177
172
  },
178
173
  "capabilities": [
179
174
  {
@@ -203,7 +198,7 @@
203
198
  "execution": {
204
199
  "placement": "any-node",
205
200
  "heapProfile": "heavy",
206
- "maxOldSpaceMb": 0
201
+ "maxOldSpaceMb": 3072
207
202
  },
208
203
  "capabilities": [
209
204
  {