Skip to content

Commit 8a753d7

Browse files
committed
Porting streams-related docs to k6/net/grpc
1 parent 655d5e4 commit 8a753d7

File tree

9 files changed

+390
-20
lines changed

9 files changed

+390
-20
lines changed

docs/sources/next/javascript-api/k6-net-grpc/_index.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ weight: 11
66

77
# k6/net/grpc
88

9-
{{< docs/shared source="k6" lookup="grpc-module.md" version="<K6_VERSION>" >}}
10-
11-
The `k6/net/grpc` module provides a [gRPC](https://grpc.io/) client for Remote Procedure Calls (RPC) over HTTP/2.
9+
The `k6/net/grpc` module provides a [gRPC](https://grpc.io/) client for Remote Procedure Calls (RPC) over HTTP/2. It supports unary and streaming (starting [v0.49](https://github.com/grafana/k6/releases/tag/v0.49.0)) RPCs.
1210

1311
| Class/Method | Description |
1412
| --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -20,6 +18,10 @@ The `k6/net/grpc` module provides a [gRPC](https://grpc.io/) client for Remote P
2018
| [Params](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-net-grpc/params) | RPC Request specific options. |
2119
| [Response](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-net-grpc/response) | Returned by RPC requests. |
2220
| [Constants](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-net-grpc/constants) | Define constants to distinguish between [gRPC Response](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-net-grpc/response) statuses. |
21+
| [Stream](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-net-grpc/stream) | Creates a new GRPC stream. |
22+
| [Stream.on(event, handler)](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-net-grpc/stream/stream-on) | Adds a new listener to one of the possible stream event's. |
23+
| [Stream.write(message)](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-net-grpc/stream/stream-write) | Writes a message to the stream. |
24+
| [Stream.end()](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-net-grpc/stream/stream-end) | Signals to server that client finished sending. |
2325

2426
## gRPC metrics
2527

docs/sources/next/javascript-api/k6-net-grpc/client/_index.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,11 @@
22
title: Client
33
excerpt: 'Client is a gRPC client that can interact with a gRPC server.'
44
weight: 10
5-
weight: 20
65
---
76

87
# Client
98

10-
{{< docs/shared source="k6" lookup="grpc-module.md" version="<K6_VERSION>" >}}
11-
12-
`Client` is a gRPC client that can interact with a gRPC server. Only unary RPCs are currently supported in this module.
9+
`Client` is a gRPC client that can interact with a gRPC server.
1310

1411
| Method | Description |
1512
| ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
---
2+
title: Stream
3+
excerpt: 'GRPC Streams'
4+
weight: 30
5+
---
6+
7+
# Stream
8+
9+
Using a GRPC client creates a stream. An important note that the client should be already connected (client.connect called) to the server before creating a stream.
10+
11+
| Method | Description |
12+
| ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
13+
| [Stream(client, url, [,params])](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-net-grpc/stream) | Using a GRPC client creates a stream. |
14+
| [Stream.write(message)](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-net-grpc/stream/stream-write) | Writes a message to the stream. |
15+
| [Stream.on(event, handler)](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-net-grpc/stream/stream-on) | Set up handler functions for various events on the GRPC stream. |
16+
| [Stream.end()](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-net-grpc/stream/stream-end) | Signals to the server that the client has finished sending. |
17+
18+
### Examples
19+
20+
_A k6 script that sends several randomly chosen points from the pre-generated feature database with a variable delay in between. Prints the statistics when they are sent from the server._
21+
22+
{{< code >}}
23+
24+
```javascript
25+
import { Client, Stream } from 'k6/net/grpc';
26+
import { sleep } from 'k6';
27+
28+
const COORD_FACTOR = 1e7;
29+
30+
const GRPC_ADDR = __ENV.GRPC_ADDR || '127.0.0.1:10000';
31+
const GRPC_PROTO_PATH = __ENV.GRPC_PROTO_PATH || '../../grpc_server/route_guide.proto';
32+
33+
const client = new Client();
34+
client.load([], GRPC_PROTO_PATH);
35+
36+
// a sample DB of points
37+
const DB = [
38+
{
39+
location: { latitude: 407838351, longitude: -746143763 },
40+
name: 'Patriots Path, Mendham, NJ 07945, USA',
41+
},
42+
{
43+
location: { latitude: 408122808, longitude: -743999179 },
44+
name: '101 New Jersey 10, Whippany, NJ 07981, USA',
45+
},
46+
{
47+
location: { latitude: 413628156, longitude: -749015468 },
48+
name: 'U.S. 6, Shohola, PA 18458, USA',
49+
},
50+
{
51+
location: { latitude: 419999544, longitude: -740371136 },
52+
name: '5 Conners Road, Kingston, NY 12401, USA',
53+
},
54+
{
55+
location: { latitude: 414008389, longitude: -743951297 },
56+
name: 'Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA',
57+
},
58+
{
59+
location: { latitude: 419611318, longitude: -746524769 },
60+
name: '287 Flugertown Road, Livingston Manor, NY 12758, USA',
61+
},
62+
{
63+
location: { latitude: 406109563, longitude: -742186778 },
64+
name: '4001 Tremley Point Road, Linden, NJ 07036, USA',
65+
},
66+
{
67+
location: { latitude: 416802456, longitude: -742370183 },
68+
name: '352 South Mountain Road, Wallkill, NY 12589, USA',
69+
},
70+
{
71+
location: { latitude: 412950425, longitude: -741077389 },
72+
name: 'Bailey Turn Road, Harriman, NY 10926, USA',
73+
},
74+
{
75+
location: { latitude: 412144655, longitude: -743949739 },
76+
name: '193-199 Wawayanda Road, Hewitt, NJ 07421, USA',
77+
},
78+
];
79+
80+
export default () => {
81+
if (__ITER == 0) {
82+
client.connect(GRPC_ADDR, { plaintext: true });
83+
}
84+
85+
const stream = new Stream(client, 'main.RouteGuide/RecordRoute');
86+
87+
stream.on('data', (stats) => {
88+
console.log('Finished trip with', stats.pointCount, 'points');
89+
console.log('Passed', stats.featureCount, 'features');
90+
console.log('Travelled', stats.distance, 'meters');
91+
console.log('It took', stats.elapsedTime, 'seconds');
92+
});
93+
94+
stream.on('error', (err) => {
95+
console.log('Stream Error: ' + JSON.stringify(err));
96+
});
97+
98+
stream.on('end', () => {
99+
client.close();
100+
console.log('All done');
101+
});
102+
103+
// send 5 random items
104+
for (let i = 0; i < 5; i++) {
105+
const point = DB[Math.floor(Math.random() * DB.length)];
106+
pointSender(stream, point);
107+
}
108+
109+
// close the client stream
110+
stream.end();
111+
112+
sleep(1);
113+
};
114+
115+
const pointSender = (stream, point) => {
116+
console.log(
117+
'Visiting point ' +
118+
point.name +
119+
' ' +
120+
point.location.latitude / COORD_FACTOR +
121+
', ' +
122+
point.location.longitude / COORD_FACTOR
123+
);
124+
125+
// send the location to the server
126+
stream.write(point.location);
127+
128+
sleep(0.5);
129+
};
130+
```
131+
132+
{{< /code >}}
133+
134+
_A k6 script that sends a rectangle message and results (features) are streamed back to the client._
135+
136+
{{< code >}}
137+
138+
```javascript
139+
import { Client, Stream } from 'k6/net/grpc';
140+
import { sleep } from 'k6';
141+
142+
const COORD_FACTOR = 1e7;
143+
144+
const GRPC_ADDR = __ENV.GRPC_ADDR || '127.0.0.1:10000';
145+
const GRPC_PROTO_PATH = __ENV.GRPC_PROTO_PATH || '../../grpc_server/route_guide.proto';
146+
147+
const client = new Client();
148+
149+
client.load([], GRPC_PROTO_PATH);
150+
151+
export default () => {
152+
client.connect(GRPC_ADDR, { plaintext: true });
153+
154+
const stream = new Stream(client, 'main.FeatureExplorer/ListFeatures', null);
155+
156+
stream.on('data', function (feature) {
157+
console.log(
158+
'Found feature called "' +
159+
feature.name +
160+
'" at ' +
161+
feature.location.latitude / COORD_FACTOR +
162+
', ' +
163+
feature.location.longitude / COORD_FACTOR
164+
);
165+
});
166+
167+
stream.on('end', function () {
168+
// The server has finished sending
169+
client.close();
170+
console.log('All done');
171+
});
172+
173+
stream.on('error', function (e) {
174+
// An error has occurred and the stream has been closed.
175+
console.log('Error: ' + JSON.stringify(e));
176+
});
177+
178+
// send a message to the server
179+
stream.write({
180+
lo: {
181+
latitude: 400000000,
182+
longitude: -750000000,
183+
},
184+
hi: {
185+
latitude: 420000000,
186+
longitude: -730000000,
187+
},
188+
});
189+
190+
sleep(0.5);
191+
};
192+
```
193+
194+
{{< /code >}}
195+
196+
The preceding examples use a demo server, which you can run with the following command (Golang should be installed) in [k6 repository's root](https://github.com/grafana/k6):
197+
198+
{{< code >}}
199+
200+
```bash
201+
$ go run -mod=mod examples/grpc_server/*.go
202+
```
203+
204+
{{< /code >}}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
title: 'Stream.end()'
3+
excerpt: 'Signals to the server that the client has finished sending.'
4+
weight: 40
5+
---
6+
7+
# Stream.end()
8+
9+
Signals to the server that the client has finished sending messages.
10+
11+
### Example
12+
13+
<div class="code-group" data-props='{"labels": ["Simple example"], "lineNumbers": [true]}'>
14+
15+
```javascript
16+
import { Client, Stream } from 'k6/net/grpc';
17+
import { sleep } from 'k6';
18+
19+
const COORD_FACTOR = 1e7;
20+
21+
const client = new Client();
22+
client.load([], '../../grpc_server/route_guide.proto');
23+
24+
export default () => {
25+
if (__ITER == 0) {
26+
client.connect('127.0.0.1:10000', { plaintext: true });
27+
}
28+
29+
const stream = new Stream(client, 'main.RouteGuide/RecordRoute');
30+
31+
stream.on('data', (stats) => {
32+
console.log('Finished trip with', stats.pointCount, 'points');
33+
console.log('Passed', stats.featureCount, 'features');
34+
console.log('Traveled', stats.distance, 'meters');
35+
console.log('It took', stats.elapsedTime, 'seconds');
36+
});
37+
38+
// send 2 items
39+
stream.write({ latitude: 406109563, longitude: -742186778 });
40+
stream.write({ latitude: 416802456, longitude: -742370183 });
41+
42+
// send end-signal to the server
43+
stream.end();
44+
45+
sleep(1);
46+
};
47+
```
48+
49+
</div>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
title: 'Error'
3+
head_title: 'gRPC.Error'
4+
excerpt: 'The error object of a gRPC stream.'
5+
weight: 15
6+
---
7+
8+
# Error
9+
10+
The error object is the object that is passed to the `error` event handler function.
11+
12+
| Name | Type | Description |
13+
| --------------- | ------ | ------------------------------------- |
14+
| `Error.code` | number | A gRPC error code. |
15+
| `Error.details` | array | A list details attached to the error. |
16+
| `Error.message` | string | An original error message. |
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
title: 'Stream.on()'
3+
excerpt: 'Set up handler functions for various events on the GRPC stream.'
4+
weight: 10
5+
---
6+
7+
# Stream.on()
8+
9+
Set up handler functions for various events on the GRPC stream.
10+
11+
| Parameter | Type | Description |
12+
| --------- | -------- | -------------------------------------------- |
13+
| event | string | The event name to define a handler for. |
14+
| handler | function | The function to call when the event happens. |
15+
16+
Possible events:
17+
18+
| Event name | Description |
19+
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
20+
| data | Emitted when the server sends data. |
21+
| error | Emitted when an error occurs. In case of the error, an [`Error`](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-net-grpc/stream/stream-error) object sends to the handler function. |
22+
| end | Emitted when the server closes the incoming stream. |
23+
24+
### Example
25+
26+
<div class="code-group" data-props='{"labels": ["Simple example"], "lineNumbers": [true]}'>
27+
28+
```javascript
29+
import { Client, Stream } from 'k6/net/grpc';
30+
import { sleep } from 'k6';
31+
32+
const COORD_FACTOR = 1e7;
33+
34+
const client = new Client();
35+
client.load([], '../../grpc_server/route_guide.proto');
36+
37+
export default () => {
38+
if (__ITER == 0) {
39+
client.connect('127.0.0.1:10000', { plaintext: true });
40+
}
41+
42+
const stream = new Stream(client, 'main.RouteGuide/RecordRoute');
43+
44+
// sets up a handler for the data (server sends data) event
45+
stream.on('data', (stats) => {
46+
console.log('Finished trip with', stats.pointCount, 'points');
47+
console.log('Passed', stats.featureCount, 'features');
48+
console.log('Traveled', stats.distance, 'meters');
49+
console.log('It took', stats.elapsedTime, 'seconds');
50+
});
51+
52+
// sets up a handler for the end event (stream closes)
53+
stream.on('end', function () {
54+
// The server has finished sending
55+
client.close();
56+
console.log('All done');
57+
});
58+
59+
// sets up a handler for the error event (an error occurs)
60+
stream.on('error', function (e) {
61+
// An error has occurred and the stream has been closed.
62+
console.log('Error: ' + JSON.stringify(e));
63+
});
64+
65+
sleep(1);
66+
};
67+
```
68+
69+
</div>

0 commit comments

Comments
 (0)