pond-ts 0.16.1 → 0.17.1
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 +178 -16
- package/README.md +142 -382
- package/dist/LivePartitionedSeries.d.ts +64 -12
- package/dist/LivePartitionedSeries.d.ts.map +1 -1
- package/dist/LivePartitionedSeries.js +91 -19
- package/dist/LivePartitionedSeries.js.map +1 -1
- package/dist/LiveSeries.d.ts +51 -0
- package/dist/LiveSeries.d.ts.map +1 -1
- package/dist/LiveSeries.js +95 -2
- package/dist/LiveSeries.js.map +1 -1
- package/dist/LiveView.d.ts +27 -0
- package/dist/LiveView.d.ts.map +1 -1
- package/dist/LiveView.js +37 -0
- package/dist/LiveView.js.map +1 -1
- package/dist/PartitionedTimeSeries.d.ts +8 -0
- package/dist/PartitionedTimeSeries.d.ts.map +1 -1
- package/dist/PartitionedTimeSeries.js +9 -0
- package/dist/PartitionedTimeSeries.js.map +1 -1
- package/dist/TimeSeries.d.ts +19 -0
- package/dist/TimeSeries.d.ts.map +1 -1
- package/dist/TimeSeries.js +52 -0
- package/dist/TimeSeries.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/sample.d.ts +90 -0
- package/dist/sample.d.ts.map +1 -0
- package/dist/sample.js +21 -0
- package/dist/sample.js.map +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,10 +7,170 @@ 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.17.1...HEAD
|
|
11
11
|
|
|
12
12
|
## [Unreleased]
|
|
13
13
|
|
|
14
|
+
## [0.17.1] — 2026-05-11
|
|
15
|
+
|
|
16
|
+
Bug fix: `live.partitionBy()` now default-inherits `ordering`,
|
|
17
|
+
`graceWindow`, and `retention` from the source `LiveSeries`. Surfaced
|
|
18
|
+
by the gRPC experiment's
|
|
19
|
+
[M4 late-data friction note](https://github.com/pjm17971/pond-grpc-experiment/blob/main/friction-notes/M4.md),
|
|
20
|
+
which measured `99.5%` of late events crashing the partition router
|
|
21
|
+
under `source = LiveSeries({ ordering: 'reorder', graceWindow })`
|
|
22
|
+
followed by bare `partitionBy('host')`.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **`LiveSeries.partitionBy(by)` default-inherits source config**
|
|
27
|
+
([#TBD](https://github.com/pjm17971/pond-ts/pull/TBD)). Pre-fix,
|
|
28
|
+
per-partition sub-series were constructed with default
|
|
29
|
+
`ordering: 'strict'` regardless of source mode. Under a `'reorder'`
|
|
30
|
+
source, late events that the source accepted via its reorder path
|
|
31
|
+
were routed into the partition's `#insert` and threw with a
|
|
32
|
+
strict-mode error; the throw propagated back through the source's
|
|
33
|
+
listener fan-out into `live.push()`.
|
|
34
|
+
|
|
35
|
+
Post-fix, `partitionBy(by)` defaults each per-partition sub-series'
|
|
36
|
+
`ordering`, `graceWindow`, and `retention` to the source's values.
|
|
37
|
+
Explicit options on `partitionBy(by, { ordering, ... })` override
|
|
38
|
+
per-field. `graceWindow` inheritance is gated on effective ordering
|
|
39
|
+
being `'reorder'` (LiveSeries rejects strict + graceWindow combos).
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
// Pre-0.17.1: crashed the partition router
|
|
43
|
+
const live = new LiveSeries({
|
|
44
|
+
name: 'metrics',
|
|
45
|
+
schema,
|
|
46
|
+
ordering: 'reorder',
|
|
47
|
+
graceWindow: '30s',
|
|
48
|
+
});
|
|
49
|
+
live.partitionBy('host'); // ← partition was strict regardless
|
|
50
|
+
|
|
51
|
+
// Post-0.17.1: partitions inherit reorder + 30s grace; late events
|
|
52
|
+
// accept correctly via the reorder path.
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Existing callers with explicit `partitionBy(by, { ordering, ... })`:
|
|
56
|
+
unchanged. Existing callers on `'strict'` sources: unchanged.
|
|
57
|
+
Existing callers on `'reorder'` sources with bare `partitionBy`:
|
|
58
|
+
the previously-thrown late events now accept correctly — bug fix,
|
|
59
|
+
not a behavior change anyone could rely on.
|
|
60
|
+
|
|
61
|
+
- **`collect()` and `apply()` on `LivePartitionedSeries` default-
|
|
62
|
+
inherit `ordering` and `graceWindow`** from the partitioned series
|
|
63
|
+
(which inherits from source). Pre-fix, the unified buffer defaulted
|
|
64
|
+
to `'strict'`, so partition fan-in on a `'reorder'` source could
|
|
65
|
+
deliver events out-of-order to a strict unified buffer and throw.
|
|
66
|
+
Retention stays caller-explicit on these per the existing append-
|
|
67
|
+
only fan-in semantics.
|
|
68
|
+
|
|
69
|
+
### Notes
|
|
70
|
+
|
|
71
|
+
- **Six regression tests pin the new defaults** in
|
|
72
|
+
`LivePartitionedSeries.test.ts`: inherited ordering, inherited
|
|
73
|
+
graceWindow within reorder, inherited retention on partitions,
|
|
74
|
+
explicit override of inheritance, strict-source no-change, and the
|
|
75
|
+
edge case where overriding ordering to strict suppresses graceWindow
|
|
76
|
+
inheritance. `collect()` inheritance pinned separately.
|
|
77
|
+
- The gRPC experiment's M4 friction note also surfaced milestone B
|
|
78
|
+
(capability-based late repair) as **driver-light by empirical test**
|
|
79
|
+
after Codex's adversarial pass caught simulator RNG leakage across
|
|
80
|
+
A/B legs. Drift signal collapsed to within noise on every host once
|
|
81
|
+
all randomness sources were seeded — milestone B's library design
|
|
82
|
+
stays sound, but the gRPC experiment's measurement style (last-tick
|
|
83
|
+
`.value()` reads) doesn't surface its payoff. Milestone B sequencing
|
|
84
|
+
updated in PLAN.md to reflect this finding.
|
|
85
|
+
|
|
86
|
+
## [0.17.0] — 2026-05-08
|
|
87
|
+
|
|
88
|
+
`sample({...})` operator wave: bounded-memory stream thinning, surfaced
|
|
89
|
+
by the gRPC experiment's M3.5 finish-line work
|
|
90
|
+
([friction note](https://github.com/pjm17971/pond-grpc-experiment/blob/main/friction-notes/rfcs/bounded-memory-sampling.md)
|
|
91
|
+
with measured firehose numbers). Decouples downstream baseline window
|
|
92
|
+
length from event rate — at firehose rates × stride 10, `sd / sqrt(N)`
|
|
93
|
+
standard error stays well below per-event noise while a 5-minute
|
|
94
|
+
baseline that wouldn't fit in a Node heap un-sampled does at
|
|
95
|
+
stride 10. PR [#129](https://github.com/pjm17971/pond-ts/pull/129).
|
|
96
|
+
|
|
97
|
+
### Added
|
|
98
|
+
|
|
99
|
+
- **`series.sample({ stride | reservoir })`** on `TimeSeries` and
|
|
100
|
+
`PartitionedTimeSeries` — single-pass thinning that keeps the
|
|
101
|
+
`TimeSeries<S>` schema. Stride is deterministic 1-in-N
|
|
102
|
+
(`{ stride: N }`); reservoir is random K-of-N via single-pass
|
|
103
|
+
[Vitter's Algorithm R](https://en.wikipedia.org/wiki/Reservoir_sampling#Simple:_Algorithm_R)
|
|
104
|
+
(`{ reservoir: { size: K } }`), sorted by key on output to preserve
|
|
105
|
+
the chronological invariant. The canonical visualization shape:
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
series.sample({ reservoir: { size: 500 } }).toRows();
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
500 uncorrelated points drawn uniformly from the source — no
|
|
112
|
+
`aggregate(seq, ...)` grid collapse, no regular-spacing artifact,
|
|
113
|
+
fixed point count regardless of source size. Per-partition state on
|
|
114
|
+
`PartitionedTimeSeries.sample(...)` — each partition gets its own
|
|
115
|
+
K-event reservoir or stride counter.
|
|
116
|
+
|
|
117
|
+
- **`live.sample({ stride })`** on `LiveSeries`, `LiveView`,
|
|
118
|
+
`LivePartitionedSeries`, `LivePartitionedView` — closure-captured
|
|
119
|
+
counter inside a `LiveView<S>`, so the chainable surface (`filter`,
|
|
120
|
+
`rolling`, `reduce`, `select`, `map`, `diff`, `rate`, `cumulative`,
|
|
121
|
+
`fill`) is immediately available downstream of the sample. The
|
|
122
|
+
bounded-memory firehose pattern:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
live.partitionBy('host').sample({ stride: 10 }).rolling('5m', mapping);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Each host's stream is thinned 1-in-10 before flowing into a per-host
|
|
129
|
+
5m rolling window. `live.stats().ingested` and `live.on('batch', cb)`
|
|
130
|
+
are upstream of any `.sample(...)` op — they continue counting true
|
|
131
|
+
throughput; only consumers downstream see the thinned stream.
|
|
132
|
+
|
|
133
|
+
- **Sampling docs page** at
|
|
134
|
+
[`pond-ts/transforms/sampling`](https://pjm17971.github.io/pond-ts/docs/pond-ts/transforms/sampling/)
|
|
135
|
+
covering when-to-use-which decision table, both strategies, the
|
|
136
|
+
visualization shape, multi-entity considerations, and a forward-link
|
|
137
|
+
to the live counterpart. New `## Sampling: bounded-memory thinning`
|
|
138
|
+
section in
|
|
139
|
+
[Live transforms](https://pjm17971.github.io/pond-ts/docs/pond-ts/live/live-transforms#sampling).
|
|
140
|
+
|
|
141
|
+
### Deferred
|
|
142
|
+
|
|
143
|
+
- **Live-side reservoir sampling** is queued for v0.18.0+. Algorithm R's
|
|
144
|
+
random-slot replacement produces non-prefix evictions, but the existing
|
|
145
|
+
live-eviction protocol (`'evict'` event + cutoff-based mirroring in
|
|
146
|
+
`LiveView`) assumes prefix evictions only. Bridging needs an exact-
|
|
147
|
+
removal eviction channel — arriving with the streaming RFC's
|
|
148
|
+
`LiveChange` model (Phase 4.5 milestone A). For visualization-shaped
|
|
149
|
+
reservoir today, materialize via `live.toTimeSeries().sample({ reservoir })`.
|
|
150
|
+
|
|
151
|
+
### Notes
|
|
152
|
+
|
|
153
|
+
- **Multi-entity bias trap** is documented in JSDoc on the pre-partition
|
|
154
|
+
sites (`LiveSeries.sample`, `LiveView.sample`) with the
|
|
155
|
+
`partitionBy(...).sample(...)` recommendation, matching the existing
|
|
156
|
+
convention for `rolling` / `aggregate` / `fill` / `diff` / `rate` /
|
|
157
|
+
`cumulative` / `pctChange` / `reduce`. An earlier iteration of #129
|
|
158
|
+
shipped a type-level `unsafeGlobal: true` token; pulled during review
|
|
159
|
+
for consistency with how every other stateful live operator handles
|
|
160
|
+
the same multi-entity consideration. Token-of-the-week novelty was
|
|
161
|
+
the wrong shape; the doc warning is the same answer the other
|
|
162
|
+
operators already give.
|
|
163
|
+
|
|
164
|
+
- **Legacy `rolling.sample(seq)` doc references removed.** Pre-v0.12
|
|
165
|
+
pond exposed `LiveRollingAggregation.sample(sequence)` as a separate
|
|
166
|
+
method (deleted in v0.12.0, replaced by `Trigger.every`). Active doc
|
|
167
|
+
references in `pond-ts/live/triggering.mdx`,
|
|
168
|
+
`pond-ts/transforms/alignment.mdx`, `pond-ts/transforms/rolling.mdx`,
|
|
169
|
+
and `pond-ts/live/live-transforms.mdx` removed to eliminate the
|
|
170
|
+
naming-collision confusion now that `series.sample({ stride | reservoir })`
|
|
171
|
+
is a real but completely unrelated operator. Historical record
|
|
172
|
+
preserved in PLAN.md, the v0.11.8 CHANGELOG entry, and the triggers RFC.
|
|
173
|
+
|
|
14
174
|
## [0.16.1] — 2026-05-06
|
|
15
175
|
|
|
16
176
|
Patch wave addressing one ergonomic gap surfaced by the gRPC
|
|
@@ -47,7 +207,7 @@ plus the v0.16.0 docs deploy that broke since v0.15.2.
|
|
|
47
207
|
- **Docs deploy workflow unblocked**
|
|
48
208
|
([#126](https://github.com/pjm17971/pond-ts/pull/126)). Has
|
|
49
209
|
been failing since v0.15.2 with `Cannot find name
|
|
50
|
-
|
|
210
|
+
'queueMicrotask'` — TypeDoc runs the same tsconfig as the
|
|
51
211
|
npm-publish path but from a different cwd, where `@types/node`
|
|
52
212
|
doesn't resolve. Fixed via a one-line ambient declaration in
|
|
53
213
|
`LiveReduce.ts`. No runtime change; `queueMicrotask` is still
|
|
@@ -101,17 +261,17 @@ narrowings.
|
|
|
101
261
|
`eventRate()`.
|
|
102
262
|
- **`stats()` accessor on every live accumulator/series.** Per-class
|
|
103
263
|
shapes, all returning a plain record (cumulative integer counters
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
| Class
|
|
107
|
-
|
|
108
|
-
| LiveSeries
|
|
109
|
-
| LiveRollingAggregation
|
|
110
|
-
| LiveFusedRolling
|
|
111
|
-
| LiveAggregation
|
|
112
|
-
| LiveReduce
|
|
113
|
-
| LivePartitionedSeries
|
|
114
|
-
| LivePartitionedSyncRolling
|
|
264
|
+
- current-state fields):
|
|
265
|
+
|
|
266
|
+
| Class | Shape |
|
|
267
|
+
| --------------------------- | --------------------------------------------------------------------- |
|
|
268
|
+
| LiveSeries | `{ ingested, evicted, rejected, length, earliestTs?, latestTs? }` |
|
|
269
|
+
| LiveRollingAggregation | `{ eventsObserved, evictions, emissions, windowSize }` |
|
|
270
|
+
| LiveFusedRolling | `{ eventsObserved, evictions, emissions, windowSize, windowsCount }` |
|
|
271
|
+
| LiveAggregation | `{ eventsObserved, bucketsClosed, openBuckets, openBucketStart? }` |
|
|
272
|
+
| LiveReduce | `{ eventsObserved, evictions, emissions, bufferSize }` |
|
|
273
|
+
| LivePartitionedSeries | `{ partitions, eventsRouted }` |
|
|
274
|
+
| LivePartitionedSyncRolling | `{ partitions, eventsObserved, emissions, windowSize }` |
|
|
115
275
|
| LivePartitionedFusedRolling | `{ partitions, eventsObserved, emissions, windowSize, windowsCount }` |
|
|
116
276
|
|
|
117
277
|
Per-event cost: ~1-3 integer increments in already-existing
|
|
@@ -152,7 +312,7 @@ narrowings.
|
|
|
152
312
|
|
|
153
313
|
- **`KeyLike` type** exported from the package root (re-exported
|
|
154
314
|
from `TimeSeries`). Accepts `EventKey | TimestampInput |
|
|
155
|
-
|
|
315
|
+
TimeRangeInput | IntervalInput`; normalised by the new query
|
|
156
316
|
primitives.
|
|
157
317
|
|
|
158
318
|
- **`DurationLiteral` and `DurationUnit` types** extracted from
|
|
@@ -186,8 +346,8 @@ narrowings.
|
|
|
186
346
|
on). Sane transforms (data-only maps, monotonic time-shifts)
|
|
187
347
|
unaffected.
|
|
188
348
|
- **`LiveAggregationOptions.grace`** type tightened from
|
|
189
|
-
`DurationInput | \`${number}${unit}\``
|
|
190
|
-
|
|
349
|
+
`DurationInput | \`${number}${unit}\``(redundant union) to
|
|
350
|
+
just`DurationInput`. No behavioral change.
|
|
191
351
|
|
|
192
352
|
### Notes
|
|
193
353
|
|
|
@@ -297,6 +457,8 @@ compaction); any downstream code reading `#entries` directly would
|
|
|
297
457
|
break, but those fields are private. Public APIs and types are
|
|
298
458
|
unchanged.
|
|
299
459
|
|
|
460
|
+
[0.17.1]: https://github.com/pjm17971/pond-ts/compare/v0.17.0...v0.17.1
|
|
461
|
+
[0.17.0]: https://github.com/pjm17971/pond-ts/compare/v0.16.1...v0.17.0
|
|
300
462
|
[0.16.1]: https://github.com/pjm17971/pond-ts/compare/v0.16.0...v0.16.1
|
|
301
463
|
[0.16.0]: https://github.com/pjm17971/pond-ts/compare/v0.15.2...v0.16.0
|
|
302
464
|
[0.15.2]: https://github.com/pjm17971/pond-ts/compare/v0.15.1...v0.15.2
|