-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sse: support Server Sent Event #3639
Changes from all commits
d5cd101
be23f19
d1c57a3
e122ad7
d711223
e9dec06
65506f2
ee60d0f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Introduce an SSE API module for k6 | ||
|
||
| | | | ||
|:---------------------|:-------------------------------------------------------------| | ||
| **author** | @phymbert | | ||
| **status** | 🔧 proposal | | ||
| **revisions** | [initial](https://github.com/grafana/k6/pull/3639) | | ||
| **Proof of concept** | [branch](https://github.com/phymbert/k6/tree/hp/feature/sse) | | ||
| **references** | [#746](https://github.com/grafana/k6/issues/746) | | ||
|
||
## Problem definition | ||
|
||
The current version of k6 reads the full http response body before returning to the client, | ||
which make impossible testing [Server-Sent Event](https://fr.wikipedia.org/wiki/Server-sent_events). | ||
|
||
We propose to introduce a new `sse` module. | ||
This module is intended to offer an intuitive and user-friendly API for SSE interactions within k6 scripts. | ||
|
||
## Proposed solution | ||
|
||
We suggest to implement a minimalist, experimental (`sse`) module based on the go http client. | ||
The new module will allow users to interact with SSE. | ||
The module will provide an `open` which will allow the user to pass a setup function to configure an `event` callback as it is done in the `ws` module with `message`. | ||
|
||
### Limitation | ||
The module will not support async io and the javascript main loop will be blocked during the http request duration. | ||
|
||
### Example usage | ||
|
||
```javascript | ||
import sse from 'k6/experimental/sse'; | ||
|
||
var url = "https://echo.websocket.org/.sse"; | ||
var params = {"tags": {"my_tag": "hello"}}; | ||
|
||
var response = sse.open(url, params, function (client) { | ||
client.on('open', function open() { | ||
console.log('connected'); | ||
}); | ||
|
||
client.on('event', function (event) { | ||
console.log(`event id=${event.id}, name=${event.name}, data=${event.data}`); | ||
}); | ||
|
||
client.on('error', function (e) { | ||
console.log('An unexpected error occurred: ', e.error()); | ||
}); | ||
}); | ||
|
||
check(response, {"status is 200": (r) => r && r.status === 200}); | ||
``` | ||
|
||
### Conclusion | ||
|
||
We believe the [proof of concept](https://github.com/grafana/k6/blob/d5cd1010ecb2381376188c8a47ab861cf8b5dc3d/js/modules/k6/experimental/sse/sse.go) developed with this proposal illustrates the feasibility and benefits of developing such an API. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import sse from "k6/experimental/sse"; | ||
import {check} from "k6"; | ||
|
||
export default function () { | ||
var url = "https://echo.websocket.org/.sse"; | ||
var params = {"tags": {"my_tag": "hello"}}; | ||
|
||
var response = sse.open(url, params, function (client) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An SSE connection is usually long-lived. We do not test normal operation by opening a new connection in each iteration. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not at all, see: https://platform.openai.com/docs/api-reference/streaming I mainly use K6 at the moment to test LLM inference server: |
||
client.on('open', function open() { | ||
console.log('connected'); | ||
}); | ||
|
||
client.on('event', function (event) { | ||
console.log(`event id=${event.id}, name=${event.name}, data=${event.data}`); | ||
}); | ||
|
||
client.on('error', function (e) { | ||
console.log('An unexpected error occurred: ', e.error()); | ||
}); | ||
}); | ||
|
||
check(response, {"status is 200": (r) => r && r.status === 200}); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Async support is becoming more and more important, so integrating a new module without async support is questionable. This is just my personal opinion, @mstoykov is more competent in this...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that SSE is by default an asynchronous communication I find that this must be asynchronous as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean by asynchronous ? it's one way server to client data flow on top of HTTP 1.1 w/ single connection. The event loop is blocked while waiting for next event, but on each new event the client callback is triggered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Take a look at xk6-mock extension code base, especially in the szkiba/muxpress library. You will find example there how to support callback running on eventloop.