pond-ts 0.65.0 → 0.67.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/API.md +211 -34
- package/CHANGELOG.md +1111 -1
- package/dist/live/listener-set.d.ts +18 -0
- package/dist/live/listener-set.js +34 -0
- package/dist/live/live-partitioned-series.d.ts +1 -1
- package/dist/live/live-partitioned-series.js +64 -0
- package/dist/live/live-reduce.d.ts +14 -14
- package/dist/live/live-reduce.js +22 -15
- package/dist/live/live-series.d.ts +18 -21
- package/dist/live/live-series.js +265 -104
- package/dist/live/live-view.d.ts +18 -9
- package/dist/live/live-view.js +72 -8
- package/dist/reducers/index.d.ts +10 -1
- package/dist/reducers/index.js +18 -24
- package/dist/reducers/rolling.d.ts +22 -0
- package/dist/reducers/rolling.js +65 -0
- package/package.json +1 -1
package/dist/reducers/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { rollingIndexedEntries, rollingSortedExtreme } from './rolling.js';
|
|
1
2
|
import { parsePercentile, percentileReducer } from './percentile.js';
|
|
2
3
|
import { parseTopN, topReducer } from './top.js';
|
|
3
4
|
import { count } from './count.js';
|
|
@@ -102,31 +103,24 @@ export function bucketStateFor(reducer) {
|
|
|
102
103
|
},
|
|
103
104
|
};
|
|
104
105
|
}
|
|
105
|
-
|
|
106
|
-
* Build a `RollingReducerState` for a reducer that may be either a
|
|
107
|
-
* built-in name (string) or a custom function. Built-ins use their
|
|
108
|
-
* dedicated incremental machinery (O(1) `add`/`remove`/`snapshot`).
|
|
109
|
-
*
|
|
110
|
-
* Custom functions use a generic adapter:
|
|
111
|
-
* - `add(idx, v)` stores into a Map keyed by event index.
|
|
112
|
-
* - `remove(idx, v)` deletes by index.
|
|
113
|
-
* - `snapshot()` calls the function with the current window's values
|
|
114
|
-
* in arrival order — O(N) per snapshot.
|
|
115
|
-
*
|
|
116
|
-
* **Performance characteristic.** Per-event cost is O(1) for state
|
|
117
|
-
* maintenance but `snapshot` is O(window size) — the function re-
|
|
118
|
-
* runs over every value in the current window each time the
|
|
119
|
-
* accumulator emits. Compare to built-in reducers which maintain a
|
|
120
|
-
* running result incrementally and snapshot in O(1).
|
|
121
|
-
*
|
|
122
|
-
* For high-throughput live use, prefer built-ins or `'samples'`
|
|
123
|
-
* (which lets you compute the custom logic once at the consumer,
|
|
124
|
-
* after the rolling has already collapsed events to the value list).
|
|
125
|
-
* Custom-function reducers shine on low-rate streams where
|
|
126
|
-
* convenience matters more than per-snapshot cost.
|
|
127
|
-
*/
|
|
128
|
-
export function rollingStateFor(reducer) {
|
|
106
|
+
export function rollingStateFor(reducer, evictionOrder = 'arrival') {
|
|
129
107
|
if (typeof reducer === 'string') {
|
|
108
|
+
if (evictionOrder === 'sorted') {
|
|
109
|
+
// [PND-LIVFIX] The four forward-sliding-window states assume
|
|
110
|
+
// oldest-arrived-first eviction; swap in the any-order structures
|
|
111
|
+
// for a source that evicts its sorted prefix. Every other built-in
|
|
112
|
+
// already removes by index or by value.
|
|
113
|
+
switch (reducer) {
|
|
114
|
+
case 'min':
|
|
115
|
+
return skipNonFiniteRolling(rollingSortedExtreme('min'));
|
|
116
|
+
case 'max':
|
|
117
|
+
return skipNonFiniteRolling(rollingSortedExtreme('max'));
|
|
118
|
+
case 'first':
|
|
119
|
+
return skipNonFiniteRolling(rollingIndexedEntries('first'));
|
|
120
|
+
case 'last':
|
|
121
|
+
return skipNonFiniteRolling(rollingIndexedEntries('last'));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
130
124
|
return skipNonFiniteRolling(resolveReducer(reducer).rollingState());
|
|
131
125
|
}
|
|
132
126
|
// Custom-function adapter: Map keyed by event index for O(1) remove.
|
|
@@ -6,6 +6,28 @@ type RollingWindowEntry<T> = {
|
|
|
6
6
|
};
|
|
7
7
|
export declare function rollingMonotoneDeque(compare: (a: number, b: number) => boolean): RollingReducerState;
|
|
8
8
|
export declare function rollingOrderedEntries(pick: (entries: RollingWindowEntry<ColumnValue>[], head: number) => ColumnValue | undefined): RollingReducerState;
|
|
9
|
+
/**
|
|
10
|
+
* [PND-LIVFIX] Ordered entries that tolerate removal of ANY index, not only
|
|
11
|
+
* the head. `rollingOrderedEntries` above is a forward-sliding window: it
|
|
12
|
+
* assumes evictions arrive oldest-added-first, which holds for append-only
|
|
13
|
+
* sources but not for a `reorder` source with retention, whose sorted-prefix
|
|
14
|
+
* eviction can drop a middle or the newest arrival — and then `first` /
|
|
15
|
+
* `last` kept reporting an evicted value. Entries live in a `Map` keyed by
|
|
16
|
+
* index (insertion order = arrival order) so any index removes in O(1);
|
|
17
|
+
* `first` is the map's first value and `last` is a tracked tail index,
|
|
18
|
+
* re-derived by an O(n) scan when the tail itself is evicted — on a
|
|
19
|
+
* reorder source that is the headline case (the newest arrival being the
|
|
20
|
+
* sorted prefix), so `last` is O(n) per such eviction and O(1) otherwise.
|
|
21
|
+
*/
|
|
22
|
+
export declare function rollingIndexedEntries(pick: 'first' | 'last'): RollingReducerState;
|
|
23
|
+
/**
|
|
24
|
+
* [PND-LIVFIX] `min` / `max` over a sorted array — removal by value, so the
|
|
25
|
+
* extreme is exact whatever order evictions arrive in. O(n) per insert /
|
|
26
|
+
* remove (a `splice`), against the monotone deque's amortised O(1); it is
|
|
27
|
+
* selected only for sources whose eviction order is not arrival order
|
|
28
|
+
* (`reorder` + retention), where the deque is wrong rather than slow.
|
|
29
|
+
*/
|
|
30
|
+
export declare function rollingSortedExtreme(pick: 'min' | 'max'): RollingReducerState;
|
|
9
31
|
export declare function rollingSortedArray(): {
|
|
10
32
|
sorted: number[];
|
|
11
33
|
add(index: number, value: ColumnValue | undefined): void;
|
package/dist/reducers/rolling.js
CHANGED
|
@@ -51,6 +51,71 @@ export function rollingOrderedEntries(pick) {
|
|
|
51
51
|
},
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* [PND-LIVFIX] Ordered entries that tolerate removal of ANY index, not only
|
|
56
|
+
* the head. `rollingOrderedEntries` above is a forward-sliding window: it
|
|
57
|
+
* assumes evictions arrive oldest-added-first, which holds for append-only
|
|
58
|
+
* sources but not for a `reorder` source with retention, whose sorted-prefix
|
|
59
|
+
* eviction can drop a middle or the newest arrival — and then `first` /
|
|
60
|
+
* `last` kept reporting an evicted value. Entries live in a `Map` keyed by
|
|
61
|
+
* index (insertion order = arrival order) so any index removes in O(1);
|
|
62
|
+
* `first` is the map's first value and `last` is a tracked tail index,
|
|
63
|
+
* re-derived by an O(n) scan when the tail itself is evicted — on a
|
|
64
|
+
* reorder source that is the headline case (the newest arrival being the
|
|
65
|
+
* sorted prefix), so `last` is O(n) per such eviction and O(1) otherwise.
|
|
66
|
+
*/
|
|
67
|
+
export function rollingIndexedEntries(pick) {
|
|
68
|
+
const items = new Map();
|
|
69
|
+
let tail;
|
|
70
|
+
return {
|
|
71
|
+
add(index, value) {
|
|
72
|
+
if (value === undefined)
|
|
73
|
+
return;
|
|
74
|
+
items.set(index, value);
|
|
75
|
+
if (tail === undefined || index > tail)
|
|
76
|
+
tail = index;
|
|
77
|
+
},
|
|
78
|
+
remove(index, value) {
|
|
79
|
+
if (value === undefined)
|
|
80
|
+
return;
|
|
81
|
+
if (!items.delete(index))
|
|
82
|
+
return;
|
|
83
|
+
if (index === tail) {
|
|
84
|
+
tail = undefined;
|
|
85
|
+
for (const k of items.keys())
|
|
86
|
+
if (tail === undefined || k > tail)
|
|
87
|
+
tail = k;
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
snapshot() {
|
|
91
|
+
if (items.size === 0)
|
|
92
|
+
return undefined;
|
|
93
|
+
if (pick === 'first')
|
|
94
|
+
return items.values().next().value;
|
|
95
|
+
return tail === undefined ? undefined : items.get(tail);
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* [PND-LIVFIX] `min` / `max` over a sorted array — removal by value, so the
|
|
101
|
+
* extreme is exact whatever order evictions arrive in. O(n) per insert /
|
|
102
|
+
* remove (a `splice`), against the monotone deque's amortised O(1); it is
|
|
103
|
+
* selected only for sources whose eviction order is not arrival order
|
|
104
|
+
* (`reorder` + retention), where the deque is wrong rather than slow.
|
|
105
|
+
*/
|
|
106
|
+
export function rollingSortedExtreme(pick) {
|
|
107
|
+
const state = rollingSortedArray();
|
|
108
|
+
return {
|
|
109
|
+
add: state.add,
|
|
110
|
+
remove: state.remove,
|
|
111
|
+
snapshot() {
|
|
112
|
+
const s = state.sorted;
|
|
113
|
+
if (s.length === 0)
|
|
114
|
+
return undefined;
|
|
115
|
+
return pick === 'min' ? s[0] : s[s.length - 1];
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
}
|
|
54
119
|
export function rollingSortedArray() {
|
|
55
120
|
const sorted = [];
|
|
56
121
|
function bisect(v) {
|