refactor(server): share event stream encoding (#36484)
This commit is contained in:
parent
5414697bd1
commit
7913c4a490
9 changed files with 483 additions and 102 deletions
|
|
@ -1,44 +1,23 @@
|
|||
import { EventV2 } from "@opencode-ai/core/event"
|
||||
import { isOpenCodeEvent, OpenCodeEvent } from "@opencode-ai/protocol/groups/event"
|
||||
import { Effect, Schema, Stream } from "effect"
|
||||
import { Sse } from "effect/unstable/encoding"
|
||||
import { Effect, Stream } from "effect"
|
||||
import { HttpServerResponse } from "effect/unstable/http"
|
||||
import { HttpApiBuilder } from "effect/unstable/httpapi"
|
||||
import { Api } from "../api"
|
||||
|
||||
// Session execution emits dense event bursts; allow healthy SSE clients enough
|
||||
// time to absorb one without weakening the bounded slow-subscriber failure.
|
||||
const subscriberCapacity = 4_096
|
||||
|
||||
function eventData(data: unknown): Sse.Event {
|
||||
return {
|
||||
_tag: "Event",
|
||||
event: "message",
|
||||
id: undefined,
|
||||
data: JSON.stringify(Schema.encodeUnknownSync(OpenCodeEvent)(data)),
|
||||
}
|
||||
}
|
||||
import { EventFeed } from "../event-feed"
|
||||
|
||||
export const EventHandler = HttpApiBuilder.group(Api, "server.event", (handlers) =>
|
||||
Effect.gen(function* () {
|
||||
const events = yield* EventV2.Service
|
||||
const feed = yield* EventFeed.Service
|
||||
return handlers.handleRaw("event.subscribe", () =>
|
||||
Effect.gen(function* () {
|
||||
const connected = {
|
||||
id: EventV2.ID.create(),
|
||||
type: "server.connected",
|
||||
data: {},
|
||||
}
|
||||
} as const
|
||||
const output = Stream.unwrap(
|
||||
Effect.gen(function* () {
|
||||
// Acquiring the bounded stream installs its listener before readiness is observable.
|
||||
const live = yield* EventV2.liveBounded(events, {
|
||||
capacity: subscriberCapacity,
|
||||
accept: isOpenCodeEvent,
|
||||
})
|
||||
return Stream.make(connected).pipe(Stream.concat(live))
|
||||
}),
|
||||
).pipe(Stream.map(eventData), Stream.pipeThroughChannel(Sse.encode()))
|
||||
feed.subscribe.pipe(Effect.map((live) => Stream.make(EventFeed.frame(connected)).pipe(Stream.concat(live)))),
|
||||
)
|
||||
const heartbeat = Stream.tick("15 seconds").pipe(Stream.map(() => ": heartbeat\n\n"))
|
||||
return HttpServerResponse.stream(
|
||||
output.pipe(Stream.merge(heartbeat, { haltStrategy: "left" }), Stream.encodeText),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue