@synnaxlabs/client 0.54.2 → 0.56.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/.turbo/turbo-build.log +10 -13
- package/dist/client.cjs +60 -42
- package/dist/client.js +8037 -6265
- package/dist/src/access/policy/client.d.ts +70 -80
- package/dist/src/access/policy/client.d.ts.map +1 -1
- package/dist/src/access/policy/types.gen.d.ts +18 -20
- package/dist/src/access/policy/types.gen.d.ts.map +1 -1
- package/dist/src/access/role/client.d.ts.map +1 -1
- package/dist/src/access/role/types.gen.d.ts +2 -2
- package/dist/src/actions/actions.d.ts +68 -0
- package/dist/src/actions/actions.d.ts.map +1 -0
- package/dist/src/actions/actions.spec.d.ts +2 -0
- package/dist/src/actions/actions.spec.d.ts.map +1 -0
- package/dist/src/actions/external.d.ts +2 -0
- package/dist/src/actions/external.d.ts.map +1 -0
- package/dist/src/actions/index.d.ts +2 -0
- package/dist/src/actions/index.d.ts.map +1 -0
- package/dist/src/arc/arc.spec.d.ts +2 -0
- package/dist/src/arc/arc.spec.d.ts.map +1 -0
- package/dist/src/arc/client.d.ts.map +1 -1
- package/dist/src/arc/compiler/types.gen.d.ts +1 -1
- package/dist/src/arc/compiler/types.gen.d.ts.map +1 -1
- package/dist/src/arc/graph/types.gen.d.ts +40 -40
- package/dist/src/arc/graph/types.gen.d.ts.map +1 -1
- package/dist/src/arc/ir/types.gen.d.ts +202 -233
- package/dist/src/arc/ir/types.gen.d.ts.map +1 -1
- package/dist/src/arc/module/types.gen.d.ts +63 -82
- package/dist/src/arc/module/types.gen.d.ts.map +1 -1
- package/dist/src/arc/program/types.gen.d.ts +63 -82
- package/dist/src/arc/program/types.gen.d.ts.map +1 -1
- package/dist/src/arc/types/types.gen.d.ts +11 -11
- package/dist/src/arc/types/types.gen.d.ts.map +1 -1
- package/dist/src/arc/types.gen.d.ts +139 -158
- package/dist/src/arc/types.gen.d.ts.map +1 -1
- package/dist/src/auth/auth.d.ts +3 -3
- package/dist/src/auth/auth.d.ts.map +1 -1
- package/dist/src/channel/client.d.ts +2 -2
- package/dist/src/channel/client.d.ts.map +1 -1
- package/dist/src/channel/retriever.d.ts +5 -8
- package/dist/src/channel/retriever.d.ts.map +1 -1
- package/dist/src/channel/types.gen.d.ts +3 -3
- package/dist/src/channel/types.gen.d.ts.map +1 -1
- package/dist/src/channel/writer.d.ts.map +1 -1
- package/dist/src/client.d.ts +5 -0
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/connection/checker.d.ts +17 -2
- package/dist/src/connection/checker.d.ts.map +1 -1
- package/dist/src/control/state.d.ts.map +1 -1
- package/dist/src/device/client.d.ts.map +1 -1
- package/dist/src/device/types.gen.d.ts +6 -8
- package/dist/src/device/types.gen.d.ts.map +1 -1
- package/dist/src/errors.d.ts +2 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/framer/adapter.d.ts.map +1 -1
- package/dist/src/framer/client.d.ts +2 -2
- package/dist/src/framer/client.d.ts.map +1 -1
- package/dist/src/framer/codec.d.ts +9 -1
- package/dist/src/framer/codec.d.ts.map +1 -1
- package/dist/src/framer/deleter.d.ts.map +1 -1
- package/dist/src/framer/frame.d.ts +1 -1
- package/dist/src/framer/iterator.d.ts +84 -3
- package/dist/src/framer/iterator.d.ts.map +1 -1
- package/dist/src/framer/streamProxy.d.ts.map +1 -1
- package/dist/src/framer/streamer.d.ts +1 -3
- package/dist/src/framer/streamer.d.ts.map +1 -1
- package/dist/src/framer/types.gen.d.ts +18 -0
- package/dist/src/framer/types.gen.d.ts.map +1 -1
- package/dist/src/framer/writer.d.ts +8 -8
- package/dist/src/framer/writer.d.ts.map +1 -1
- package/dist/src/group/client.d.ts +1 -2
- package/dist/src/group/client.d.ts.map +1 -1
- package/dist/src/group/types.gen.d.ts +2 -2
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/label/client.d.ts +5 -8
- package/dist/src/label/client.d.ts.map +1 -1
- package/dist/src/lineplot/client.d.ts.map +1 -1
- package/dist/src/lineplot/types.gen.d.ts +2 -2
- package/dist/src/log/client.d.ts.map +1 -1
- package/dist/src/log/types.gen.d.ts +2 -2
- package/dist/src/ontology/client.d.ts +1 -3
- package/dist/src/ontology/client.d.ts.map +1 -1
- package/dist/src/ontology/payload.d.ts +12 -16
- package/dist/src/ontology/payload.d.ts.map +1 -1
- package/dist/src/ontology/types.gen.d.ts +1 -2
- package/dist/src/ontology/types.gen.d.ts.map +1 -1
- package/dist/src/ontology/writer.d.ts +5 -10
- package/dist/src/ontology/writer.d.ts.map +1 -1
- package/dist/src/rack/client.d.ts.map +1 -1
- package/dist/src/rack/types.gen.d.ts +3 -3
- package/dist/src/ranger/alias/client.d.ts.map +1 -1
- package/dist/src/ranger/client.d.ts.map +1 -1
- package/dist/src/ranger/kv/client.d.ts.map +1 -1
- package/dist/src/ranger/types.gen.d.ts +6 -6
- package/dist/src/ranger/types.gen.d.ts.map +1 -1
- package/dist/src/ranger/writer.d.ts +2 -3
- package/dist/src/ranger/writer.d.ts.map +1 -1
- package/dist/src/schematic/actions.d.ts +147 -0
- package/dist/src/schematic/actions.d.ts.map +1 -0
- package/dist/src/schematic/actions.gen.d.ts +484 -0
- package/dist/src/schematic/actions.gen.d.ts.map +1 -0
- package/dist/src/schematic/actions.spec.d.ts +2 -0
- package/dist/src/schematic/actions.spec.d.ts.map +1 -0
- package/dist/src/schematic/client.d.ts +53 -2
- package/dist/src/schematic/client.d.ts.map +1 -1
- package/dist/src/schematic/external.d.ts +2 -0
- package/dist/src/schematic/external.d.ts.map +1 -1
- package/dist/src/schematic/symbol/client.d.ts.map +1 -1
- package/dist/src/schematic/symbol/types.gen.d.ts +48 -58
- package/dist/src/schematic/symbol/types.gen.d.ts.map +1 -1
- package/dist/src/schematic/types.gen.d.ts +131 -5
- package/dist/src/schematic/types.gen.d.ts.map +1 -1
- package/dist/src/status/client.d.ts.map +1 -1
- package/dist/src/status/payload.d.ts +3 -3
- package/dist/src/table/actions.d.ts +156 -0
- package/dist/src/table/actions.d.ts.map +1 -0
- package/dist/src/table/actions.gen.d.ts +587 -0
- package/dist/src/table/actions.gen.d.ts.map +1 -0
- package/dist/src/table/client.d.ts +28 -2
- package/dist/src/table/client.d.ts.map +1 -1
- package/dist/src/table/external.d.ts +2 -0
- package/dist/src/table/external.d.ts.map +1 -1
- package/dist/src/table/types.gen.d.ts +71 -4
- package/dist/src/table/types.gen.d.ts.map +1 -1
- package/dist/src/task/client.d.ts.map +1 -1
- package/dist/src/task/types.gen.d.ts +7 -7
- package/dist/src/task/types.gen.d.ts.map +1 -1
- package/dist/src/user/client.d.ts +2 -2
- package/dist/src/user/client.d.ts.map +1 -1
- package/dist/src/user/types.gen.d.ts +2 -2
- package/dist/src/view/client.d.ts.map +1 -1
- package/dist/src/view/types.gen.d.ts +2 -2
- package/dist/src/workspace/client.d.ts.map +1 -1
- package/dist/src/workspace/types.gen.d.ts +3 -3
- package/dist/src/workspace/types.gen.d.ts.map +1 -1
- package/package.json +12 -11
- package/src/access/policy/client.ts +4 -7
- package/src/access/role/client.ts +6 -26
- package/src/actions/actions.spec.ts +229 -0
- package/src/actions/actions.ts +104 -0
- package/src/actions/external.ts +10 -0
- package/src/actions/index.ts +10 -0
- package/src/arc/arc.spec.ts +44 -0
- package/src/arc/client.ts +3 -7
- package/src/arc/compiler/types.gen.ts +2 -1
- package/src/arc/ir/types.gen.ts +102 -48
- package/src/arc/lsp.spec.ts +3 -7
- package/src/arc/types/types.gen.ts +3 -3
- package/src/auth/auth.spec.ts +12 -13
- package/src/auth/auth.ts +48 -34
- package/src/channel/batchRetriever.spec.ts +13 -4
- package/src/channel/channel.spec.ts +13 -0
- package/src/channel/client.ts +8 -6
- package/src/channel/retriever.ts +7 -16
- package/src/channel/types.gen.ts +1 -2
- package/src/channel/writer.ts +4 -20
- package/src/client.ts +3 -0
- package/src/connection/checker.ts +48 -10
- package/src/connection/connection.spec.ts +64 -2
- package/src/control/state.ts +5 -4
- package/src/device/client.ts +5 -8
- package/src/device/device.spec.ts +7 -5
- package/src/device/types.gen.ts +4 -4
- package/src/errors.ts +8 -9
- package/src/framer/adapter.ts +2 -4
- package/src/framer/client.ts +12 -0
- package/src/framer/codec.spec.ts +53 -3
- package/src/framer/codec.ts +58 -25
- package/src/framer/deleter.ts +2 -8
- package/src/framer/iterator.ts +42 -39
- package/src/framer/streamProxy.ts +11 -12
- package/src/framer/streamer.spec.ts +1 -1
- package/src/framer/streamer.ts +2 -7
- package/src/framer/types.gen.ts +20 -0
- package/src/framer/writer.spec.ts +221 -1
- package/src/framer/writer.ts +53 -28
- package/src/group/client.ts +4 -7
- package/src/index.ts +3 -2
- package/src/label/client.ts +6 -16
- package/src/label/label.spec.ts +12 -0
- package/src/lineplot/client.ts +6 -21
- package/src/log/client.ts +6 -21
- package/src/ontology/client.ts +2 -3
- package/src/ontology/ontology.spec.ts +10 -0
- package/src/ontology/types.gen.ts +0 -1
- package/src/ontology/writer.ts +4 -7
- package/src/rack/client.ts +4 -7
- package/src/rack/rack.spec.ts +12 -1
- package/src/ranger/alias/client.ts +6 -11
- package/src/ranger/client.ts +2 -3
- package/src/ranger/kv/client.ts +4 -7
- package/src/ranger/ranger.spec.ts +12 -0
- package/src/ranger/writer.ts +4 -17
- package/src/schematic/access.spec.ts +6 -6
- package/src/schematic/actions.gen.ts +200 -0
- package/src/schematic/actions.spec.ts +699 -0
- package/src/schematic/actions.ts +168 -0
- package/src/schematic/client.ts +34 -30
- package/src/schematic/external.ts +2 -0
- package/src/schematic/schematic.spec.ts +233 -69
- package/src/schematic/symbol/client.spec.ts +33 -9
- package/src/schematic/symbol/client.ts +6 -11
- package/src/schematic/symbol/types.gen.ts +1 -10
- package/src/schematic/types.gen.ts +55 -6
- package/src/status/client.ts +4 -10
- package/src/status/status.spec.ts +7 -6
- package/src/table/access.spec.ts +0 -6
- package/src/table/actions.gen.ts +243 -0
- package/src/table/actions.ts +255 -0
- package/src/table/client.ts +21 -25
- package/src/table/external.ts +2 -0
- package/src/table/table.spec.ts +588 -43
- package/src/table/types.gen.ts +58 -5
- package/src/task/client.ts +14 -20
- package/src/task/task.spec.ts +15 -1
- package/src/task/types.gen.ts +8 -6
- package/src/user/client.ts +6 -11
- package/src/view/client.ts +4 -7
- package/src/view/view.spec.ts +9 -5
- package/src/workspace/client.ts +6 -16
- package/src/workspace/types.gen.ts +2 -1
- package/src/workspace/workspace.spec.ts +14 -1
package/src/framer/iterator.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
|
-
import { type Stream, type
|
|
10
|
+
import { type Stream, type WebSocketClient } from "@synnaxlabs/freighter";
|
|
11
11
|
import {
|
|
12
12
|
type CrudeTimeRange,
|
|
13
13
|
type CrudeTimeSpan,
|
|
@@ -21,31 +21,15 @@ import { z } from "zod";
|
|
|
21
21
|
|
|
22
22
|
import { channel } from "@/channel";
|
|
23
23
|
import { ReadAdapter } from "@/framer/adapter";
|
|
24
|
+
import { WSIteratorCodec } from "@/framer/codec";
|
|
24
25
|
import { Frame, frameZ } from "@/framer/frame";
|
|
25
26
|
import { StreamProxy } from "@/framer/streamProxy";
|
|
27
|
+
import { IteratorCommand, IteratorResponseVariant } from "@/framer/types.gen";
|
|
26
28
|
|
|
27
29
|
export const AUTO_SPAN = new TimeSpan(-1);
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
Next = 1,
|
|
32
|
-
Prev = 2,
|
|
33
|
-
SeekFirst = 3,
|
|
34
|
-
SeekLast = 4,
|
|
35
|
-
SeekLE = 5,
|
|
36
|
-
SeekGE = 6,
|
|
37
|
-
Valid = 7,
|
|
38
|
-
Error = 8,
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
enum ResponseVariant {
|
|
42
|
-
None = 0,
|
|
43
|
-
Ack = 1,
|
|
44
|
-
Data = 2,
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const reqZ = z.object({
|
|
48
|
-
command: z.enum(Command),
|
|
31
|
+
export const iteratorReqZ = z.object({
|
|
32
|
+
command: z.enum(IteratorCommand),
|
|
49
33
|
span: TimeSpan.z.optional(),
|
|
50
34
|
bounds: TimeRange.z.optional(),
|
|
51
35
|
stamp: TimeStamp.z.optional(),
|
|
@@ -53,16 +37,19 @@ const reqZ = z.object({
|
|
|
53
37
|
chunkSize: z.number().optional(),
|
|
54
38
|
downsampleFactor: z.int().optional(),
|
|
55
39
|
});
|
|
56
|
-
interface Request extends z.infer<typeof reqZ> {}
|
|
57
40
|
|
|
58
|
-
|
|
59
|
-
|
|
41
|
+
export interface IteratorRequest extends z.infer<typeof iteratorReqZ> {}
|
|
42
|
+
|
|
43
|
+
export const iteratorResZ = z.object({
|
|
44
|
+
variant: z.enum(IteratorResponseVariant),
|
|
60
45
|
ack: z.boolean(),
|
|
61
|
-
command: z.enum(
|
|
46
|
+
command: z.enum(IteratorCommand),
|
|
62
47
|
error: errors.payloadZ.optional().nullable(),
|
|
63
48
|
frame: frameZ.optional(),
|
|
64
49
|
});
|
|
65
50
|
|
|
51
|
+
export interface IteratorResponse extends z.infer<typeof iteratorResZ> {}
|
|
52
|
+
|
|
66
53
|
export interface IteratorConfig {
|
|
67
54
|
/** chunkSize is the maximum number of samples contained per channel in the frame
|
|
68
55
|
* resulting from a call to next with {@link AUTO_SPAN}.
|
|
@@ -84,11 +71,14 @@ export interface IteratorConfig {
|
|
|
84
71
|
* telemetry between two timestamps, see the SegmentClient.read method.
|
|
85
72
|
*/
|
|
86
73
|
export class Iterator {
|
|
87
|
-
private readonly stream: StreamProxy<typeof
|
|
74
|
+
private readonly stream: StreamProxy<typeof iteratorReqZ, typeof iteratorResZ>;
|
|
88
75
|
private readonly adapter: ReadAdapter;
|
|
89
76
|
value: Frame;
|
|
90
77
|
|
|
91
|
-
private constructor(
|
|
78
|
+
private constructor(
|
|
79
|
+
stream: Stream<typeof iteratorReqZ, typeof iteratorResZ>,
|
|
80
|
+
adapter: ReadAdapter,
|
|
81
|
+
) {
|
|
92
82
|
this.stream = new StreamProxy("Iterator", stream);
|
|
93
83
|
this.value = new Frame();
|
|
94
84
|
this.adapter = adapter;
|
|
@@ -109,14 +99,15 @@ export class Iterator {
|
|
|
109
99
|
tr: CrudeTimeRange,
|
|
110
100
|
channels: channel.Params,
|
|
111
101
|
retriever: channel.Retriever,
|
|
112
|
-
client:
|
|
102
|
+
client: WebSocketClient,
|
|
113
103
|
opts: IteratorConfig = {},
|
|
114
104
|
): Promise<Iterator> {
|
|
115
105
|
const adapter = await ReadAdapter.open(retriever, channels);
|
|
116
|
-
|
|
106
|
+
client = client.withCodec(new WSIteratorCodec(adapter.codec));
|
|
107
|
+
const stream = await client.stream("/frame/iterate", iteratorReqZ, iteratorResZ);
|
|
117
108
|
const iter = new Iterator(stream, adapter);
|
|
118
109
|
await iter.execute({
|
|
119
|
-
command:
|
|
110
|
+
command: IteratorCommand.Open,
|
|
120
111
|
keys: Array.from(adapter.keys),
|
|
121
112
|
bounds: new TimeRange(tr),
|
|
122
113
|
chunkSize: opts.chunkSize ?? 1e5,
|
|
@@ -137,7 +128,10 @@ export class Iterator {
|
|
|
137
128
|
* particular channel or the iterator has accumulated an error.
|
|
138
129
|
*/
|
|
139
130
|
async next(span: CrudeTimeSpan = AUTO_SPAN): Promise<boolean> {
|
|
140
|
-
return await this.execute({
|
|
131
|
+
return await this.execute({
|
|
132
|
+
command: IteratorCommand.Next,
|
|
133
|
+
span: new TimeSpan(span),
|
|
134
|
+
});
|
|
141
135
|
}
|
|
142
136
|
|
|
143
137
|
/**
|
|
@@ -152,7 +146,10 @@ export class Iterator {
|
|
|
152
146
|
* channel or the iterator has accumulated an error.
|
|
153
147
|
*/
|
|
154
148
|
async prev(span: CrudeTimeSpan = AUTO_SPAN): Promise<boolean> {
|
|
155
|
-
return await this.execute({
|
|
149
|
+
return await this.execute({
|
|
150
|
+
command: IteratorCommand.Prev,
|
|
151
|
+
span: new TimeSpan(span),
|
|
152
|
+
});
|
|
156
153
|
}
|
|
157
154
|
|
|
158
155
|
/**
|
|
@@ -164,7 +161,7 @@ export class Iterator {
|
|
|
164
161
|
* channel or has accumulated an error.
|
|
165
162
|
*/
|
|
166
163
|
async seekFirst(): Promise<boolean> {
|
|
167
|
-
return await this.execute({ command:
|
|
164
|
+
return await this.execute({ command: IteratorCommand.SeekFirst });
|
|
168
165
|
}
|
|
169
166
|
|
|
170
167
|
/** Seeks the iterator to the last segment in the time range, but does not read it.
|
|
@@ -175,7 +172,7 @@ export class Iterator {
|
|
|
175
172
|
* channel or has accumulated an error.
|
|
176
173
|
*/
|
|
177
174
|
async seekLast(): Promise<boolean> {
|
|
178
|
-
return await this.execute({ command:
|
|
175
|
+
return await this.execute({ command: IteratorCommand.SeekLast });
|
|
179
176
|
}
|
|
180
177
|
|
|
181
178
|
/**
|
|
@@ -187,7 +184,10 @@ export class Iterator {
|
|
|
187
184
|
* channel or has accumulated an error.
|
|
188
185
|
*/
|
|
189
186
|
async seekLE(stamp: CrudeTimeStamp): Promise<boolean> {
|
|
190
|
-
return await this.execute({
|
|
187
|
+
return await this.execute({
|
|
188
|
+
command: IteratorCommand.SeekLE,
|
|
189
|
+
stamp: new TimeStamp(stamp),
|
|
190
|
+
});
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
/**
|
|
@@ -199,7 +199,10 @@ export class Iterator {
|
|
|
199
199
|
* channel or has accumulated an error.
|
|
200
200
|
*/
|
|
201
201
|
async seekGE(stamp: CrudeTimeStamp): Promise<boolean> {
|
|
202
|
-
return await this.execute({
|
|
202
|
+
return await this.execute({
|
|
203
|
+
command: IteratorCommand.SeekGE,
|
|
204
|
+
stamp: new TimeStamp(stamp),
|
|
205
|
+
});
|
|
203
206
|
}
|
|
204
207
|
|
|
205
208
|
/**
|
|
@@ -208,7 +211,7 @@ export class Iterator {
|
|
|
208
211
|
* an error.
|
|
209
212
|
*/
|
|
210
213
|
async valid(): Promise<boolean> {
|
|
211
|
-
return await this.execute({ command:
|
|
214
|
+
return await this.execute({ command: IteratorCommand.Valid });
|
|
212
215
|
}
|
|
213
216
|
|
|
214
217
|
/**
|
|
@@ -224,12 +227,12 @@ export class Iterator {
|
|
|
224
227
|
return new IteratorIterator(this);
|
|
225
228
|
}
|
|
226
229
|
|
|
227
|
-
private async execute(request:
|
|
230
|
+
private async execute(request: IteratorRequest): Promise<boolean> {
|
|
228
231
|
this.stream.send(request);
|
|
229
232
|
this.value = new Frame();
|
|
230
233
|
while (true) {
|
|
231
234
|
const res = await this.stream.receive();
|
|
232
|
-
if (res.variant ===
|
|
235
|
+
if (res.variant === IteratorResponseVariant.Ack) return res.ack;
|
|
233
236
|
this.value.push(this.adapter.adapt(new Frame(res.frame)));
|
|
234
237
|
}
|
|
235
238
|
}
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
import { EOF, type Stream } from "@synnaxlabs/freighter";
|
|
11
11
|
import { type z } from "zod";
|
|
12
12
|
|
|
13
|
+
import { UnexpectedError } from "@/errors";
|
|
14
|
+
|
|
13
15
|
export class StreamProxy<RQ extends z.ZodType, RS extends z.ZodType> {
|
|
14
16
|
readonly name: string;
|
|
15
17
|
private readonly stream: Stream<RQ, RS>;
|
|
@@ -20,9 +22,7 @@ export class StreamProxy<RQ extends z.ZodType, RS extends z.ZodType> {
|
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
async receive(): Promise<z.infer<RS>> {
|
|
23
|
-
|
|
24
|
-
if (err != null) throw err;
|
|
25
|
-
return res;
|
|
25
|
+
return await this.stream.receive();
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
received(): boolean {
|
|
@@ -32,16 +32,16 @@ export class StreamProxy<RQ extends z.ZodType, RS extends z.ZodType> {
|
|
|
32
32
|
async closeAndAck(): Promise<void> {
|
|
33
33
|
this.stream.closeSend();
|
|
34
34
|
while (true) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
Please report this error to the Synnax team.`,
|
|
40
|
-
);
|
|
41
|
-
if (err != null) {
|
|
35
|
+
let res: z.infer<RS>;
|
|
36
|
+
try {
|
|
37
|
+
res = await this.stream.receive();
|
|
38
|
+
} catch (err) {
|
|
42
39
|
if (EOF.matches(err)) return;
|
|
43
40
|
throw err;
|
|
44
41
|
}
|
|
42
|
+
throw new UnexpectedError(
|
|
43
|
+
`${this.name} received unexpected response ${JSON.stringify(res)} on closure.`,
|
|
44
|
+
);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -50,7 +50,6 @@ export class StreamProxy<RQ extends z.ZodType, RS extends z.ZodType> {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
send(req: z.input<RQ>): void {
|
|
53
|
-
|
|
54
|
-
if (err != null) throw err;
|
|
53
|
+
this.stream.send(req);
|
|
55
54
|
}
|
|
56
55
|
}
|
|
@@ -565,7 +565,7 @@ describe("Streamer", () => {
|
|
|
565
565
|
it("should correctly call the underlying streamer methods", async () => {
|
|
566
566
|
const streamer = new MockStreamer();
|
|
567
567
|
const openMock = vi.fn();
|
|
568
|
-
const config = { channels: [1, 2, 3]
|
|
568
|
+
const config = { channels: [1, 2, 3] };
|
|
569
569
|
const fr = new Frame({ 1: new Series([1]) });
|
|
570
570
|
const hardened = await HardenedStreamer.open(
|
|
571
571
|
async (cfg) => {
|
package/src/framer/streamer.ts
CHANGED
|
@@ -46,9 +46,6 @@ const intermediateStreamerConfigZ = z.object({
|
|
|
46
46
|
downsampleFactor: z.int().default(1),
|
|
47
47
|
/** Optional throttle rate in Hz to limit the rate of frames sent to the client. Defaults to 0 (no throttling). */
|
|
48
48
|
throttleRate: Rate.z.default(new Rate(0)),
|
|
49
|
-
/** useHighPerformanceCodec sets whether the writer will use the Synnax frame encoder
|
|
50
|
-
as opposed to the standard JSON encoding mechanisms for frames. */
|
|
51
|
-
useHighPerformanceCodec: z.boolean().default(true),
|
|
52
49
|
/** excludeGroups sets writer group IDs whose frames should be filtered out by the
|
|
53
50
|
Core. Used for telemetry bypass deduplication. */
|
|
54
51
|
excludeGroups: z.uint32().array().default([]),
|
|
@@ -112,8 +109,7 @@ export const createStreamOpener =
|
|
|
112
109
|
async (config) => {
|
|
113
110
|
const cfg = streamerConfigZ.parse(config);
|
|
114
111
|
const adapter = await ReadAdapter.open(retriever, cfg.channels);
|
|
115
|
-
|
|
116
|
-
client = client.withCodec(new WSStreamerCodec(adapter.codec));
|
|
112
|
+
client = client.withCodec(new WSStreamerCodec(adapter.codec));
|
|
117
113
|
const stream = await client.stream("/frame/stream", reqZ, resZ);
|
|
118
114
|
const streamer = new BaseStreamer(
|
|
119
115
|
stream,
|
|
@@ -128,8 +124,7 @@ export const createStreamOpener =
|
|
|
128
124
|
throttleRate: cfg.throttleRate,
|
|
129
125
|
excludeGroups: cfg.excludeGroups,
|
|
130
126
|
});
|
|
131
|
-
|
|
132
|
-
if (err != null) throw err;
|
|
127
|
+
await stream.receive();
|
|
133
128
|
return streamer;
|
|
134
129
|
};
|
|
135
130
|
|
package/src/framer/types.gen.ts
CHANGED
|
@@ -18,3 +18,23 @@ export enum WriterCommand {
|
|
|
18
18
|
SetAuthority = 3,
|
|
19
19
|
}
|
|
20
20
|
export const writerCommandZ = z.enum(WriterCommand);
|
|
21
|
+
|
|
22
|
+
export enum IteratorCommand {
|
|
23
|
+
Open = 0,
|
|
24
|
+
Next = 1,
|
|
25
|
+
Prev = 2,
|
|
26
|
+
SeekFirst = 3,
|
|
27
|
+
SeekLast = 4,
|
|
28
|
+
SeekLE = 5,
|
|
29
|
+
SeekGE = 6,
|
|
30
|
+
Valid = 7,
|
|
31
|
+
Error = 8,
|
|
32
|
+
}
|
|
33
|
+
export const iteratorCommandZ = z.enum(IteratorCommand);
|
|
34
|
+
|
|
35
|
+
export enum IteratorResponseVariant {
|
|
36
|
+
None = 0,
|
|
37
|
+
Ack = 1,
|
|
38
|
+
Data = 2,
|
|
39
|
+
}
|
|
40
|
+
export const iteratorResponseVariantZ = z.enum(IteratorResponseVariant);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
|
-
import { DataType, id, TimeRange, TimeSpan, TimeStamp } from "@synnaxlabs/x";
|
|
10
|
+
import { DataType, id, Series, TimeRange, TimeSpan, TimeStamp } from "@synnaxlabs/x";
|
|
11
11
|
import { describe, expect, it, test } from "vitest";
|
|
12
12
|
|
|
13
13
|
import { UnauthorizedError, ValidationError } from "@/errors";
|
|
@@ -115,6 +115,83 @@ describe("Writer", () => {
|
|
|
115
115
|
expect(true).toBe(true);
|
|
116
116
|
});
|
|
117
117
|
|
|
118
|
+
test("auto-index generates server-side timestamps for data-only writes", async () => {
|
|
119
|
+
const [index, data] = await newIndexedPair(client);
|
|
120
|
+
const before = TimeStamp.now();
|
|
121
|
+
const writer = await client.openWriter({
|
|
122
|
+
start: before,
|
|
123
|
+
channels: [data.key],
|
|
124
|
+
autoIndex: true,
|
|
125
|
+
});
|
|
126
|
+
try {
|
|
127
|
+
await writer.write(data.key, randomSeries(5, data.dataType));
|
|
128
|
+
await writer.commit();
|
|
129
|
+
} finally {
|
|
130
|
+
await writer.close();
|
|
131
|
+
}
|
|
132
|
+
const f = await client.read(
|
|
133
|
+
new TimeRange(before, TimeStamp.now().add(TimeSpan.seconds(1))),
|
|
134
|
+
index.key,
|
|
135
|
+
);
|
|
136
|
+
expect(f.length).toEqual(5);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("auto-index mixes user-provided and generated timestamps in one writer", async () => {
|
|
140
|
+
const [index, data] = await newIndexedPair(client);
|
|
141
|
+
const userStamps = secondsLinspace(200, 2);
|
|
142
|
+
const beforeAuto = TimeStamp.now();
|
|
143
|
+
const writer = await client.openWriter({
|
|
144
|
+
start: TimeStamp.seconds(200),
|
|
145
|
+
channels: [index.key, data.key],
|
|
146
|
+
autoIndex: true,
|
|
147
|
+
});
|
|
148
|
+
try {
|
|
149
|
+
await writer.write({
|
|
150
|
+
[index.key]: userStamps,
|
|
151
|
+
[data.key]: randomSeries(2, data.dataType),
|
|
152
|
+
});
|
|
153
|
+
await writer.write(data.key, randomSeries(3, data.dataType));
|
|
154
|
+
await writer.commit();
|
|
155
|
+
} finally {
|
|
156
|
+
await writer.close();
|
|
157
|
+
}
|
|
158
|
+
const userF = await client.read(
|
|
159
|
+
new TimeRange(TimeStamp.seconds(200), TimeStamp.seconds(202)),
|
|
160
|
+
index.key,
|
|
161
|
+
);
|
|
162
|
+
expect(userF.data).toEqual(new BigInt64Array(userStamps.map((v) => v.valueOf())));
|
|
163
|
+
const autoF = await client.read(
|
|
164
|
+
new TimeRange(beforeAuto, TimeStamp.now().add(TimeSpan.seconds(1))),
|
|
165
|
+
index.key,
|
|
166
|
+
);
|
|
167
|
+
expect(autoF.length).toEqual(3);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test("auto-index leaves user-provided index data untouched", async () => {
|
|
171
|
+
const [index, data] = await newIndexedPair(client);
|
|
172
|
+
const writer = await client.openWriter({
|
|
173
|
+
start: TimeStamp.seconds(200),
|
|
174
|
+
channels: [index.key, data.key],
|
|
175
|
+
autoIndex: true,
|
|
176
|
+
});
|
|
177
|
+
try {
|
|
178
|
+
await writer.write({
|
|
179
|
+
[index.key]: secondsLinspace(200, 3),
|
|
180
|
+
[data.key]: randomSeries(3, data.dataType),
|
|
181
|
+
});
|
|
182
|
+
await writer.commit();
|
|
183
|
+
} finally {
|
|
184
|
+
await writer.close();
|
|
185
|
+
}
|
|
186
|
+
const f = await client.read(
|
|
187
|
+
new TimeRange(TimeStamp.seconds(200), TimeStamp.seconds(203)),
|
|
188
|
+
index.key,
|
|
189
|
+
);
|
|
190
|
+
expect(f.data).toEqual(
|
|
191
|
+
new BigInt64Array(secondsLinspace(200, 3).map((v) => v.valueOf())),
|
|
192
|
+
);
|
|
193
|
+
});
|
|
194
|
+
|
|
118
195
|
test("write with auto commit and a set interval", async () => {
|
|
119
196
|
const channels = await newIndexedPair(client);
|
|
120
197
|
const writer = await client.openWriter({
|
|
@@ -263,4 +340,147 @@ describe("Writer", () => {
|
|
|
263
340
|
expect(f.length).toEqual(10);
|
|
264
341
|
});
|
|
265
342
|
});
|
|
343
|
+
|
|
344
|
+
describe("Variable Channels", () => {
|
|
345
|
+
test("write and read string data", async () => {
|
|
346
|
+
const index = await client.channels.create({
|
|
347
|
+
name: id.create(),
|
|
348
|
+
isIndex: true,
|
|
349
|
+
dataType: DataType.TIMESTAMP,
|
|
350
|
+
leaseholder: 1,
|
|
351
|
+
});
|
|
352
|
+
const data = await client.channels.create({
|
|
353
|
+
name: id.create(),
|
|
354
|
+
index: index.key,
|
|
355
|
+
dataType: DataType.STRING,
|
|
356
|
+
leaseholder: 1,
|
|
357
|
+
});
|
|
358
|
+
const writer = await client.openWriter({
|
|
359
|
+
start: TimeStamp.seconds(1),
|
|
360
|
+
channels: [index, data],
|
|
361
|
+
});
|
|
362
|
+
try {
|
|
363
|
+
await writer.write({
|
|
364
|
+
[index.key]: secondsLinspace(1, 3),
|
|
365
|
+
[data.key]: new Series({
|
|
366
|
+
data: ["hello", "world", "foo"],
|
|
367
|
+
dataType: DataType.STRING,
|
|
368
|
+
}),
|
|
369
|
+
});
|
|
370
|
+
await writer.commit();
|
|
371
|
+
} finally {
|
|
372
|
+
await writer.close();
|
|
373
|
+
}
|
|
374
|
+
const f = await data.read(TimeRange.MAX);
|
|
375
|
+
expect(f.toStrings()).toEqual(["hello", "world", "foo"]);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
test("write and read JSON data", async () => {
|
|
379
|
+
const index = await client.channels.create({
|
|
380
|
+
name: id.create(),
|
|
381
|
+
isIndex: true,
|
|
382
|
+
dataType: DataType.TIMESTAMP,
|
|
383
|
+
leaseholder: 1,
|
|
384
|
+
});
|
|
385
|
+
const data = await client.channels.create({
|
|
386
|
+
name: id.create(),
|
|
387
|
+
index: index.key,
|
|
388
|
+
dataType: DataType.JSON,
|
|
389
|
+
leaseholder: 1,
|
|
390
|
+
});
|
|
391
|
+
const writer = await client.openWriter({
|
|
392
|
+
start: TimeStamp.seconds(1),
|
|
393
|
+
channels: [index, data],
|
|
394
|
+
});
|
|
395
|
+
try {
|
|
396
|
+
await writer.write({
|
|
397
|
+
[index.key]: secondsLinspace(1, 2),
|
|
398
|
+
[data.key]: new Series({
|
|
399
|
+
data: [{ key: "value" }, { num: 42 }],
|
|
400
|
+
dataType: DataType.JSON,
|
|
401
|
+
}),
|
|
402
|
+
});
|
|
403
|
+
await writer.commit();
|
|
404
|
+
} finally {
|
|
405
|
+
await writer.close();
|
|
406
|
+
}
|
|
407
|
+
const f = await data.read(TimeRange.MAX);
|
|
408
|
+
expect(f.length).toEqual(2);
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
test("write mixed fixed and variable channels", async () => {
|
|
412
|
+
const index = await client.channels.create({
|
|
413
|
+
name: id.create(),
|
|
414
|
+
isIndex: true,
|
|
415
|
+
dataType: DataType.TIMESTAMP,
|
|
416
|
+
leaseholder: 1,
|
|
417
|
+
});
|
|
418
|
+
const floatCh = await client.channels.create({
|
|
419
|
+
name: id.create(),
|
|
420
|
+
index: index.key,
|
|
421
|
+
dataType: DataType.FLOAT64,
|
|
422
|
+
leaseholder: 1,
|
|
423
|
+
});
|
|
424
|
+
const strCh = await client.channels.create({
|
|
425
|
+
name: id.create(),
|
|
426
|
+
index: index.key,
|
|
427
|
+
dataType: DataType.STRING,
|
|
428
|
+
leaseholder: 1,
|
|
429
|
+
});
|
|
430
|
+
const writer = await client.openWriter({
|
|
431
|
+
start: TimeStamp.seconds(1),
|
|
432
|
+
channels: [index, floatCh, strCh],
|
|
433
|
+
});
|
|
434
|
+
try {
|
|
435
|
+
await writer.write({
|
|
436
|
+
[index.key]: secondsLinspace(1, 3),
|
|
437
|
+
[floatCh.key]: new Float64Array([1.1, 2.2, 3.3]),
|
|
438
|
+
[strCh.key]: new Series({
|
|
439
|
+
data: ["a", "b", "c"],
|
|
440
|
+
dataType: DataType.STRING,
|
|
441
|
+
}),
|
|
442
|
+
});
|
|
443
|
+
await writer.commit();
|
|
444
|
+
} finally {
|
|
445
|
+
await writer.close();
|
|
446
|
+
}
|
|
447
|
+
const floatData = await floatCh.read(TimeRange.MAX);
|
|
448
|
+
expect(floatData.length).toEqual(3);
|
|
449
|
+
const strData = await strCh.read(TimeRange.MAX);
|
|
450
|
+
expect(strData.toStrings()).toEqual(["a", "b", "c"]);
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
test("write strings with embedded newlines", async () => {
|
|
454
|
+
const index = await client.channels.create({
|
|
455
|
+
name: id.create(),
|
|
456
|
+
isIndex: true,
|
|
457
|
+
dataType: DataType.TIMESTAMP,
|
|
458
|
+
leaseholder: 1,
|
|
459
|
+
});
|
|
460
|
+
const data = await client.channels.create({
|
|
461
|
+
name: id.create(),
|
|
462
|
+
index: index.key,
|
|
463
|
+
dataType: DataType.STRING,
|
|
464
|
+
leaseholder: 1,
|
|
465
|
+
});
|
|
466
|
+
const writer = await client.openWriter({
|
|
467
|
+
start: TimeStamp.seconds(1),
|
|
468
|
+
channels: [index, data],
|
|
469
|
+
});
|
|
470
|
+
try {
|
|
471
|
+
await writer.write({
|
|
472
|
+
[index.key]: secondsLinspace(1, 2),
|
|
473
|
+
[data.key]: new Series({
|
|
474
|
+
data: ["line1\nline2", "no newline"],
|
|
475
|
+
dataType: DataType.STRING,
|
|
476
|
+
}),
|
|
477
|
+
});
|
|
478
|
+
await writer.commit();
|
|
479
|
+
} finally {
|
|
480
|
+
await writer.close();
|
|
481
|
+
}
|
|
482
|
+
const f = await data.read(TimeRange.MAX);
|
|
483
|
+
expect(f.toStrings()).toEqual(["line1\nline2", "no newline"]);
|
|
484
|
+
});
|
|
485
|
+
});
|
|
266
486
|
});
|