pond-ts 0.18.0 → 0.20.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 (35) hide show
  1. package/CHANGELOG.md +66 -1
  2. package/README.md +6 -1
  3. package/dist/batch/aggregate-columns.d.ts +1 -7
  4. package/dist/batch/aggregate-columns.d.ts.map +1 -1
  5. package/dist/columnar/column.d.ts +0 -7
  6. package/dist/columnar/column.d.ts.map +1 -1
  7. package/dist/columnar/key-column.d.ts +0 -45
  8. package/dist/columnar/key-column.d.ts.map +1 -1
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +1 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/live/live-chunked-storage.d.ts +28 -1
  14. package/dist/live/live-chunked-storage.d.ts.map +1 -1
  15. package/dist/live/live-chunked-storage.js +175 -26
  16. package/dist/live/live-chunked-storage.js.map +1 -1
  17. package/dist/live/live-partitioned-fused-rolling.d.ts +0 -18
  18. package/dist/live/live-partitioned-fused-rolling.d.ts.map +1 -1
  19. package/dist/live/live-partitioned-series.d.ts +1 -32
  20. package/dist/live/live-partitioned-series.d.ts.map +1 -1
  21. package/dist/live/live-partitioned-series.js +126 -14
  22. package/dist/live/live-partitioned-series.js.map +1 -1
  23. package/dist/live/live-partitioned-sync-rolling.d.ts +0 -6
  24. package/dist/live/live-partitioned-sync-rolling.d.ts.map +1 -1
  25. package/dist/live/live-series.d.ts +0 -39
  26. package/dist/live/live-series.d.ts.map +1 -1
  27. package/dist/live/live-series.js +128 -28
  28. package/dist/live/live-series.js.map +1 -1
  29. package/dist/live/live-view.d.ts +54 -1
  30. package/dist/live/live-view.d.ts.map +1 -1
  31. package/dist/live/live-view.js +190 -3
  32. package/dist/live/live-view.js.map +1 -1
  33. package/dist/schema/series.d.ts +0 -2
  34. package/dist/schema/series.d.ts.map +1 -1
  35. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,11 +7,76 @@ 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.18.0...HEAD
