1import { Effect, Schema, Stream } from "effect"
2import { HttpClient, HttpClientResponse } from "effect/http"
3import { HttpApi, HttpApiClient, HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "effect/http-api"
4import { Bench } from "tinybench"
5
6const Event = Schema.Struct({
7 event: Schema.Literal("tick"),
8 data: Schema.String
9})
10
11const Api = HttpApi.make("Api").add(
12 HttpApiGroup.make("test").add(
13 HttpApiEndpoint.get("events", "/events", {
14 success: HttpApiSchema.StreamSse({
15 events: Event,
16 error: Schema.String
17 })
18 })
19 )
20)
21
22const httpClient = HttpClient.make((request) =>
23 Effect.sync(() =>
24 HttpClientResponse.fromWeb(
25 request,
26 new Response("event: tick\ndata: payload\n\n", {
27 status: 200,
28 headers: { "content-type": "text/event-stream" }
29 })
30 )
31 )
32)
33
34const client = await Effect.runPromise(HttpApiClient.makeWith(Api, {
35 baseUrl: "http://localhost",
36 httpClient
37}))
38const consumeResponse = Effect.flatMap(client.test.events({}), Stream.runDrain)
39const responsesPerIteration = 25
40const responses = Array.from({ length: responsesPerIteration })
41const runIteration = Effect.forEach(responses, () => consumeResponse, {
42 concurrency: 1,
43 discard: true
44})
45
46const bench = new Bench({ time: 3000 })
47
48bench.add(`${responsesPerIteration} sequential SSE responses through one client`, () => Effect.runPromise(runIteration))
49
50await bench.run()
51
52console.table(bench.table())