@synnaxlabs/client 0.17.1 → 0.17.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 +5 -5
- package/README.md +1 -1
- package/dist/client.cjs +5 -5
- package/dist/client.cjs.map +1 -1
- package/dist/client.js +60 -54
- package/dist/client.js.map +1 -1
- package/examples/node/liveStream.js +41 -0
- package/examples/node/package-lock.json +4 -4
- package/examples/node/package.json +1 -1
- package/examples/node/streamWrite.js +57 -2
- package/package.json +4 -4
- package/src/framer/frame.ts +5 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Synnax, TimeStamp } from "@synnaxlabs/client";
|
|
2
|
+
|
|
3
|
+
// This example demonstrates how to stream live data from a channel in Synnax.
|
|
4
|
+
// Live-streaming is useful for real-time data processing and analysis, and is an
|
|
5
|
+
// integral part of Synnax's control sequence and data streaming capabilities.
|
|
6
|
+
|
|
7
|
+
// This example is meant to be used in conjunction with the stream_write.py example, and
|
|
8
|
+
// assumes that example is running in a separate terminal.
|
|
9
|
+
|
|
10
|
+
// Connect to a locally running, insecure Synnax cluster. If your connection parameters
|
|
11
|
+
// are different, enter them here.
|
|
12
|
+
const client = new Synnax({
|
|
13
|
+
host: "localhost",
|
|
14
|
+
port: 9090,
|
|
15
|
+
username: "synnax",
|
|
16
|
+
password: "seldon",
|
|
17
|
+
secure: false
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// We can just specify the names of the channels we'd like to stream from.
|
|
21
|
+
const read_from = ["stream_write_example_time", "stream_write_example_data"]
|
|
22
|
+
|
|
23
|
+
const streamer = await client.telem.newStreamer(read_from);
|
|
24
|
+
|
|
25
|
+
// It's very important that we close the streamer when we're done with it to release
|
|
26
|
+
// network connections and other resources, so we wrap the streaming loop in a try-finally
|
|
27
|
+
// block.
|
|
28
|
+
try {
|
|
29
|
+
// Loop through the frames in the streamer. Each iteration will block until a new
|
|
30
|
+
// frame is available, and then we'll just print it out.
|
|
31
|
+
for await (const frame of streamer)
|
|
32
|
+
console.log({
|
|
33
|
+
time: new TimeStamp(frame.get("stream_write_example_time")[0].at(0)).toString(),
|
|
34
|
+
data: frame.get("stream_write_example_data")[0].at(0)
|
|
35
|
+
})
|
|
36
|
+
} finally {
|
|
37
|
+
streamer.close();
|
|
38
|
+
// Close the client when we're done with it.
|
|
39
|
+
client.close();
|
|
40
|
+
}
|
|
41
|
+
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"version": "1.0.0",
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@synnaxlabs/client": "^0.17.
|
|
12
|
+
"@synnaxlabs/client": "^0.17.2"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"node_modules/@grpc/grpc-js": {
|
|
@@ -3653,9 +3653,9 @@
|
|
|
3653
3653
|
}
|
|
3654
3654
|
},
|
|
3655
3655
|
"node_modules/@synnaxlabs/client": {
|
|
3656
|
-
"version": "0.17.
|
|
3657
|
-
"resolved": "https://registry.npmjs.org/@synnaxlabs/client/-/client-0.17.
|
|
3658
|
-
"integrity": "sha512-
|
|
3656
|
+
"version": "0.17.2",
|
|
3657
|
+
"resolved": "https://registry.npmjs.org/@synnaxlabs/client/-/client-0.17.2.tgz",
|
|
3658
|
+
"integrity": "sha512-9r8C7KbWBHluBRnu8qw34hf+u8JW1CkM6VmAT+51N+m0z2AZA0pbK01MNNIjLQAZ1bAdKpzc57BxqSzCwIceGQ==",
|
|
3659
3659
|
"dependencies": {
|
|
3660
3660
|
"@synnaxlabs/freighter": "0.9.1",
|
|
3661
3661
|
"@synnaxlabs/x": "0.14.1",
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// applications (such as data acquisition from a sensor) or for very large datasets that
|
|
4
4
|
// cannot be written all at once.
|
|
5
5
|
|
|
6
|
-
import { Synnax } from "@synnaxlabs/client";
|
|
6
|
+
import { Rate, Series, Synnax, TimeStamp, framer } from "@synnaxlabs/client";
|
|
7
7
|
|
|
8
8
|
// Connect to a locally running, insecure Synnax cluster. If your connection parameters
|
|
9
9
|
// are different, enter them here.
|
|
@@ -20,4 +20,59 @@ const timeChannel = await client.channels.create({
|
|
|
20
20
|
name: "stream_write_example_time",
|
|
21
21
|
isIndex: true,
|
|
22
22
|
dataType: "timestamp"
|
|
23
|
-
});
|
|
23
|
+
}, { retrieveIfNameExists: true });
|
|
24
|
+
|
|
25
|
+
// Create a data channel that will be used to store our fake sensor data.
|
|
26
|
+
const dataChannel = await client.channels.create({
|
|
27
|
+
name: "stream_write_example_data",
|
|
28
|
+
dataType: "float32",
|
|
29
|
+
index: timeChannel.key,
|
|
30
|
+
}, { retrieveIfNameExists: true });
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
// We'll start our write at the current time. This timestamps should be the same as or
|
|
34
|
+
// just before the first timestamp we write.
|
|
35
|
+
const start = TimeStamp.now();
|
|
36
|
+
|
|
37
|
+
// Set a rough rate of 20 Hz. This won't be exact because we're sleeping for a fixed
|
|
38
|
+
// amount of time, but it's close enough for demonstration purposes.
|
|
39
|
+
const roughRate = Rate.hz(40);
|
|
40
|
+
|
|
41
|
+
// Make the writer commit every 500 samples. This will make the data available for
|
|
42
|
+
// historical reads every 500 samples.
|
|
43
|
+
const commitInterval = 500;
|
|
44
|
+
|
|
45
|
+
const writer = await client.telem.newWriter({
|
|
46
|
+
start,
|
|
47
|
+
channels: [timeChannel.key, dataChannel.key]
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
let i = 0;
|
|
52
|
+
while (true) {
|
|
53
|
+
await new Promise(resolve => setTimeout(resolve, roughRate.period.milliseconds));
|
|
54
|
+
i++;
|
|
55
|
+
const timestamp = TimeStamp.now();
|
|
56
|
+
const data = Math.sin(i / 10);
|
|
57
|
+
const fr = new framer.Frame({
|
|
58
|
+
[timeChannel.key]: new Series({ data: new timeChannel.dataType.Array([timestamp]) }),
|
|
59
|
+
[dataChannel.key]: new Series({ data: new dataChannel.dataType.Array([data]) })
|
|
60
|
+
});
|
|
61
|
+
await writer.write(fr);
|
|
62
|
+
|
|
63
|
+
if (i % 60 == 0)
|
|
64
|
+
console.log(`Writing sample ${i} at ${timestamp.toISOString()}`)
|
|
65
|
+
|
|
66
|
+
if (i % commitInterval == 0) {
|
|
67
|
+
// Commit the writer. This method will return false if the commit fails i.e.
|
|
68
|
+
// we've mad an invalid write or someone has already written to this region.
|
|
69
|
+
if (!await writer.commit()) {
|
|
70
|
+
console.error("Failed to commit data");
|
|
71
|
+
break;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
} finally {
|
|
76
|
+
await writer.close();
|
|
77
|
+
}
|
|
78
|
+
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synnaxlabs/client",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.17.
|
|
4
|
+
"version": "0.17.3",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The Client Library for Synnax",
|
|
7
7
|
"repository": "https://github.com/synnaxlabs/synnax/tree/main/client/ts",
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"async-mutex": "^0.4.0",
|
|
20
20
|
"zod": "3.22.4",
|
|
21
|
-
"@synnaxlabs/
|
|
22
|
-
"@synnaxlabs/
|
|
21
|
+
"@synnaxlabs/freighter": "0.9.1",
|
|
22
|
+
"@synnaxlabs/x": "0.14.1"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@types/node": "^20.10.5",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"typescript": "^5.3.3",
|
|
28
28
|
"vite": "^5.1.2",
|
|
29
29
|
"vitest": "^1.2.2",
|
|
30
|
-
"@synnaxlabs/vite-plugin": "0.0.1",
|
|
31
30
|
"@synnaxlabs/tsconfig": "0.0.2",
|
|
31
|
+
"@synnaxlabs/vite-plugin": "0.0.1",
|
|
32
32
|
"eslint-config-synnaxlabs": "0.0.1"
|
|
33
33
|
},
|
|
34
34
|
"main": "dist/client.cjs",
|
package/src/framer/frame.ts
CHANGED
|
@@ -110,7 +110,11 @@ export class Frame {
|
|
|
110
110
|
validateMatchedColsAndArrays(data_.keys, arrays);
|
|
111
111
|
data_.keys.forEach((key, i) => this.push(key, arrays[i]));
|
|
112
112
|
} else
|
|
113
|
-
Object.entries(columnsOrData).forEach(([k, v]) =>
|
|
113
|
+
Object.entries(columnsOrData).forEach(([k, v]) => {
|
|
114
|
+
const key = parseInt(k);
|
|
115
|
+
if (!isNaN(key)) return this.push(key, ...toArray(v));
|
|
116
|
+
else this.push(k, ...toArray(v))
|
|
117
|
+
});
|
|
114
118
|
return;
|
|
115
119
|
}
|
|
116
120
|
|