@pond-ts/react 0.13.1 → 0.14.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 +159 -1
  2. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -7,10 +7,168 @@ 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.13.1...HEAD
10
+ [Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.14.0...HEAD
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [0.14.0] — 2026-05-01
15
+
16
+ Two perf wins driven by the gRPC experiment's V3 profiling pass
17
+ (PR #14 on `pond-grpc-experiment`): `estimateEventBytes` at 6.2%
18
+ self time and the partition router's `Event → row → Event`
19
+ round-trip (combined ~7% in `#validateRow` + `Event` constructor
20
+ re-allocations). Both root-caused, both fixed.
21
+
22
+ Benchmark deltas on `scripts/perf-live-partitioned.mjs`
23
+ (100k events, median ms):
24
+
25
+ | Scenario | Before | After | Δ |
26
+ | ------------------------------------- | -----: | -----: | ------: |
27
+ | bare `LiveSeries.push` | 41.11 | 30.08 | **−27%** |
28
+ | `partitionBy('host')` routing (10) | 83.14 | 39.10 | **−53%** |
29
+ | `partitionBy + collect()` | 124.82 | 49.96 | **−60%** |
30
+ | `partitionBy + apply(fill)` | 120.53 | 49.64 | **−59%** |
31
+ | `partitionBy('host')` routing (1000) | 105.92 | 43.23 | **−59%** |
32
+
33
+ The bare-push delta is from the byte-estimate removal; the
34
+ partition-routing deltas are from the trusted-pipeline path that
35
+ skips `Event → row → Event` reconstruction at every routing hop.
36
+
37
+ ### Removed (breaking, pre-1.0)
38
+
39
+ - **`retention.maxBytes`** option on `LiveSeriesOptions`. Speculative
40
+ feature from pre-v0.10 that no real user has reached for. Use
41
+ `retention.maxEvents` for count-based caps; `maxBytes` was
42
+ approximate (rough per-event byte estimate) and the imprecision
43
+ meant it was rarely used as designed.
44
+
45
+ Migration: replace `{ retention: { maxBytes: N } }` with
46
+ `{ retention: { maxEvents: M } }` where M is your desired
47
+ upper bound on event count.
48
+
49
+ ### Changed
50
+
51
+ - **`estimateEventBytes` and the `#byteEstimate` accumulator
52
+ removed** from `LiveSeries`. Closes the 6.2% per-push self-time
53
+ line the gRPC experiment surfaced. Bare push is now ~27% faster
54
+ for the typical case where `maxBytes` was never set.
55
+
56
+ - **Partition router uses a trusted-pipeline fast path.**
57
+ `LivePartitionedSeries.#routeEvent`, `collect()`, and `apply()`
58
+ previously round-tripped `Event → row → Event` at every routing
59
+ hop — re-validating and re-allocating Events that the source
60
+ pipeline had already constructed. New `_pushTrustedEvents` method
61
+ on `LiveSeries` accepts pre-validated Event references (under a
62
+ schema-identity contract; only used internally where the source
63
+ and target schemas are guaranteed identical). Closes the ~7%
64
+ combined self-time line in `#validateRow` (×2) and `Event`
65
+ constructor (×2) that the gRPC profile flagged.
66
+
67
+ Trusted-pipeline applies to: the source-to-partition route, the
68
+ per-partition replay-on-construct prefix, the unified-buffer
69
+ `collect()` subscriber, and `apply()`'s factory-output forwarding.
70
+ All four sites had identical schemas at both ends — the trust
71
+ contract holds without runtime re-checking.
72
+
73
+ `_pushTrustedEvents` is `@internal` and not exported from the
74
+ public type surface. Reach for `pushMany` from any external
75
+ context; the trusted variant skips schema validation and is
76
+ only safe for pond's own internal pipelines.
77
+
78
+ ### Tests
79
+
80
+ - 4 new tests in `test/LiveSeries.test.ts` for the trusted-pipeline
81
+ path: insertion without re-validation, listener fan-out and
82
+ retention behaviour, ordering enforcement (strict still rejects
83
+ out-of-order on the trusted path — the trust contract is only
84
+ about validation/allocation, not insertion ordering), empty-array
85
+ no-op.
86
+ - Removed the `retention: maxBytes` describe block in
87
+ `test/LiveSeries.test.ts` and the `forwards retention.maxBytes`
88
+ assertion in `test/LiveSeries.snapshot-append.test.ts`.
89
+ - Total core tests: 1072 (was 1070; +4 new for the trusted path,
90
+ −2 for the removed maxBytes assertions).
91
+
92
+ ### Docs
93
+
94
+ - `live-series.mdx`: retention table and example trimmed to
95
+ `maxEvents` + `maxAge` only. Removed the byte-estimate prose.
96
+
97
+ [0.14.0]: https://github.com/pjm17971/pond-ts/compare/v0.13.2...v0.14.0
98
+
99
+ ## [0.13.2] — 2026-05-01
100
+
101
+ Strictly additive over v0.13.1. Adds `Trigger.count(n)` per the
102
+ second wave of Codex feedback after webapp-telemetry adoption. Use
103
+ case: "very hot metrics like row stale times or handler payload
104
+ sizes where event-time boundaries may lag during bursts, but
105
+ per-event is too noisy."
106
+
107
+ ### Added
108
+
109
+ - **`Trigger.count(n)`** — third trigger primitive alongside
110
+ `Trigger.event()` and `Trigger.clock(seq)` /
111
+ `Trigger.every(duration)`. Emits one rolling-window snapshot
112
+ every `n` source events, with the counter resetting on each fire
113
+ (so "events since the last emission," not "every Nth event modulo
114
+ the input"):
115
+
116
+ ```ts
117
+ const rolling = timings.rolling(
118
+ '5m',
119
+ { latency: 'p95' },
120
+ { trigger: Trigger.count(1000) },
121
+ );
122
+ ```
123
+
124
+ - **Data-driven** — counter only advances on event ingestion, no
125
+ `setTimeout` inside the library. The first emission fires on
126
+ the `n`th event, not the first.
127
+ - **Per-partition** — when applied via `partitionBy(...).rolling(...)`,
128
+ each partition counts independently. Count does not synchronise
129
+ emission across partitions; use `Trigger.clock` for that.
130
+ - **Rejects non-positive integers** — `Trigger.count(0)`,
131
+ `Trigger.count(-1)`, `Trigger.count(1.5)`, and `Trigger.count(NaN)`
132
+ throw at construction with a clear error.
133
+
134
+ ### Changed
135
+
136
+ - **Trigger taxonomy expanded.** `Trigger` union is now
137
+ `EventTrigger | ClockTrigger | CountTrigger`. Per-partition
138
+ rolling overload widened to accept count triggers and route them
139
+ to the `LivePartitionedView` per-partition path (not the synced
140
+ rolling — count semantics across partitions are ambiguous and
141
+ there's no killer use case for either choice yet).
142
+
143
+ ### Docs
144
+
145
+ - `live-transforms.mdx`: trigger section now lists all three
146
+ primitives up front with a dedicated subsection on count
147
+ semantics. JSDoc on `LiveRollingAggregation.trigger` updated to
148
+ mention count.
149
+ - PLAN.md: trigger-taxonomy expansion RFC sketch captured —
150
+ documents the shipped `count` plus deferred decisions on `idle`
151
+ (the wall-clock crossing, requires its own RFC), `any` (composite,
152
+ ships after singletons exist), and `threshold` / `manual`
153
+ (declined / deferred as misclassified or sugar over existing
154
+ primitives).
155
+
156
+ ### Tests
157
+
158
+ - 7 new tests in `test/Triggers.test.ts`:
159
+ - `Trigger.count(n)` shape and freeze
160
+ - Non-positive integer rejection (zero, negative, fractional, NaN)
161
+ - Emission cadence: snapshots every Nth event with correct
162
+ rolling-window values
163
+ - `Trigger.count(1)` behavioural equivalence to `Trigger.event()`
164
+ - No emission during quiet periods (data-driven)
165
+ - `rolling.value()` independent of trigger
166
+ - Per-partition independent counting via
167
+ `partitionBy().rolling(..., { trigger: Trigger.count(2) })`
168
+ - Total core tests: 1070 (was 1063).
169
+
170
+ [0.13.2]: https://github.com/pjm17971/pond-ts/compare/v0.13.1...v0.13.2
171
+
14
172
  ## [0.13.1] — 2026-05-01
15
173
 
16
174
  Strictly additive over v0.13.0. Adds a sugar factory on `Trigger`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pond-ts/react",
3
- "version": "0.13.1",
3
+ "version": "0.14.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.13.0",
34
+ "pond-ts": "^0.14.0",
35
35
  "react": "^18.0.0 || ^19.0.0"
36
36
  },
37
37
  "devDependencies": {