10
+ [Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.20.0...HEAD
11
+ [0.20.0]: https://github.com/pjm17971/pond-ts/compare/v0.19.0...v0.20.0
12
+ [0.19.0]: https://github.com/pjm17971/pond-ts/compare/v0.18.0...v0.19.0
11
13
  [0.18.0]: https://github.com/pjm17971/pond-ts/compare/v0.17.1...v0.18.0
12
14
 
13
15
  ## [Unreleased]
14
16
 
17
+ ## [0.20.0] — 2026-06-04
18
+
19
+ Two internal performance improvements driven by the dashboard experiment at
20
+ 256-host stress. **No public API changes** — both are behavior-preserving.
21
+
22
+ ### Changed
23
+
24
+ - **Column-native partition routing.** `partitionBy(...)` over a strict
25
+ time-keyed source now routes its source chunks into per-partition
26
+ **chunked** sub-series via a coalescing staging tier, replacing the
27
+ per-partition `Event[]` retention. A large drop in retained memory and
28
+ object count at high partition counts (gRPC bench at 256 partitions: 60×
29
+ fewer columnar stores, −99.4% `Event` retention, +24% sustained throughput)
30
+ ([#175](https://github.com/pjm17971/pond-ts/pull/175)). Behavior-preserving;
31
+ internal only — no public surface added.
32
+ - **`LiveView.toTimeSeries()` snapshot caching.** The built `TimeSeries` is
33
+ memoized against an internal mutation counter, so back-to-back
34
+ identical-state calls (multiple subscribers, framework commit batching,
35
+ StrictMode double-invoke) return the cached instance by reference instead of
36
+ rebuilding the whole snapshot — ~44 ms → ~0 at a 262k-event window. A
37
+ fresh-state call still builds; safe because `TimeSeries` is immutable
38
+ ([#180](https://github.com/pjm17971/pond-ts/pull/180)).
39
+
40
+ ## [0.19.0] — 2026-06-02
41
+
42
+ Adds an **experimental column-read surface to the live side** — read typed
43
+ columns straight off a `LiveView` without materializing a `TimeSeries`
44
+ snapshot — driven by the dashboard experiment's per-tick memo cost. Plus a
45
+ `useTimeSeries` schema-inference fix. The live column surface is
46
+ **experimental and expected to keep moving in 0.19.x**.
47
+
48
+ ### Added
49
+
50
+ - **`LiveView` column-read surface (experimental).** Read columns directly
51
+ off a windowed live view, the column-API counterpart to the batch
52
+ `TimeSeries` surface ([#179](https://github.com/pjm17971/pond-ts/pull/179)):
53
+ - `liveView.column(name)` — a numeric value column gathered from the view's
54
+ current events (string / array columns are a compile error; read those as
55
+ scalars or snapshot via `toTimeSeries()`).
56
+ - `liveView.keyColumn()` — the time axis (`TimeKeyColumn`; time-keyed views
57
+ only, enforced at compile time).
58
+ - `liveView.partitionBy(col).toMap(fn)` — a walk-now per-partition read
59
+ returning `Map<string, R>`, mirroring `TimeSeries.partitionBy().toMap()`
60
+ but without per-partition `TimeSeries` construction. Distinct from
61
+ `LiveSeries.partitionBy` (which is subscription-oriented). Throws on a
62
+ missing / key partition column rather than silently merging.
63
+ - `LiveColumnGroup` — the per-partition view passed to the `toMap` callback.
64
+ - **`@pond-ts/react`: `useLiveVersion(source, { throttle })` (experimental)**
65
+ — a `useSyncExternalStore`-based change signal that bumps on append **and**
66
+ eviction, so a component can read columns off a live view each render
67
+ without manufacturing a `TimeSeries` snapshot. Closes the
68
+ render-before-subscribe gap; throttling bounds only the React notification
69
+ ([#179](https://github.com/pjm17971/pond-ts/pull/179)).
70
+
71
+ ### Changed
72
+
73
+ - **`useTimeSeries` collapsed to a single generic** `<S extends SeriesSchema>`
74
+ so the schema infers from `input.schema`. The prior two-generic signature
75
+ lost `S` through the input-wrapper generic and resolved
76
+ `result.column('cpu')` to `never`; the accepted input type is unchanged, so
77
+ this is an inference fix — but a caller passing two explicit type arguments
78
+ must drop the second ([#176](https://github.com/pjm17971/pond-ts/pull/176)).
79
+
15
80
  ## [0.18.0] — 2026-05-30
16
81
 
17
82
  This release graduates the **Phase 4.7 columnar substrate** from
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # pond-ts
2
2
 
3
3
  **Highly optimised, fully typed Timeseries library for TypeScript**
4
-
4
+
5
5
  Schema-driven events, composable batch transforms, push-based streaming
6
6
  ingest, multi-entity partitioning, and an optional React integration —
7
7
  all strict TypeScript end to end, all immutable.
@@ -31,6 +31,11 @@ npm install @pond-ts/react # React hooks (optional)
31
31
  single node.js instance.)
32
32
  - **Triggers** — for control of rolling emission cadences. Synchronised
33
33
  partitioned rolling fires across partitions on every boundary.
34
+ - **Typed column extraction** — `series.column('cpu')` returns a
35
+ schema-narrowed typed column with single-pass reductions
36
+ (`min`/`max`/`sum`/`mean`/`stdev`/`median`/`percentile`/`minMax`),
37
+ index downsampling (`bin`), and a zero-copy `toFloat64Array()` for
38
+ canvas / WebGL draw loops — no per-event allocation on the hot path.
34
39
  - **No legacy baggage**
35
40
 
36
41
  ## Quick start: batch
@@ -1,4 +1,4 @@
1
- import type { AggregateMap, AggregateOutputMap, AggregateOutputSpec, AggregateReducer, ScalarKind, SeriesSchema } from '../schema/index.js';
1
+ import type { AggregateMap, AggregateOutputMap, AggregateReducer, ScalarKind, SeriesSchema } from '../schema/index.js';
2
2
  /**
3
3
  * Normalised column spec used by both batch and live aggregation paths.
4
4
  *
@@ -17,12 +17,6 @@ export type AggregateColumnSpec = {
17
17
  reducer: AggregateReducer;
18
18
  kind: ScalarKind;
19
19
  };
20
- /**
21
- * @internal — discriminator between an `AggregateOutputSpec` (`{ from,
22
- * using, kind? }`) and a bare reducer string/function passed in an
23
- * `AggregateMap` slot.
24
- */
25
- export declare function isAggregateOutputSpec<S extends SeriesSchema>(value: unknown): value is AggregateOutputSpec<S>;
26
20
  /**
27
21
  * Resolve a user-supplied `mapping` (either `AggregateMap<S>` or
28
22
  * `AggregateOutputMap<S>`) against the source `schema` into a flat
@@ -1 +1 @@
1
- {"version":3,"file":"aggregate-columns.d.ts","sourceRoot":"","sources":["../../src/batch/aggregate-columns.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,EACV,YAAY,EACb,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,gBAAgB,CAAC;IAC1B,IAAI,EAAE,UAAU,CAAC;CAClB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,YAAY,EAC1D,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,mBAAmB,CAAC,CAAC,CAAC,CAOjC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,YAAY,EAC9D,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,GAC/C,mBAAmB,EAAE,CAuDvB"}
1
+ {"version":3,"file":"aggregate-columns.d.ts","sourceRoot":"","sources":["../../src/batch/aggregate-columns.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAElB,gBAAgB,EAChB,UAAU,EACV,YAAY,EACb,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,gBAAgB,CAAC;IAC1B,IAAI,EAAE,UAAU,CAAC;CAClB,CAAC;AAkBF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,YAAY,EAC9D,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,GAC/C,mBAAmB,EAAE,CAuDvB"}
@@ -127,13 +127,6 @@ export declare class Float64Column implements ColumnBase<number, 'number'> {
127
127
  readonly kind: "number";
128
128
  readonly storage: "packed";
129
129
  readonly length: number;
130
- /**
131
- * @internal Substrate-level raw buffer handle. May be oversized
132
- * (`_values.length > length` for capacity-grown columns). Walk
133
- * with `this.length` as the bound. For consumer code that wants
134
- * a length-bounded `Float64Array`, use `toFloat64Array()`.
135
- */
136
- readonly _values: Float64Array;
137
130
  readonly validity?: ValidityBitmap;
138
131
  constructor(values: Float64Array, length: number, validity?: ValidityBitmap);
139
132
  read(i: number): number | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"column.d.ts","sourceRoot":"","sources":["../../src/columnar/column.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"column.d.ts","sourceRoot":"","sources":["../../src/columnar/column.ts"],"names":[],"mappings":"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"}
@@ -88,19 +88,6 @@ export declare class TimeKeyColumn implements KeyColumnBase<'time'> {
88
88
  * O(1) on the key axis rather than O(e − s).
89
89
  */
90
90
  sliceByRange(start: number, end: number): TimeKeyColumn;
91
- /**
92
- * @internal Trusted-buffer factory used by slice paths. Skips
93
- * the per-row finiteness scan that the public constructor runs;
94
- * the caller MUST pass a subarray of (or otherwise equivalently
95
- * pre-validated) buffer from a `TimeKeyColumn` that was itself
96
- * constructed via the public path. External callers must use
97
- * `new TimeKeyColumn(...)`.
98
- *
99
- * Still validates structural invariants: finite non-negative
100
- * integer `length` and `length <= begin.length`. Those are O(1)
101
- * and protect against caller-passed garbage.
102
- */
103
- static fromValidatedSubarray(begin: Float64Array, length: number): TimeKeyColumn;
104
91
  /**
105
92
  * Gathers rows by index into a new `TimeKeyColumn`. Out-of-range
106
93
  * source indices produce a `0` slot in the output buffer — the
@@ -131,20 +118,6 @@ export declare class TimeRangeKeyColumn implements KeyColumnBase<'timeRange'> {
131
118
  * See RFC §4 close-cases for why range-key max-end is deferred.
132
119
  */
133
120
  sliceByRange(start: number, end: number): TimeRangeKeyColumn;
134
- /**
135
- * @internal Trusted-buffer factory for slice paths. Skips per-
136
- * row finiteness scans on both buffers AND the `begin[i] <=
137
- * end[i]` invariant check — the caller MUST pass subarrays of
138
- * (or equivalently pre-validated) buffers from a
139
- * `TimeRangeKeyColumn` that was itself constructed via the
140
- * public path. External callers must use
141
- * `new TimeRangeKeyColumn(...)`.
142
- *
143
- * Still validates O(1) structural invariants: finite non-
144
- * negative integer `length`, and `length <= min(begin.length,
145
- * end.length)`.
146
- */
147
- static fromValidatedSubarray(begin: Float64Array, end: Float64Array, length: number): TimeRangeKeyColumn;
148
121
  /**
149
122
  * Gathers rows by index into a new `TimeRangeKeyColumn`. See
150
123
  * `TimeKeyColumn.sliceByIndices` for the out-of-range semantics.
@@ -189,24 +162,6 @@ export declare class IntervalKeyColumn implements KeyColumnBase<'interval'> {
189
162
  * `end[length - 1]`).
190
163
  */
191
164
  sliceByRange(start: number, end: number): IntervalKeyColumn;
192
- /**
193
- * @internal Trusted-buffer factory for slice paths. Skips
194
- * per-row validation: finiteness scans on begin/end, the
195
- * begin[i] <= end[i] invariant check, AND the per-row label
196
- * defined-and-type-matches check (which is the dominant cost
197
- * for IntervalKeyColumn — `labels.read(i)` per row).
198
- *
199
- * Caller MUST pass subarrays / pre-validated buffers from an
200
- * `IntervalKeyColumn` that was constructed via the public path
201
- * (or compositionally from other trusted paths). External
202
- * callers must use `new IntervalKeyColumn(...)`.
203
- *
204
- * The `labelKind` argument is explicit (rather than re-derived
205
- * from `labels.kind`) so callers retain the source column's
206
- * discriminator without an extra branch — trusted construction
207
- * trusts the caller knows what they have.
208
- */
209
- static fromValidatedSubarray(begin: Float64Array, end: Float64Array, labels: StringColumn | Float64Column, labelKind: IntervalLabelKind, length: number): IntervalKeyColumn;
210
165
  /**
211
166
  * Gathers rows by index into a new `IntervalKeyColumn`. The label
212
167
  * column is `sliceByIndices`'d as well — for string labels the
@@ -1 +1 @@
1
- {"version":3,"file":"key-column.d.ts","sourceRoot":"","sources":["../../src/columnar/key-column.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"key-column.d.ts","sourceRoot":"","sources":["../../src/columnar/key-column.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@ export { LiveAggregation } from './live/live-aggregation.js';
5
5
  export type { LiveAggregationOptions } from './live/live-aggregation.js';
6
6
  export { LivePartitionedSeries, LivePartitionedView, type LivePartitionedOptions, } from './live/live-partitioned-series.js';
7
7
  export { LiveSeries } from './live/live-series.js';
8
- export { LiveView } from './live/live-view.js';
8
+ export { LiveView, LiveColumnGroup } from './live/live-view.js';
9
9
  export type { LiveFillMapping, LiveFillStrategy } from './live/live-view.js';
10
10
  export { LiveRollingAggregation } from './live/live-rolling-aggregation.js';
11
11
  export { LiveFusedRolling } from './live/live-fused-rolling.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,YAAY,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,KAAK,sBAAsB,GAC5B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAChE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AACvF,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAUnD,OAAO,aAAa,CAAC;AASrB,YAAY,EACV,SAAS,EACT,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,GACf,MAAM,aAAa,CAAC;AAyBrB,OAAO,EACL,KAAK,MAAM,EACX,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,aAAa,EACb,aAAa,GACd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,iBAAiB,EACjB,aAAa,EACb,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,YAAY,EACV,WAAW,EACX,wBAAwB,EACxB,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,SAAS,EACT,YAAY,EACZ,0BAA0B,EAC1B,kBAAkB,EAClB,2BAA2B,EAC3B,wBAAwB,EACxB,yBAAyB,EACzB,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,sBAAsB,EACtB,kBAAkB,EAClB,UAAU,EACV,QAAQ,EACR,UAAU,EACV,sBAAsB,EACtB,4BAA4B,EAC5B,mBAAmB,EACnB,sBAAsB,EACtB,YAAY,EACZ,UAAU,EACV,SAAS,EACT,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,UAAU,EACV,WAAW,EACX,UAAU,EACV,WAAW,EACX,sBAAsB,EACtB,UAAU,EACV,0BAA0B,EAC1B,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,WAAW,EACX,YAAY,GACb,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,eAAe,EACf,YAAY,EACZ,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,QAAQ,EACR,aAAa,EACb,aAAa,EACb,YAAY,EACZ,cAAc,EACd,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,YAAY,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,YAAY,EACV,iBAAiB,EACjB,YAAY,EACZ,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,kBAAkB,EAClB,aAAa,GACd,MAAM,oCAAoC,CAAC;AAC5C,YAAY,EACV,cAAc,EACd,YAAY,EACZ,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,EAClB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ export { Interval } from './core/interval.js';
4
4
  export { LiveAggregation } from './live/live-aggregation.js';
5
5
  export { LivePartitionedSeries, LivePartitionedView, } from './live/live-partitioned-series.js';
6
6
  export { LiveSeries } from './live/live-series.js';
7
- export { LiveView } from './live/live-view.js';
7
+ export { LiveView, LiveColumnGroup } from './live/live-view.js';
8
8
  export { LiveRollingAggregation } from './live/live-rolling-aggregation.js';
9
9
  export { LiveFusedRolling } from './live/live-fused-rolling.js';
10
10
  export { LivePartitionedFusedRolling } from './live/live-partitioned-fused-rolling.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,EACL,qBAAqB,EACrB,mBAAmB,GAEpB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AACvF,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAM7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAgB,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,mEAAmE;AACnE,EAAE;AACF,0DAA0D;AAC1D,kEAAkE;AAClE,6DAA6D;AAC7D,yDAAyD;AACzD,iEAAiE;AACjE,mEAAmE;AACnE,OAAO,aAAa,CAAC;AAmBrB,iEAAiE;AACjE,EAAE;AACF,+DAA+D;AAC/D,oEAAoE;AACpE,+DAA+D;AAC/D,8DAA8D;AAC9D,oEAAoE;AACpE,mDAAmD;AACnD,EAAE;AACF,8DAA8D;AAC9D,kEAAkE;AAClE,kEAAkE;AAClE,2DAA2D;AAC3D,kEAAkE;AAClE,4DAA4D;AAC5D,kEAAkE;AAClE,EAAE;AACF,iEAAiE;AACjE,8DAA8D;AAC9D,8DAA8D;AAC9D,6DAA6D;AAC7D,6DAA6D;AAC7D,gBAAgB;AAChB,OAAO,EAKL,aAAa,EACb,aAAa,GACd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAGL,iBAAiB,EACjB,aAAa,EACb,kBAAkB,GACnB,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,EACL,qBAAqB,EACrB,mBAAmB,GAEpB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEhE,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AACvF,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAM7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAgB,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,mEAAmE;AACnE,EAAE;AACF,0DAA0D;AAC1D,kEAAkE;AAClE,6DAA6D;AAC7D,yDAAyD;AACzD,iEAAiE;AACjE,mEAAmE;AACnE,OAAO,aAAa,CAAC;AAmBrB,iEAAiE;AACjE,EAAE;AACF,+DAA+D;AAC/D,oEAAoE;AACpE,+DAA+D;AAC/D,8DAA8D;AAC9D,oEAAoE;AACpE,mDAAmD;AACnD,EAAE;AACF,8DAA8D;AAC9D,kEAAkE;AAClE,kEAAkE;AAClE,2DAA2D;AAC3D,kEAAkE;AAClE,4DAA4D;AAC5D,kEAAkE;AAClE,EAAE;AACF,iEAAiE;AACjE,8DAA8D;AAC9D,8DAA8D;AAC9D,6DAA6D;AAC7D,6DAA6D;AAC7D,gBAAgB;AAChB,OAAO,EAKL,aAAa,EACb,aAAa,GACd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAGL,iBAAiB,EACjB,aAAa,EACb,kBAAkB,GACnB,MAAM,0BAA0B,CAAC"}
@@ -48,10 +48,25 @@ import type { ReadableLiveStorage } from './live-storage.js';
48
48
  * after the listeners run), so they don't defeat the heap win.
49
49
  */
50
50
  export declare function materializeEventsFromStore<S extends SeriesSchema>(store: ColumnarStore<S>, schema: S): EventForSchema<S>[];
51
+ /**
52
+ * Like {@link materializeEventsFromStore} but over a subset of rows
53
+ * (`indices`, in order) — the transient `'event'` / `'batch'` fan-out
54
+ * for the column-native partition router's staged slice. NOT cached
55
+ * (young-gen), so it doesn't defeat the heap win.
56
+ */
57
+ export declare function materializeEventsFromStoreAt<S extends SeriesSchema>(store: ColumnarStore<S>, indices: ArrayLike<number>, schema: S): EventForSchema<S>[];
51
58
  export declare class ChunkedColumnarLiveStorage<S extends SeriesSchema> implements ReadableLiveStorage<S> {
52
59
  #private;
53
- constructor(schema: S);
60
+ constructor(schema: S, flushThreshold?: number);
54
61
  get length(): number;
62
+ /**
63
+ * Number of committed (compacted) chunks. Test/bench observability for
64
+ * the coalescing win — under thin partition routing this stays bounded
65
+ * (≈ rows / flushThreshold) instead of one chunk per source batch.
66
+ */
67
+ get committedChunkCount(): number;
68
+ /** Rows currently in the un-flushed staging tier (`< flushThreshold`). */
69
+ get pendingCount(): number;
55
70
  /**
56
71
  * Validate a batch of rows directly into columns and append it as a
57
72
  * chunk. No per-row `Event` is created. The caller (`LiveSeries`)
@@ -66,6 +81,18 @@ export declare class ChunkedColumnarLiveStorage<S extends SeriesSchema> implemen
66
81
  * convenience used by the isolated tests.
67
82
  */
68
83
  appendStore(store: ColumnarStore<S>): void;
84
+ /**
85
+ * Stage a partition's slice of a source chunk: gather rows `indices`
86
+ * from `store` into the pending tier (cheap tuples — NO per-batch
87
+ * `ColumnarStore`), flushing one packed chunk when the tier reaches
88
+ * `#flushThreshold`. The column-native partition-routing path
89
+ * (`LivePartitionedSeries.#routeChunk`); the coalescing fix for thin
90
+ * scatter (gRPC V7: naive one-chunk-per-slice was 23.5× the object
91
+ * count + a throughput collapse). The caller guarantees the gathered
92
+ * rows are `>=` the current last key (strict source + order-preserving
93
+ * scatter). Time-keyed only — the chunked routing gate is strict+time.
94
+ */
95
+ stageRows(store: ColumnarStore<S>, indices: ArrayLike<number>): void;
69
96
  at(index: number): EventForSchema<S> | undefined;
70
97
  keyAt(index: number): EventKey | undefined;
71
98
  beginAt(index: number): number | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"live-chunked-storage.d.ts","sourceRoot":"","sources":["../../src/live/live-chunked-storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAKH,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,YAAY,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,YAAY,EAC/D,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EACvB,MAAM,EAAE,CAAC,GACR,cAAc,CAAC,CAAC,CAAC,EAAE,CAoBrB;AAiBD,qBAAa,0BAA0B,CACrC,CAAC,SAAS,YAAY,CACtB,YAAW,mBAAmB,CAAC,CAAC,CAAC;;gBASrB,MAAM,EAAE,CAAC;IAYrB,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;;;;OAKG;IACH,mBAAmB,CAAC,IAAI,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;IAY/D;;;;;OAKG;IACH,WAAW,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI;IAkB1C,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS;IAWhD,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAQ1C,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAM1C,IAAI,IAAI,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS;IAIrC,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IASxD,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAM3B,KAAK,IAAI,aAAa,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IAWzC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC;CA4EtC"}
1
+ {"version":3,"file":"live-chunked-storage.d.ts","sourceRoot":"","sources":["../../src/live/live-chunked-storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAKH,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,YAAY,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,YAAY,EAC/D,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EACvB,MAAM,EAAE,CAAC,GACR,cAAc,CAAC,CAAC,CAAC,EAAE,CAoBrB;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,CAAC,SAAS,YAAY,EACjE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EACvB,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,EAC1B,MAAM,EAAE,CAAC,GACR,cAAc,CAAC,CAAC,CAAC,EAAE,CAqBrB;AAiBD,qBAAa,0BAA0B,CACrC,CAAC,SAAS,YAAY,CACtB,YAAW,mBAAmB,CAAC,CAAC,CAAC;;gBAsBrB,MAAM,EAAE,CAAC,EAAE,cAAc,SAAM;IAkB3C,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;;;OAIG;IACH,IAAI,mBAAmB,IAAI,MAAM,CAEhC;IAED,0EAA0E;IAC1E,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED;;;;;OAKG;IACH,mBAAmB,CAAC,IAAI,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;IAY/D;;;;;OAKG;IACH,WAAW,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI;IAY1C;;;;;;;;;;OAUG;IACH,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI;IAyDpE,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS;IAehD,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAa1C,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAS1C,IAAI,IAAI,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS;IAIrC,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IASxD,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAM3B,KAAK,IAAI,aAAa,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IAYzC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC;CAkGtC"}
@@ -68,6 +68,33 @@ export function materializeEventsFromStore(store, schema) {
68
68
  }
69
69
  return out;
70
70
  }
71
+ /**
72
+ * Like {@link materializeEventsFromStore} but over a subset of rows
73
+ * (`indices`, in order) — the transient `'event'` / `'batch'` fan-out
74
+ * for the column-native partition router's staged slice. NOT cached
75
+ * (young-gen), so it doesn't defeat the heap win.
76
+ */
77
+ export function materializeEventsFromStoreAt(store, indices, schema) {
78
+ const keyKind = schema[0].kind;
79
+ const valueNames = [];
80
+ for (let i = 1; i < schema.length; i += 1) {
81
+ valueNames.push(schema[i].name);
82
+ }
83
+ const out = new Array(indices.length);
84
+ for (let j = 0; j < indices.length; j += 1) {
85
+ const i = indices[j];
86
+ const begin = store.beginAt(i);
87
+ const key = keyKind === 'time'
88
+ ? new Time(begin)
89
+ : new TimeRange({ start: begin, end: store.endAt(i) });
90
+ const data = {};
91
+ for (let v = 0; v < valueNames.length; v += 1) {
92
+ data[valueNames[v]] = store.valueAt(i, valueNames[v]);
93
+ }
94
+ out[j] = new Event(key, data);
95
+ }
96
+ return out;
97
+ }
71
98
  /** Row-range slice of a store: sliced keys + each column sliced in lockstep. */
72
99
  function sliceStore(store, start, end) {
73
100
  const keys = store.keys.sliceByRange(start, end);
@@ -83,20 +110,49 @@ export class ChunkedColumnarLiveStorage {
83
110
  #keyKind;
84
111
  #valueNames;
85
112
  #chunks = [];
86
- #total = 0;
113
+ /** Rows committed to `#chunks` (excludes the pending staging tier). */
114
+ #committed = 0;
115
+ /**
116
+ * Staging tier — gathered row tuples not yet compacted into a chunk.
117
+ * The coalescing fix for thin partition routing (scatter delivers ~1
118
+ * row per partition per source batch; one chunk each would be ~23×
119
+ * the object count of the Events it replaces — see PLAN "Deferred").
120
+ * Rows accumulate here (cheap pushes, no per-batch `ColumnarStore`),
121
+ * then flush as ONE packed chunk at `#flushThreshold`. Readable in
122
+ * place so the live series' `length` / `at(i)` / retention see staged
123
+ * rows immediately. Bounded to `[0, #flushThreshold)` at any instant.
124
+ */
125
+ #pending = [];
126
+ #flushThreshold;
87
127
  /** Lazy event materialization cache, keyed by logical index. */
88
128
  #cache = new Map();
89
- constructor(schema) {
129
+ constructor(schema, flushThreshold = 256) {
90
130
  this.#schema = schema;
91
131
  const keyKind = schema[0].kind;
92
132
  if (keyKind !== 'time' && keyKind !== 'timeRange') {
93
133
  throw new Error(`ChunkedColumnarLiveStorage: unsupported key kind '${keyKind}' (expected 'time' | 'timeRange')`);
94
134
  }
135
+ if (!Number.isInteger(flushThreshold) || flushThreshold < 1) {
136
+ throw new Error(`ChunkedColumnarLiveStorage: flushThreshold must be a positive integer, got ${flushThreshold}`);
137
+ }
95
138
  this.#keyKind = keyKind;
139
+ this.#flushThreshold = flushThreshold;
96
140
  this.#valueNames = schema.slice(1).map((c) => c.name);
97
141
  }
98
142
  get length() {
99
- return this.#total;
143
+ return this.#committed + this.#pending.length;
144
+ }
145
+ /**
146
+ * Number of committed (compacted) chunks. Test/bench observability for
147
+ * the coalescing win — under thin partition routing this stays bounded
148
+ * (≈ rows / flushThreshold) instead of one chunk per source batch.
149
+ */
150
+ get committedChunkCount() {
151
+ return this.#chunks.length;
152
+ }
153
+ /** Rows currently in the un-flushed staging tier (`< flushThreshold`). */
154
+ get pendingCount() {
155
+ return this.#pending.length;
100
156
  }
101
157
  /**
102
158
  * Validate a batch of rows directly into columns and append it as a
@@ -123,12 +179,72 @@ export class ChunkedColumnarLiveStorage {
123
179
  appendStore(store) {
124
180
  if (store.length === 0)
125
181
  return;
182
+ // A direct chunk lands logically AFTER any staged rows, so flush
183
+ // pending first to keep committed order correct. (In practice a
184
+ // storage uses either appendStore — the source's big batches — or
185
+ // stageRows — partition routing — not both; the guard keeps the
186
+ // order contract unconditional.)
187
+ if (this.#pending.length > 0)
188
+ this.#flushPending();
126
189
  this.#chunks.push(store);
127
- this.#total += store.length;
190
+ this.#committed += store.length;
191
+ }
192
+ /**
193
+ * Stage a partition's slice of a source chunk: gather rows `indices`
194
+ * from `store` into the pending tier (cheap tuples — NO per-batch
195
+ * `ColumnarStore`), flushing one packed chunk when the tier reaches
196
+ * `#flushThreshold`. The column-native partition-routing path
197
+ * (`LivePartitionedSeries.#routeChunk`); the coalescing fix for thin
198
+ * scatter (gRPC V7: naive one-chunk-per-slice was 23.5× the object
199
+ * count + a throughput collapse). The caller guarantees the gathered
200
+ * rows are `>=` the current last key (strict source + order-preserving
201
+ * scatter). Time-keyed only — the chunked routing gate is strict+time.
202
+ */
203
+ stageRows(store, indices) {
204
+ if (this.#keyKind !== 'time') {
205
+ throw new Error(`ChunkedColumnarLiveStorage.stageRows: only 'time' keys are stageable (got '${this.#keyKind}')`);
206
+ }
207
+ const k = indices.length;
208
+ if (k === 0)
209
+ return;
210
+ const valueNames = this.#valueNames;
211
+ for (let j = 0; j < k; j += 1) {
212
+ const i = indices[j];
213
+ const row = [store.beginAt(i)];
214
+ for (let v = 0; v < valueNames.length; v += 1) {
215
+ row.push(store.valueAt(i, valueNames[v]));
216
+ }
217
+ this.#pending.push(row);
218
+ }
219
+ if (this.#pending.length >= this.#flushThreshold)
220
+ this.#flushPending();
221
+ }
222
+ /**
223
+ * Compact the pending tier into one packed chunk. Rows are trusted
224
+ * (gathered from a validated source store), but reusing
225
+ * `validateAndNormalizeColumnar` is fine — it runs once per
226
+ * `#flushThreshold` rows (amortized O(N)), and avoids re-implementing
227
+ * per-kind column + validity construction.
228
+ */
229
+ #flushPending() {
230
+ if (this.#pending.length === 0)
231
+ return;
232
+ const { keys, columns } = validateAndNormalizeColumnar({
233
+ name: 'live-chunk',
234
+ schema: this.#schema,
235
+ rows: this.#pending,
236
+ });
237
+ this.#chunks.push(ColumnarStore.fromTrustedStore(this.#schema, keys, columns));
238
+ this.#committed += this.#pending.length;
239
+ this.#pending = [];
128
240
  }
129
- /** Locate logical index `i` as `[chunkIndex, localIndex]`, or null if out of range. */
241
+ /**
242
+ * Locate a COMMITTED logical index `i` as `[chunkIndex, localIndex]`,
243
+ * or null if out of the committed range. Pending-tier indices
244
+ * (`i >= #committed`) are handled by the callers, not here.
245
+ */
130
246
  #locate(i) {
131
- if (i < 0 || i >= this.#total)
247
+ if (i < 0 || i >= this.#committed)
132
248
  return null;
133
249
  let acc = 0;
134
250
  for (let c = 0; c < this.#chunks.length; c += 1) {
@@ -140,33 +256,44 @@ export class ChunkedColumnarLiveStorage {
140
256
  return null; // unreachable given the range guard
141
257
  }
142
258
  at(index) {
143
- const loc = this.#locate(index);
144
- if (loc === null)
259
+ if (index < 0 || index >= this.length)
145
260
  return undefined;
146
261
  let event = this.#cache.get(index);
147
262
  if (event === undefined) {
148
- event = this.#materializeAt(loc[0], loc[1]);
263
+ if (index < this.#committed) {
264
+ const loc = this.#locate(index);
265
+ event = this.#materializeAt(loc[0], loc[1]);
266
+ }
267
+ else {
268
+ event = this.#materializePending(index - this.#committed);
269
+ }
149
270
  this.#cache.set(index, event);
150
271
  }
151
272
  return event;
152
273
  }
153
274
  keyAt(index) {
154
- const loc = this.#locate(index);
155
- if (loc === null)
275
+ if (index < 0 || index >= this.length)
156
276
  return undefined;
157
277
  const cached = this.#cache.get(index);
158
278
  if (cached !== undefined)
159
279
  return cached.key();
160
- return this.#keyAt(loc[0], loc[1]);
280
+ if (index < this.#committed) {
281
+ const loc = this.#locate(index);
282
+ return this.#keyAt(loc[0], loc[1]);
283
+ }
284
+ return new Time(this.#pending[index - this.#committed][0]);
161
285
  }
162
286
  beginAt(index) {
163
- const loc = this.#locate(index);
164
- if (loc === null)
287
+ if (index < 0 || index >= this.length)
165
288
  return undefined;
166
- return this.#chunks[loc[0]].beginAt(loc[1]);
289
+ if (index < this.#committed) {
290
+ const loc = this.#locate(index);
291
+ return this.#chunks[loc[0]].beginAt(loc[1]);
292
+ }
293
+ return this.#pending[index - this.#committed][0];
167
294
  }
168
295
  last() {
169
- return this.at(this.#total - 1);
296
+ return this.at(this.length - 1);
170
297
  }
171
298
  evictPrefix(n) {
172
299
  if (n <= 0)
@@ -185,24 +312,24 @@ export class ChunkedColumnarLiveStorage {
185
312
  this.#shiftCacheBy(n);
186
313
  }
187
314
  clear() {
188
- const len = this.#total;
315
+ const len = this.length;
189
316
  if (len === 0)
190
317
  return [];
191
318
  const all = new Array(len);
192
319
  for (let i = 0; i < len; i += 1)
193
320
  all[i] = this.at(i);
194
321
  this.#chunks = [];
195
- this.#total = 0;
322
+ this.#committed = 0;
323
+ this.#pending = [];
196
324
  this.#cache.clear();
197
325
  return all;
198
326
  }
199
327
  snapshot(name) {
200
- // Walk chunks in order, materializing rows. (A columnar fast-path
201
- // snapshot — concatSorted(chunks) → trusted TimeSeries — is a
202
- // deferred follow-up; snapshot isn't the hot path. Matches the
203
- // array backing's row-rebuild for now.)
328
+ // Walk committed chunks then the pending tier, materializing rows.
329
+ // (A columnar fast-path snapshot — concatSorted(chunks) → trusted
330
+ // TimeSeries — is a deferred follow-up; snapshot isn't the hot path.)
204
331
  const schema = this.#schema;
205
- const rows = new Array(this.#total);
332
+ const rows = new Array(this.length);
206
333
  let r = 0;
207
334
  for (let c = 0; c < this.#chunks.length; c += 1) {
208
335
  const store = this.#chunks[c];
@@ -215,25 +342,37 @@ export class ChunkedColumnarLiveStorage {
215
342
  r += 1;
216
343
  }
217
344
  }
345
+ for (let p = 0; p < this.#pending.length; p += 1) {
346
+ const pr = this.#pending[p];
347
+ rows[r] = [new Time(pr[0]), ...pr.slice(1)];
348
+ r += 1;
349
+ }
218
350
  return new TimeSeries({ name, schema, rows: rows });
219
351
  }
220
- /** Drop exactly the oldest `n` rows: whole chunks then a boundary slice. */
352
+ /**
353
+ * Drop exactly the oldest `n` rows: whole committed chunks, then a
354
+ * boundary slice, then the pending tier (only reached when the
355
+ * retention window is smaller than the pending tail — tiny windows).
356
+ */
221
357
  #evictExact(n) {
222
358
  let toEvict = n;
223
359
  while (toEvict > 0 && this.#chunks.length > 0) {
224
360
  const c0 = this.#chunks[0];
225
361
  if (c0.length <= toEvict) {
226
362
  toEvict -= c0.length;
227
- this.#total -= c0.length;
363
+ this.#committed -= c0.length;
228
364
  this.#chunks.shift();
229
365
  }
230
366
  else {
231
367
  // Partial: slice the oldest `toEvict` rows off the boundary chunk.
232
368
  this.#chunks[0] = sliceStore(c0, toEvict, c0.length);
233
- this.#total -= toEvict;
369
+ this.#committed -= toEvict;
234
370
  toEvict = 0;
235
371
  }
236
372
  }
373
+ if (toEvict > 0 && this.#pending.length > 0) {
374
+ this.#pending.splice(0, Math.min(toEvict, this.#pending.length));
375
+ }
237
376
  }
238
377
  /** Remap the cache after evicting `n` head rows: drop `<n`, shift the rest down. */
239
378
  #shiftCacheBy(n) {
@@ -257,6 +396,16 @@ export class ChunkedColumnarLiveStorage {
257
396
  end: store.endAt(localIdx),
258
397
  });
259
398
  }
399
+ /** Materialize an Event from a pending-tier row tuple (time-keyed). */
400
+ #materializePending(p) {
401
+ const row = this.#pending[p];
402
+ const key = new Time(row[0]);
403
+ const data = {};
404
+ for (let v = 0; v < this.#valueNames.length; v += 1) {
405
+ data[this.#valueNames[v]] = row[v + 1];
406
+ }
407
+ return new Event(key, data);
408
+ }
260
409
  #materializeAt(chunkIdx, localIdx) {
261
410
  const store = this.#chunks[chunkIdx];
262
411
  const begin = store.beginAt(localIdx);