@pond-ts/react 0.16.1 → 0.17.0

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.
Files changed (2) hide show
  1. package/CHANGELOG.md +105 -16
  2. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -7,10 +7,98 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
7
7
  file covers both packages. Pre-1.0: minor bumps may include new features and
8
8
  type-level changes; patch bumps are strictly additive.
9
9
 
10
- [Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.16.1...HEAD
10
+ [Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.17.0...HEAD
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [0.17.0] — 2026-05-08
15
+
16
+ `sample({...})` operator wave: bounded-memory stream thinning, surfaced
17
+ by the gRPC experiment's M3.5 finish-line work
18
+ ([friction note](https://github.com/pjm17971/pond-grpc-experiment/blob/main/friction-notes/rfcs/bounded-memory-sampling.md)
19
+ with measured firehose numbers). Decouples downstream baseline window
20
+ length from event rate — at firehose rates × stride 10, `sd / sqrt(N)`
21
+ standard error stays well below per-event noise while a 5-minute
22
+ baseline that wouldn't fit in a Node heap un-sampled does at
23
+ stride 10. PR [#129](https://github.com/pjm17971/pond-ts/pull/129).
24
+
25
+ ### Added
26
+
27
+ - **`series.sample({ stride | reservoir })`** on `TimeSeries` and
28
+ `PartitionedTimeSeries` — single-pass thinning that keeps the
29
+ `TimeSeries<S>` schema. Stride is deterministic 1-in-N
30
+ (`{ stride: N }`); reservoir is random K-of-N via single-pass
31
+ [Vitter's Algorithm R](https://en.wikipedia.org/wiki/Reservoir_sampling#Simple:_Algorithm_R)
32
+ (`{ reservoir: { size: K } }`), sorted by key on output to preserve
33
+ the chronological invariant. The canonical visualization shape:
34
+
35
+ ```ts
36
+ series.sample({ reservoir: { size: 500 } }).toRows();
37
+ ```
38
+
39
+ 500 uncorrelated points drawn uniformly from the source — no
40
+ `aggregate(seq, ...)` grid collapse, no regular-spacing artifact,
41
+ fixed point count regardless of source size. Per-partition state on
42
+ `PartitionedTimeSeries.sample(...)` — each partition gets its own
43
+ K-event reservoir or stride counter.
44
+
45
+ - **`live.sample({ stride })`** on `LiveSeries`, `LiveView`,
46
+ `LivePartitionedSeries`, `LivePartitionedView` — closure-captured
47
+ counter inside a `LiveView<S>`, so the chainable surface (`filter`,
48
+ `rolling`, `reduce`, `select`, `map`, `diff`, `rate`, `cumulative`,
49
+ `fill`) is immediately available downstream of the sample. The
50
+ bounded-memory firehose pattern:
51
+
52
+ ```ts
53
+ live.partitionBy('host').sample({ stride: 10 }).rolling('5m', mapping);
54
+ ```
55
+
56
+ Each host's stream is thinned 1-in-10 before flowing into a per-host
57
+ 5m rolling window. `live.stats().ingested` and `live.on('batch', cb)`
58
+ are upstream of any `.sample(...)` op — they continue counting true
59
+ throughput; only consumers downstream see the thinned stream.
60
+
61
+ - **Sampling docs page** at
62
+ [`pond-ts/transforms/sampling`](https://pjm17971.github.io/pond-ts/docs/pond-ts/transforms/sampling/)
63
+ covering when-to-use-which decision table, both strategies, the
64
+ visualization shape, multi-entity considerations, and a forward-link
65
+ to the live counterpart. New `## Sampling: bounded-memory thinning`
66
+ section in
67
+ [Live transforms](https://pjm17971.github.io/pond-ts/docs/pond-ts/live/live-transforms#sampling).
68
+
69
+ ### Deferred
70
+
71
+ - **Live-side reservoir sampling** is queued for v0.18.0+. Algorithm R's
72
+ random-slot replacement produces non-prefix evictions, but the existing
73
+ live-eviction protocol (`'evict'` event + cutoff-based mirroring in
74
+ `LiveView`) assumes prefix evictions only. Bridging needs an exact-
75
+ removal eviction channel — arriving with the streaming RFC's
76
+ `LiveChange` model (Phase 4.5 milestone A). For visualization-shaped
77
+ reservoir today, materialize via `live.toTimeSeries().sample({ reservoir })`.
78
+
79
+ ### Notes
80
+
81
+ - **Multi-entity bias trap** is documented in JSDoc on the pre-partition
82
+ sites (`LiveSeries.sample`, `LiveView.sample`) with the
83
+ `partitionBy(...).sample(...)` recommendation, matching the existing
84
+ convention for `rolling` / `aggregate` / `fill` / `diff` / `rate` /
85
+ `cumulative` / `pctChange` / `reduce`. An earlier iteration of #129
86
+ shipped a type-level `unsafeGlobal: true` token; pulled during review
87
+ for consistency with how every other stateful live operator handles
88
+ the same multi-entity consideration. Token-of-the-week novelty was
89
+ the wrong shape; the doc warning is the same answer the other
90
+ operators already give.
91
+
92
+ - **Legacy `rolling.sample(seq)` doc references removed.** Pre-v0.12
93
+ pond exposed `LiveRollingAggregation.sample(sequence)` as a separate
94
+ method (deleted in v0.12.0, replaced by `Trigger.every`). Active doc
95
+ references in `pond-ts/live/triggering.mdx`,
96
+ `pond-ts/transforms/alignment.mdx`, `pond-ts/transforms/rolling.mdx`,
97
+ and `pond-ts/live/live-transforms.mdx` removed to eliminate the
98
+ naming-collision confusion now that `series.sample({ stride | reservoir })`
99
+ is a real but completely unrelated operator. Historical record
100
+ preserved in PLAN.md, the v0.11.8 CHANGELOG entry, and the triggers RFC.
101
+
14
102
  ## [0.16.1] — 2026-05-06
15
103
 
16
104
  Patch wave addressing one ergonomic gap surfaced by the gRPC
@@ -47,7 +135,7 @@ plus the v0.16.0 docs deploy that broke since v0.15.2.
47
135
  - **Docs deploy workflow unblocked**
48
136
  ([#126](https://github.com/pjm17971/pond-ts/pull/126)). Has
49
137
  been failing since v0.15.2 with `Cannot find name
50
- 'queueMicrotask'` — TypeDoc runs the same tsconfig as the
138
+ 'queueMicrotask'` — TypeDoc runs the same tsconfig as the
51
139
  npm-publish path but from a different cwd, where `@types/node`
52
140
  doesn't resolve. Fixed via a one-line ambient declaration in
53
141
  `LiveReduce.ts`. No runtime change; `queueMicrotask` is still
@@ -101,17 +189,17 @@ narrowings.
101
189
  `eventRate()`.
102
190
  - **`stats()` accessor on every live accumulator/series.** Per-class
103
191
  shapes, all returning a plain record (cumulative integer counters
104
- + current-state fields):
105
-
106
- | Class | Shape |
107
- |---|---|
108
- | LiveSeries | `{ ingested, evicted, rejected, length, earliestTs?, latestTs? }` |
109
- | LiveRollingAggregation | `{ eventsObserved, evictions, emissions, windowSize }` |
110
- | LiveFusedRolling | `{ eventsObserved, evictions, emissions, windowSize, windowsCount }` |
111
- | LiveAggregation | `{ eventsObserved, bucketsClosed, openBuckets, openBucketStart? }` |
112
- | LiveReduce | `{ eventsObserved, evictions, emissions, bufferSize }` |
113
- | LivePartitionedSeries | `{ partitions, eventsRouted }` |
114
- | LivePartitionedSyncRolling | `{ partitions, eventsObserved, emissions, windowSize }` |
192
+ - current-state fields):
193
+
194
+ | Class | Shape |
195
+ | --------------------------- | --------------------------------------------------------------------- |
196
+ | LiveSeries | `{ ingested, evicted, rejected, length, earliestTs?, latestTs? }` |
197
+ | LiveRollingAggregation | `{ eventsObserved, evictions, emissions, windowSize }` |
198
+ | LiveFusedRolling | `{ eventsObserved, evictions, emissions, windowSize, windowsCount }` |
199
+ | LiveAggregation | `{ eventsObserved, bucketsClosed, openBuckets, openBucketStart? }` |
200
+ | LiveReduce | `{ eventsObserved, evictions, emissions, bufferSize }` |
201
+ | LivePartitionedSeries | `{ partitions, eventsRouted }` |
202
+ | LivePartitionedSyncRolling | `{ partitions, eventsObserved, emissions, windowSize }` |
115
203
  | LivePartitionedFusedRolling | `{ partitions, eventsObserved, emissions, windowSize, windowsCount }` |
116
204
 
117
205
  Per-event cost: ~1-3 integer increments in already-existing
@@ -152,7 +240,7 @@ narrowings.
152
240
 
153
241
  - **`KeyLike` type** exported from the package root (re-exported
154
242
  from `TimeSeries`). Accepts `EventKey | TimestampInput |
155
- TimeRangeInput | IntervalInput`; normalised by the new query
243
+ TimeRangeInput | IntervalInput`; normalised by the new query
156
244
  primitives.
157
245
 
158
246
  - **`DurationLiteral` and `DurationUnit` types** extracted from
@@ -186,8 +274,8 @@ narrowings.
186
274
  on). Sane transforms (data-only maps, monotonic time-shifts)
187
275
  unaffected.
188
276
  - **`LiveAggregationOptions.grace`** type tightened from
189
- `DurationInput | \`${number}${unit}\`` (redundant union) to
190
- just `DurationInput`. No behavioral change.
277
+ `DurationInput | \`${number}${unit}\``(redundant union) to
278
+ just`DurationInput`. No behavioral change.
191
279
 
192
280
  ### Notes
193
281
 
@@ -297,6 +385,7 @@ compaction); any downstream code reading `#entries` directly would
297
385
  break, but those fields are private. Public APIs and types are
298
386
  unchanged.
299
387
 
388
+ [0.17.0]: https://github.com/pjm17971/pond-ts/compare/v0.16.1...v0.17.0
300
389
  [0.16.1]: https://github.com/pjm17971/pond-ts/compare/v0.16.0...v0.16.1
301
390
  [0.16.0]: https://github.com/pjm17971/pond-ts/compare/v0.15.2...v0.16.0
302
391
  [0.15.2]: https://github.com/pjm17971/pond-ts/compare/v0.15.1...v0.15.2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pond-ts/react",
3
- "version": "0.16.1",
3
+ "version": "0.17.0",
4
4
  "description": "React hooks for pond-ts live time series",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -31,7 +31,7 @@
31
31
  "test:runtime": "vitest run"
32
32
  },
33
33
  "peerDependencies": {
34
- "pond-ts": "^0.16.0",
34
+ "pond-ts": "^0.17.0",
35
35
  "react": "^18.0.0 || ^19.0.0"
36
36
  },
37
37
  "devDependencies": {