@pond-ts/react 0.11.8 → 0.12.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.
- package/CHANGELOG.md +135 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,10 +7,143 @@ 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.
|
|
10
|
+
[Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.12.0...HEAD
|
|
11
11
|
|
|
12
12
|
## [Unreleased]
|
|
13
13
|
|
|
14
|
+
## [0.12.0] — 2026-05-01
|
|
15
|
+
|
|
16
|
+
The "triggers" release. Major redesign of how live accumulators
|
|
17
|
+
control emission cadence — `Trigger` is now a first-class concept
|
|
18
|
+
shaped by two converging real-world use cases (synchronised
|
|
19
|
+
partitioned tick aggregation in the gRPC pipeline experiment,
|
|
20
|
+
sequence-sampled rolling in webapp telemetry).
|
|
21
|
+
|
|
22
|
+
Two correctness audits before publish: a Layer 2 Claude review
|
|
23
|
+
(column collision, dispose, late-spawn, peer-dep) and a Codex
|
|
24
|
+
adversarial review (quiet-partition stale samples, pre-existing
|
|
25
|
+
data replay at construction, spawn-listener cleanup). All findings
|
|
26
|
+
fixed and pinned with regression tests. 1039 / 1039 tests pass.
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- **Trigger as a first-class concept.** A new `Trigger` factory
|
|
31
|
+
exposed at the package root lets `LiveRollingAggregation` switch
|
|
32
|
+
emission cadence without changing any other shape:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { LiveSeries, Sequence, Trigger } from 'pond-ts';
|
|
36
|
+
|
|
37
|
+
// Webapp telemetry: rolling 1m p95, emit on every 30 s of event-time
|
|
38
|
+
const rolling = timings.rolling(
|
|
39
|
+
'1m',
|
|
40
|
+
{ latency: 'p95' },
|
|
41
|
+
{ trigger: Trigger.clock(Sequence.every('30s')) },
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
rolling.on('event', (e) =>
|
|
45
|
+
fetch('/api/telemetry', { method: 'POST', body: JSON.stringify(e.data()) }),
|
|
46
|
+
);
|
|
47
|
+
rolling.value(); // current rolling-window snapshot, independent of trigger
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Two trigger variants in this release:
|
|
51
|
+
- **`Trigger.event()`** — per-event emission. Default; the historical
|
|
52
|
+
behavior of `LiveRollingAggregation` when no trigger is specified.
|
|
53
|
+
- **`Trigger.clock(sequence)`** — sequence-triggered emission. One
|
|
54
|
+
snapshot fires when a source event crosses an epoch-aligned
|
|
55
|
+
boundary of the (fixed-step) `Sequence`. Output keyed at boundary
|
|
56
|
+
instants. Calendar sequences are rejected upfront.
|
|
57
|
+
|
|
58
|
+
Future variants (`Trigger.count(n)`, custom predicates, compound
|
|
59
|
+
triggers) are reserved but not yet shipped.
|
|
60
|
+
|
|
61
|
+
- **Synchronised partitioned rolling.** `LivePartitionedSeries.rolling`
|
|
62
|
+
now accepts a clock trigger. The output is a
|
|
63
|
+
`LiveSource<RowSchema>` whose schema is `[time, <partitionColumn>,
|
|
64
|
+
...mappingColumns]`; on every boundary crossing, one event fires
|
|
65
|
+
per known partition, all sharing the same boundary timestamp.
|
|
66
|
+
Synchronised across partitions by construction (the bucket index is
|
|
67
|
+
shared, not per-partition).
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
// Dashboard tick aggregation: 100 hosts, 200ms cadence
|
|
71
|
+
const ticks = live
|
|
72
|
+
.partitionBy('host')
|
|
73
|
+
.rolling(
|
|
74
|
+
'1m',
|
|
75
|
+
{ cpu: 'avg' },
|
|
76
|
+
{ trigger: Trigger.clock(Sequence.every('200ms')) },
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
ticks.on('event', (e) => {
|
|
80
|
+
// e.begin() === <boundary timestamp>, same for every host this tick
|
|
81
|
+
// e.get('host') === 'api-1' | 'api-2' | …
|
|
82
|
+
// e.get('cpu') === <rolling avg for that host>
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Restricted to direct-after-`partitionBy` in this release: chained
|
|
87
|
+
sugar (`partitionBy(c).fill(...).rolling(...)`) rejects clock
|
|
88
|
+
triggers with a clear error. Lifts in a future release once a real
|
|
89
|
+
use case appears.
|
|
90
|
+
|
|
91
|
+
Closes the gRPC experiment's M3.5 dashboard friction note (the
|
|
92
|
+
hand-rolled `HostAggregator` becomes ~10 lines of pond code).
|
|
93
|
+
|
|
94
|
+
### Removed (breaking — pre-1.0)
|
|
95
|
+
|
|
96
|
+
- **`LiveSequenceRollingAggregation`** class deleted. Its capability
|
|
97
|
+
is preserved as `LiveRollingAggregation` with
|
|
98
|
+
`{ trigger: Trigger.clock(sequence) }`. Migration: replace
|
|
99
|
+
`live.rolling('1m', m).sample(seq)` with
|
|
100
|
+
`live.rolling('1m', m, { trigger: Trigger.clock(seq) })`. Single
|
|
101
|
+
rolling object now serves both backend reporting and direct
|
|
102
|
+
`.value()` reads (no separate sampler reference).
|
|
103
|
+
- **`.sample(sequence)`** method removed from `LiveRollingAggregation`.
|
|
104
|
+
Use the trigger option above.
|
|
105
|
+
|
|
106
|
+
### Changed
|
|
107
|
+
|
|
108
|
+
- **`LiveRollingOptions`** gains an optional `trigger?: Trigger`
|
|
109
|
+
field. Default behavior (no `trigger` specified) is unchanged from
|
|
110
|
+
v0.11.x — per-event emission. Backward compatible for everyone
|
|
111
|
+
who didn't use `.sample()`.
|
|
112
|
+
|
|
113
|
+
### Performance
|
|
114
|
+
|
|
115
|
+
- New benchmark `scripts/perf-triggers.mjs` covers both
|
|
116
|
+
non-partitioned and synchronised partitioned cases. Headline numbers
|
|
117
|
+
on a current MacBook Pro:
|
|
118
|
+
- Non-partitioned: clock(30s) ~50% faster than per-event baseline
|
|
119
|
+
(emission is rarer); clock(1s) similar.
|
|
120
|
+
- Synchronised partitioned (100 hosts, 30k events at realistic
|
|
121
|
+
rates): ~300 ns/emission at 200ms cadence; +205% over per-
|
|
122
|
+
partition baseline at the high end. Well within budget for the
|
|
123
|
+
motivating dashboard use case.
|
|
124
|
+
|
|
125
|
+
### Notes
|
|
126
|
+
|
|
127
|
+
- **`docs/rfcs/triggers.md`** captures the full design rationale,
|
|
128
|
+
the four sign-off questions, and the migration plan. Read this if
|
|
129
|
+
you want the "why this shape" context.
|
|
130
|
+
|
|
131
|
+
### Known limitations
|
|
132
|
+
|
|
133
|
+
- **Synchronised partitioned rolling output type is loose** —
|
|
134
|
+
`LiveSource<SeriesSchema>` rather than a schema-narrowed shape.
|
|
135
|
+
Runtime schema is correct; only static types widen. Tightening is
|
|
136
|
+
queued for a follow-up release.
|
|
137
|
+
- **Synchronised partitioned rolling rejects column-name collisions**
|
|
138
|
+
between the partition column and any reducer-output column at
|
|
139
|
+
construction (e.g. `partitionBy('cpu').rolling('1m', { cpu: 'avg' }, { trigger })`).
|
|
140
|
+
Rename the reducer output (once `AggregateOutputMap` lands on live
|
|
141
|
+
rolling) or partition by a different column.
|
|
142
|
+
- **Late-spawn partitions only appear in ticks after their first event
|
|
143
|
+
arrives.** A partition unknown to the sync source contributes no
|
|
144
|
+
row to the current tick. Use `partitionBy(col, { groups: [...] })`
|
|
145
|
+
to eagerly include partitions from construction.
|
|
146
|
+
|
|
14
147
|
## [0.11.8] — 2026-04-30
|
|
15
148
|
|
|
16
149
|
### Added
|
|
@@ -61,6 +194,7 @@ type-level changes; patch bumps are strictly additive.
|
|
|
61
194
|
frontend-collection → backend-summary pattern using `.sample()`,
|
|
62
195
|
plus the React in-app display via `useLiveQuery`.
|
|
63
196
|
|
|
197
|
+
[0.12.0]: https://github.com/pjm17971/pond-ts/compare/v0.11.8...v0.12.0
|
|
64
198
|
[0.11.8]: https://github.com/pjm17971/pond-ts/compare/v0.11.7...v0.11.8
|
|
65
199
|
|
|
66
200
|
## [0.11.7] — 2026-04-29
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pond-ts/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.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.
|
|
34
|
+
"pond-ts": "^0.12.0",
|
|
35
35
|
"react": "^18.0.0 || ^19.0.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|