@synnaxlabs/client 0.49.0 → 0.49.3
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/.turbo/turbo-build.log +6 -6
- package/dist/client.cjs +33 -31
- package/dist/client.js +3795 -3637
- package/dist/src/framer/client.d.ts +3 -0
- package/dist/src/framer/client.d.ts.map +1 -1
- package/dist/src/framer/external.d.ts +1 -0
- package/dist/src/framer/external.d.ts.map +1 -1
- package/dist/src/framer/iterator.d.ts +5 -0
- package/dist/src/framer/iterator.d.ts.map +1 -1
- package/dist/src/framer/reader.d.ts +18 -0
- package/dist/src/framer/reader.d.ts.map +1 -0
- package/dist/src/framer/reader.spec.d.ts +2 -0
- package/dist/src/framer/reader.spec.d.ts.map +1 -0
- package/package.json +5 -5
- package/src/framer/client.ts +12 -15
- package/src/framer/external.ts +1 -0
- package/src/framer/iterator.spec.ts +67 -0
- package/src/framer/iterator.ts +7 -0
- package/src/framer/reader.spec.ts +865 -0
- package/src/framer/reader.ts +272 -0
|
@@ -3,6 +3,7 @@ import { CrudeSeries, CrudeTimeRange, CrudeTimeStamp, MultiSeries } from '@synna
|
|
|
3
3
|
import { channel } from '../channel';
|
|
4
4
|
import { Frame } from './frame';
|
|
5
5
|
import { Iterator, IteratorConfig } from './iterator';
|
|
6
|
+
import { ReadRequest } from './reader';
|
|
6
7
|
import { Streamer, StreamerConfig } from './streamer';
|
|
7
8
|
import { Writer, WriterConfig } from './writer';
|
|
8
9
|
import { ontology } from '../ontology';
|
|
@@ -18,6 +19,7 @@ export declare class Client {
|
|
|
18
19
|
private readonly streamClient;
|
|
19
20
|
private readonly retriever;
|
|
20
21
|
private readonly deleter;
|
|
22
|
+
private readonly reader;
|
|
21
23
|
constructor(stream: WebSocketClient, unary: UnaryClient, retriever: channel.Retriever);
|
|
22
24
|
/**
|
|
23
25
|
* Opens a new iterator over the given channels within the provided time range.
|
|
@@ -53,6 +55,7 @@ export declare class Client {
|
|
|
53
55
|
write(start: CrudeTimeStamp, data: Record<channel.KeyOrName, CrudeSeries>): Promise<void>;
|
|
54
56
|
read(tr: CrudeTimeRange, channel: channel.KeyOrName): Promise<MultiSeries>;
|
|
55
57
|
read(tr: CrudeTimeRange, channels: channel.Params): Promise<Frame>;
|
|
58
|
+
read(request: ReadRequest): Promise<ReadableStream<Uint8Array>>;
|
|
56
59
|
private readFrame;
|
|
57
60
|
readLatest(channel: channel.KeyOrName, n: number): Promise<MultiSeries>;
|
|
58
61
|
readLatest(channels: channel.Params, n: number): Promise<Frame>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/framer/client.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,WAAW,EAGjB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAa,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EAAgB,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,EAAE,MAAM,EAAE,KAAK,YAAY,EAAc,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,eAAO,MAAM,UAAU,2BAA6C,CAAC;AACrE,eAAO,MAAM,gBAAgB;;;;;;CAAiB,CAAC;AAE/C,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkB;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/framer/client.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,WAAW,EAGjB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAa,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAgB,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,EAAE,MAAM,EAAE,KAAK,YAAY,EAAc,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,eAAO,MAAM,UAAU,2BAA6C,CAAC;AACrE,eAAO,MAAM,gBAAgB;;;;;;CAAiB,CAAC;AAE/C,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkB;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAG9B,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,OAAO,CAAC,SAAS;IAQ9B;;;;;;;OAOG;IACG,YAAY,CAChB,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,OAAO,CAAC,MAAM,EACxB,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAIvD;;;;;;;;;;OAUG;IACG,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC;IAIvD,KAAK,CACT,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,OAAO,CAAC,SAAS,EAC1B,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,IAAI,CAAC;IAEV,KAAK,CACT,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,OAAO,CAAC,WAAW,EAC7B,IAAI,EAAE,WAAW,EAAE,GAClB,OAAO,CAAC,IAAI,CAAC;IAEV,KAAK,CACT,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,WAAW,CAAC,GAC3C,OAAO,CAAC,IAAI,CAAC;IAuCV,IAAI,CAAC,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IAC1E,IAAI,CAAC,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAClE,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;YAYvD,SAAS;IAcjB,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAEvE,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;YAYvD,gBAAgB;IAcxB,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAOjF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"external.d.ts","sourceRoot":"","sources":["../../../src/framer/external.ts"],"names":[],"mappings":"AASA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"external.d.ts","sourceRoot":"","sources":["../../../src/framer/external.ts"],"names":[],"mappings":"AASA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC"}
|
|
@@ -8,6 +8,11 @@ export interface IteratorConfig {
|
|
|
8
8
|
* resulting from a call to next with {@link AUTO_SPAN}.
|
|
9
9
|
*/
|
|
10
10
|
chunkSize?: number;
|
|
11
|
+
/**
|
|
12
|
+
* downsampleFactor is the factor to downsample the data by. If downsampleFactor is
|
|
13
|
+
* less than or equal to 1, no downsampling will be performed.
|
|
14
|
+
*/
|
|
15
|
+
downsampleFactor?: number;
|
|
11
16
|
}
|
|
12
17
|
/**
|
|
13
18
|
* Used to iterate over a clusters telemetry in time-order. It should not be
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iterator.d.ts","sourceRoot":"","sources":["../../../src/framer/iterator.ts"],"names":[],"mappings":"AASA,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,cAAc,EAGnB,QAAQ,EAET,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,KAAK,EAAU,MAAM,gBAAgB,CAAC;AAG/C,eAAO,MAAM,SAAS,UAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"iterator.d.ts","sourceRoot":"","sources":["../../../src/framer/iterator.ts"],"names":[],"mappings":"AASA,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,cAAc,EAGnB,QAAQ,EAET,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,KAAK,EAAU,MAAM,gBAAgB,CAAC;AAG/C,eAAO,MAAM,SAAS,UAAmB,CAAC;AAuC1C,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwC;IAC/D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,KAAK,EAAE,KAAK,CAAC;IAEb,OAAO;IAMP;;;;;;;;;;OAUG;WACU,KAAK,CAChB,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,OAAO,CAAC,MAAM,EACxB,SAAS,EAAE,OAAO,CAAC,SAAS,EAC5B,MAAM,EAAE,YAAY,EACpB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,QAAQ,CAAC;IAcpB;;;;;;;;;;OAUG;IACG,IAAI,CAAC,IAAI,GAAE,aAAyB,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7D;;;;;;;;;;OAUG;IACG,IAAI,CAAC,IAAI,GAAE,aAAyB,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7D;;;;;;;OAOG;IACG,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAInC;;;;;;OAMG;IACG,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAIlC;;;;;;;OAOG;IACG,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IAIrD;;;;;;;OAOG;IACG,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IAIrD;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/B;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC;YAIhD,OAAO;CAStB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { WebSocketClient } from '@synnaxlabs/freighter';
|
|
2
|
+
import { CrudeTimeRange } from '@synnaxlabs/x';
|
|
3
|
+
import { channel } from '../channel';
|
|
4
|
+
import { IteratorConfig } from './iterator';
|
|
5
|
+
export interface ReadRequest {
|
|
6
|
+
channels: channel.Params;
|
|
7
|
+
timeRange: CrudeTimeRange;
|
|
8
|
+
channelNames?: Record<channel.KeyOrName, string>;
|
|
9
|
+
responseType: "csv";
|
|
10
|
+
iteratorConfig?: IteratorConfig;
|
|
11
|
+
}
|
|
12
|
+
export declare class Reader {
|
|
13
|
+
private readonly retriever;
|
|
14
|
+
private readonly streamClient;
|
|
15
|
+
constructor(retriever: channel.Retriever, streamClient: WebSocketClient);
|
|
16
|
+
read(request: ReadRequest): Promise<ReadableStream<Uint8Array>>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../../src/framer/reader.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,KAAK,cAAc,EAAgB,MAAM,eAAe,CAAC;AAElE,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAElE,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC;IACzB,SAAS,EAAE,cAAc,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACjD,YAAY,EAAE,KAAK,CAAC;IACpB,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkB;gBAEnC,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,YAAY,EAAE,eAAe;IAKjE,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;CAiCtE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reader.spec.d.ts","sourceRoot":"","sources":["../../../src/framer/reader.spec.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synnaxlabs/client",
|
|
3
|
-
"version": "0.49.
|
|
3
|
+
"version": "0.49.3",
|
|
4
4
|
"description": "The Synnax Client Library",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"synnax",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"async-mutex": "^0.5.0",
|
|
28
28
|
"zod": "^4.1.12",
|
|
29
|
-
"@synnaxlabs/
|
|
30
|
-
"@synnaxlabs/
|
|
29
|
+
"@synnaxlabs/x": "^0.49.3",
|
|
30
|
+
"@synnaxlabs/freighter": "^0.49.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@vitest/coverage-v8": "^3.2.4",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"vite": "^7.1.12",
|
|
39
39
|
"vitest": "^3.2.4",
|
|
40
40
|
"@synnaxlabs/tsconfig": "^0.43.0",
|
|
41
|
-
"
|
|
42
|
-
"
|
|
41
|
+
"eslint-config-synnaxlabs": "^0.43.0",
|
|
42
|
+
"@synnaxlabs/vite-plugin": "^0.43.0"
|
|
43
43
|
},
|
|
44
44
|
"type": "module",
|
|
45
45
|
"types": "dist/src/index.d.ts",
|
package/src/framer/client.ts
CHANGED
|
@@ -21,6 +21,7 @@ import { channel } from "@/channel";
|
|
|
21
21
|
import { Deleter } from "@/framer/deleter";
|
|
22
22
|
import { Frame } from "@/framer/frame";
|
|
23
23
|
import { AUTO_SPAN, Iterator, type IteratorConfig } from "@/framer/iterator";
|
|
24
|
+
import { Reader, type ReadRequest } from "@/framer/reader";
|
|
24
25
|
import { openStreamer, type Streamer, type StreamerConfig } from "@/framer/streamer";
|
|
25
26
|
import { Writer, type WriterConfig, WriterMode } from "@/framer/writer";
|
|
26
27
|
import { ontology } from "@/ontology";
|
|
@@ -32,6 +33,7 @@ export class Client {
|
|
|
32
33
|
private readonly streamClient: WebSocketClient;
|
|
33
34
|
private readonly retriever: channel.Retriever;
|
|
34
35
|
private readonly deleter: Deleter;
|
|
36
|
+
private readonly reader: Reader;
|
|
35
37
|
|
|
36
38
|
constructor(
|
|
37
39
|
stream: WebSocketClient,
|
|
@@ -41,6 +43,7 @@ export class Client {
|
|
|
41
43
|
this.streamClient = stream;
|
|
42
44
|
this.retriever = retriever;
|
|
43
45
|
this.deleter = new Deleter(unary);
|
|
46
|
+
this.reader = new Reader(retriever, stream);
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
/**
|
|
@@ -140,15 +143,15 @@ export class Client {
|
|
|
140
143
|
}
|
|
141
144
|
|
|
142
145
|
async read(tr: CrudeTimeRange, channel: channel.KeyOrName): Promise<MultiSeries>;
|
|
143
|
-
|
|
144
146
|
async read(tr: CrudeTimeRange, channels: channel.Params): Promise<Frame>;
|
|
145
|
-
|
|
147
|
+
async read(request: ReadRequest): Promise<ReadableStream<Uint8Array>>;
|
|
146
148
|
async read(
|
|
147
|
-
tr: CrudeTimeRange,
|
|
148
|
-
channels
|
|
149
|
-
): Promise<MultiSeries | Frame
|
|
150
|
-
|
|
151
|
-
const
|
|
149
|
+
tr: CrudeTimeRange | ReadRequest,
|
|
150
|
+
channels?: channel.Params,
|
|
151
|
+
): Promise<MultiSeries | Frame | ReadableStream<Uint8Array>> {
|
|
152
|
+
if (!("start" in tr)) return this.reader.read(tr);
|
|
153
|
+
const { single } = channel.analyzeParams(channels!);
|
|
154
|
+
const fr = await this.readFrame(tr, channels!);
|
|
152
155
|
if (single) return fr.get(channels as channel.KeyOrName);
|
|
153
156
|
return fr;
|
|
154
157
|
}
|
|
@@ -199,13 +202,7 @@ export class Client {
|
|
|
199
202
|
const { normalized, variant } = channel.analyzeParams(channels);
|
|
200
203
|
const bounds = new TimeRange(timeRange);
|
|
201
204
|
if (variant === "keys")
|
|
202
|
-
return await this.deleter.delete({
|
|
203
|
-
|
|
204
|
-
bounds,
|
|
205
|
-
});
|
|
206
|
-
return await this.deleter.delete({
|
|
207
|
-
names: normalized as string[],
|
|
208
|
-
bounds,
|
|
209
|
-
});
|
|
205
|
+
return await this.deleter.delete({ keys: normalized as channel.Key[], bounds });
|
|
206
|
+
return await this.deleter.delete({ names: normalized as string[], bounds });
|
|
210
207
|
}
|
|
211
208
|
}
|
package/src/framer/external.ts
CHANGED
|
@@ -99,4 +99,71 @@ describe("Iterator", () => {
|
|
|
99
99
|
await iter.close();
|
|
100
100
|
}
|
|
101
101
|
});
|
|
102
|
+
test("downsample factor 2", async () => {
|
|
103
|
+
const channels = await newIndexedPair(client);
|
|
104
|
+
const [idx_ch, data_ch] = channels;
|
|
105
|
+
const writer = await client.openWriter({ start: TimeStamp.SECOND, channels });
|
|
106
|
+
await writer.write({
|
|
107
|
+
[idx_ch.key]: secondsLinspace(1, 8),
|
|
108
|
+
[data_ch.key]: new Float64Array([1, 2, 3, 4, 5, 6, 7, 8]),
|
|
109
|
+
});
|
|
110
|
+
await writer.close();
|
|
111
|
+
const iter = await client.openIterator(TimeRange.MAX, channels, {
|
|
112
|
+
downsampleFactor: 2,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
expect(await iter.seekFirst()).toBe(true);
|
|
117
|
+
expect(await iter.next(AUTO_SPAN)).toBe(true);
|
|
118
|
+
// [1, 2, 3, 4, 5, 6, 7, 8] downsampled by 2 = [1, 3, 5, 7]
|
|
119
|
+
expect(iter.value.get(data_ch.key).data).toEqual(new Float64Array([1, 3, 5, 7]));
|
|
120
|
+
expect(await iter.next(AUTO_SPAN)).toBe(false);
|
|
121
|
+
} finally {
|
|
122
|
+
await iter.close();
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
test("downsample factor 3", async () => {
|
|
126
|
+
const channels = await newIndexedPair(client);
|
|
127
|
+
const [idx_ch, data_ch] = channels;
|
|
128
|
+
const writer = await client.openWriter({ start: TimeStamp.SECOND, channels });
|
|
129
|
+
await writer.write({
|
|
130
|
+
[idx_ch.key]: secondsLinspace(1, 9),
|
|
131
|
+
[data_ch.key]: new Float64Array([1, 2, 3, 4, 5, 6, 7, 8, 9]),
|
|
132
|
+
});
|
|
133
|
+
await writer.close();
|
|
134
|
+
const iter = await client.openIterator(TimeRange.MAX, channels, {
|
|
135
|
+
downsampleFactor: 3,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
expect(await iter.seekFirst()).toBe(true);
|
|
140
|
+
expect(await iter.next(AUTO_SPAN)).toBe(true);
|
|
141
|
+
// [1, 2, 3, 4, 5, 6, 7, 8, 9] downsampled by 3 = [1, 4, 7]
|
|
142
|
+
expect(iter.value.get(data_ch.key).data).toEqual(new Float64Array([1, 4, 7]));
|
|
143
|
+
expect(await iter.next(AUTO_SPAN)).toBe(false);
|
|
144
|
+
} finally {
|
|
145
|
+
await iter.close();
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
test("no downsample when factor is 1", async () => {
|
|
149
|
+
const channels = await newIndexedPair(client);
|
|
150
|
+
const [idx_ch, data_ch] = channels;
|
|
151
|
+
const writer = await client.openWriter({ start: TimeStamp.SECOND, channels });
|
|
152
|
+
await writer.write({
|
|
153
|
+
[idx_ch.key]: secondsLinspace(1, 4),
|
|
154
|
+
[data_ch.key]: new Float64Array([1, 2, 3, 4]),
|
|
155
|
+
});
|
|
156
|
+
await writer.close();
|
|
157
|
+
const iter = await client.openIterator(TimeRange.MAX, channels, {
|
|
158
|
+
downsampleFactor: 1,
|
|
159
|
+
});
|
|
160
|
+
try {
|
|
161
|
+
expect(await iter.seekFirst()).toBe(true);
|
|
162
|
+
expect(await iter.next(AUTO_SPAN)).toBe(true);
|
|
163
|
+
expect(iter.value.get(data_ch.key).data).toEqual(new Float64Array([1, 2, 3, 4]));
|
|
164
|
+
expect(await iter.next(AUTO_SPAN)).toBe(false);
|
|
165
|
+
} finally {
|
|
166
|
+
await iter.close();
|
|
167
|
+
}
|
|
168
|
+
});
|
|
102
169
|
});
|
package/src/framer/iterator.ts
CHANGED
|
@@ -51,6 +51,7 @@ const reqZ = z.object({
|
|
|
51
51
|
stamp: TimeStamp.z.optional(),
|
|
52
52
|
keys: channel.keyZ.array().optional(),
|
|
53
53
|
chunkSize: z.number().optional(),
|
|
54
|
+
downsampleFactor: z.int().optional(),
|
|
54
55
|
});
|
|
55
56
|
interface Request extends z.infer<typeof reqZ> {}
|
|
56
57
|
|
|
@@ -67,6 +68,11 @@ export interface IteratorConfig {
|
|
|
67
68
|
* resulting from a call to next with {@link AUTO_SPAN}.
|
|
68
69
|
*/
|
|
69
70
|
chunkSize?: number;
|
|
71
|
+
/**
|
|
72
|
+
* downsampleFactor is the factor to downsample the data by. If downsampleFactor is
|
|
73
|
+
* less than or equal to 1, no downsampling will be performed.
|
|
74
|
+
*/
|
|
75
|
+
downsampleFactor?: number;
|
|
70
76
|
}
|
|
71
77
|
|
|
72
78
|
/**
|
|
@@ -114,6 +120,7 @@ export class Iterator {
|
|
|
114
120
|
keys: Array.from(adapter.keys),
|
|
115
121
|
bounds: new TimeRange(tr),
|
|
116
122
|
chunkSize: opts.chunkSize ?? 1e5,
|
|
123
|
+
downsampleFactor: opts.downsampleFactor ?? 1,
|
|
117
124
|
});
|
|
118
125
|
return iter;
|
|
119
126
|
}
|