polfan-server-js-client 0.2.86 → 0.2.87
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/.idea/workspace.xml +23 -27
- package/build/index.cjs.js +29 -9
- package/build/index.cjs.js.map +1 -1
- package/build/index.umd.js +1 -1
- package/build/index.umd.js.map +1 -1
- package/build/types/state-tracker/TopicHistoryWindow.d.ts +12 -3
- package/package.json +1 -1
- package/src/state-tracker/TopicHistoryWindow.ts +32 -10
- package/tests/history-window.test.ts +35 -1
|
@@ -30,6 +30,7 @@ export declare abstract class TraversableRemoteCollection<ItemT, EventMapT exten
|
|
|
30
30
|
current: WindowState;
|
|
31
31
|
ongoing?: WindowState;
|
|
32
32
|
limit: number | null;
|
|
33
|
+
retainRatio: number;
|
|
33
34
|
fetchLimit: number;
|
|
34
35
|
lastFetchCount: number;
|
|
35
36
|
oldestId: string | null;
|
|
@@ -43,15 +44,23 @@ export declare abstract class TraversableRemoteCollection<ItemT, EventMapT exten
|
|
|
43
44
|
*/
|
|
44
45
|
set fetchLimit(value: number);
|
|
45
46
|
/**
|
|
46
|
-
* Maximum
|
|
47
|
+
* Maximum number of items stored in window (High Watermark).
|
|
47
48
|
* Null for unlimited.
|
|
48
49
|
*/
|
|
49
50
|
get limit(): number | null;
|
|
50
51
|
/**
|
|
51
|
-
* Maximum
|
|
52
|
+
* Maximum number of items stored in window (High Watermark).
|
|
52
53
|
* Null for unlimited.
|
|
53
54
|
*/
|
|
54
55
|
set limit(value: number | null);
|
|
56
|
+
/**
|
|
57
|
+
* Percentage of limit to keep when trimming.
|
|
58
|
+
*/
|
|
59
|
+
get retainRatio(): number;
|
|
60
|
+
/**
|
|
61
|
+
* Percentage of limit to keep when trimming.
|
|
62
|
+
*/
|
|
63
|
+
set retainRatio(value: number);
|
|
55
64
|
get hasLatest(): boolean;
|
|
56
65
|
get hasOldest(): boolean;
|
|
57
66
|
abstract createMirror(): TraversableRemoteCollection<ItemT, EventMapT>;
|
|
@@ -65,7 +74,7 @@ export declare abstract class TraversableRemoteCollection<ItemT, EventMapT exten
|
|
|
65
74
|
protected refreshFetchedState(): Promise<void>;
|
|
66
75
|
protected addItems(newItems: ItemT[], to: 'head' | 'tail'): void;
|
|
67
76
|
/**
|
|
68
|
-
* Return array with messages
|
|
77
|
+
* Return array with messages trimmed using High/Low Watermark strategy.
|
|
69
78
|
*/
|
|
70
79
|
private trimItemsArrayToLimit;
|
|
71
80
|
}
|
package/package.json
CHANGED
|
@@ -40,14 +40,16 @@ export abstract class TraversableRemoteCollection<
|
|
|
40
40
|
protected internalState: {
|
|
41
41
|
current: WindowState,
|
|
42
42
|
ongoing?: WindowState,
|
|
43
|
-
limit: number | null,
|
|
43
|
+
limit: number | null, // Acts as High Watermark
|
|
44
|
+
retainRatio: number, // Percentage of limit to keep when trimming
|
|
44
45
|
fetchLimit: number,
|
|
45
46
|
lastFetchCount: number,
|
|
46
47
|
oldestId: string | null,
|
|
47
48
|
} = {
|
|
48
49
|
current: WindowState.LIVE,
|
|
49
50
|
ongoing: undefined,
|
|
50
|
-
limit:
|
|
51
|
+
limit: 1000,
|
|
52
|
+
retainRatio: 1,
|
|
51
53
|
fetchLimit: 50,
|
|
52
54
|
lastFetchCount: 0,
|
|
53
55
|
oldestId: null,
|
|
@@ -68,7 +70,7 @@ export abstract class TraversableRemoteCollection<
|
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
/**
|
|
71
|
-
* Maximum
|
|
73
|
+
* Maximum number of items stored in window (High Watermark).
|
|
72
74
|
* Null for unlimited.
|
|
73
75
|
*/
|
|
74
76
|
public get limit(): number | null {
|
|
@@ -76,13 +78,27 @@ export abstract class TraversableRemoteCollection<
|
|
|
76
78
|
}
|
|
77
79
|
|
|
78
80
|
/**
|
|
79
|
-
* Maximum
|
|
81
|
+
* Maximum number of items stored in window (High Watermark).
|
|
80
82
|
* Null for unlimited.
|
|
81
83
|
*/
|
|
82
84
|
public set limit(value: number | null) {
|
|
83
85
|
this.internalState.limit = value;
|
|
84
86
|
}
|
|
85
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Percentage of limit to keep when trimming.
|
|
90
|
+
*/
|
|
91
|
+
public get retainRatio(): number {
|
|
92
|
+
return this.internalState.retainRatio;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Percentage of limit to keep when trimming.
|
|
97
|
+
*/
|
|
98
|
+
public set retainRatio(value: number) {
|
|
99
|
+
this.internalState.retainRatio = value;
|
|
100
|
+
}
|
|
101
|
+
|
|
86
102
|
public get hasLatest(): boolean {
|
|
87
103
|
return [WindowState.LATEST, WindowState.LIVE].includes(this.state);
|
|
88
104
|
}
|
|
@@ -111,7 +127,7 @@ export abstract class TraversableRemoteCollection<
|
|
|
111
127
|
this.internalState.ongoing = undefined;
|
|
112
128
|
}
|
|
113
129
|
|
|
114
|
-
this.deleteAll();
|
|
130
|
+
this._items.deleteAll(); // Directly call deleteAll to prevent event emit.
|
|
115
131
|
this.addItems(result, 'tail');
|
|
116
132
|
this.internalState.current = WindowState.LATEST;
|
|
117
133
|
}
|
|
@@ -205,25 +221,31 @@ export abstract class TraversableRemoteCollection<
|
|
|
205
221
|
result = this.trimItemsArrayToLimit([...this.items, ...newItems], 'head');
|
|
206
222
|
}
|
|
207
223
|
|
|
208
|
-
this.deleteAll();
|
|
224
|
+
this._items.deleteAll(); // Directly call deleteAll to prevent event emit.
|
|
209
225
|
this.set(...result);
|
|
210
226
|
}
|
|
211
227
|
|
|
212
228
|
/**
|
|
213
|
-
* Return array with messages
|
|
229
|
+
* Return array with messages trimmed using High/Low Watermark strategy.
|
|
214
230
|
*/
|
|
215
231
|
private trimItemsArrayToLimit(items: ItemT[], from: 'head' | 'tail'): ItemT[] {
|
|
216
|
-
|
|
232
|
+
const highWatermark = this.limit;
|
|
233
|
+
|
|
234
|
+
if (highWatermark === null || items.length <= highWatermark) {
|
|
217
235
|
return items;
|
|
218
236
|
}
|
|
219
237
|
|
|
238
|
+
const lowWatermark = Math.floor(highWatermark * this.internalState.retainRatio);
|
|
239
|
+
|
|
220
240
|
if (from === 'head') {
|
|
221
|
-
return items.slice(-
|
|
241
|
+
return items.slice(-lowWatermark);
|
|
222
242
|
}
|
|
223
243
|
|
|
224
244
|
if (from === 'tail') {
|
|
225
|
-
return items.slice(0,
|
|
245
|
+
return items.slice(0, lowWatermark);
|
|
226
246
|
}
|
|
247
|
+
|
|
248
|
+
return items;
|
|
227
249
|
}
|
|
228
250
|
}
|
|
229
251
|
|
|
@@ -69,7 +69,8 @@ class TestableHistoryWindow extends TraversableRemoteCollection<SimpleMessage> {
|
|
|
69
69
|
test('history window - fresh instance', async () => {
|
|
70
70
|
const window = new TestableHistoryWindow();
|
|
71
71
|
expect(window.items).toHaveLength(0);
|
|
72
|
-
expect(window.limit).toEqual(
|
|
72
|
+
expect(window.limit).toEqual(1000);
|
|
73
|
+
expect(window.retainRatio).toEqual(1);
|
|
73
74
|
});
|
|
74
75
|
|
|
75
76
|
test('history window - states change', async () => {
|
|
@@ -251,3 +252,36 @@ test('history window - hasOldest false when in LATEST and length == fetchLimit',
|
|
|
251
252
|
expect(window.fetchLimit).toEqual(3);
|
|
252
253
|
expect(window.hasOldest).toBeFalsy();
|
|
253
254
|
});
|
|
255
|
+
|
|
256
|
+
test('history window - high/low watermark limit (retainRatio)', async () => {
|
|
257
|
+
const window = new TestableHistoryWindow();
|
|
258
|
+
window.limit = 6; // High Watermark
|
|
259
|
+
window.retainRatio = 0.5; // Low Watermark target = 6 * 0.5 = 3
|
|
260
|
+
window.fetchLimit = 3;
|
|
261
|
+
|
|
262
|
+
await window.resetToLatest(); // [7, 8, 9]
|
|
263
|
+
|
|
264
|
+
expect(window.items).toHaveLength(3);
|
|
265
|
+
|
|
266
|
+
await window.fetchPrevious(); // [4, 5, 6] added to 'head' -> [4, 5, 6, 7, 8, 9]
|
|
267
|
+
|
|
268
|
+
expect(window.items).toHaveLength(6);
|
|
269
|
+
[4, 5, 6, 7, 8, 9].forEach(id => expect(window.items.map(item => item.id)).toContain(id));
|
|
270
|
+
|
|
271
|
+
await window.fetchPrevious(); // [1, 2, 3] added to 'head' -> [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
272
|
+
|
|
273
|
+
expect(window.items).toHaveLength(3);
|
|
274
|
+
[1, 2, 3].forEach(id => expect(window.items.map(item => item.id)).toContain(id));
|
|
275
|
+
expect(window.state).toEqual(WindowState.PAST);
|
|
276
|
+
|
|
277
|
+
await window.fetchNext(); // [4, 5, 6] added to 'tail' -> [1, 2, 3, 4, 5, 6]
|
|
278
|
+
|
|
279
|
+
expect(window.items).toHaveLength(6);
|
|
280
|
+
[1, 2, 3, 4, 5, 6].forEach(id => expect(window.items.map(item => item.id)).toContain(id));
|
|
281
|
+
|
|
282
|
+
await window.fetchNext(); // [7, 8, 9] added to 'tail' -> [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
283
|
+
|
|
284
|
+
expect(window.items).toHaveLength(3);
|
|
285
|
+
[7, 8, 9].forEach(id => expect(window.items.map(item => item.id)).toContain(id));
|
|
286
|
+
expect(window.state).toEqual(WindowState.LATEST);
|
|
287
|
+
});
|