mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
Implements the chatd stabilization RFC. Combines: - https://github.com/coder/coder/pull/25908 - https://github.com/coder/coder/pull/25923 - https://github.com/coder/coder/pull/26109 - https://github.com/coder/coder/pull/26110 - https://github.com/coder/coder/pull/26111 - https://github.com/coder/coder/pull/26112
61 lines
2.0 KiB
Go
61 lines
2.0 KiB
Go
package chatd
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/google/uuid"
|
|
"golang.org/x/xerrors"
|
|
|
|
"cdr.dev/slog/v3"
|
|
"github.com/coder/coder/v2/coderd/x/chatd/messagepartbuffer"
|
|
)
|
|
|
|
// LocalStreamPartsDialerConfig configures an in-process stream parts dialer.
|
|
type LocalStreamPartsDialerConfig struct {
|
|
Buffer *messagepartbuffer.Buffer
|
|
Logger slog.Logger
|
|
}
|
|
|
|
// NewLocalStreamPartsDialer returns a dialer that streams message parts through
|
|
// in-process channels while using the same stream serving loop as WebSockets.
|
|
func NewLocalStreamPartsDialer(cfg LocalStreamPartsDialerConfig) StreamPartsDialer {
|
|
return func(ctx context.Context, input StreamPartsDialInput) (StreamPartsSession, error) {
|
|
if cfg.Buffer == nil {
|
|
return nil, xerrors.New("message part buffer is not configured")
|
|
}
|
|
serverTransport, clientTransport := newStreamPartsChannelTransportPair()
|
|
logger := cfg.Logger.Named("chat_stream_parts").With(slog.F("chat_id", input.ChatID))
|
|
endpoint := streamPartsEndpoint{
|
|
chatID: input.ChatID,
|
|
buffer: cfg.Buffer,
|
|
logger: logger,
|
|
}
|
|
serveCtx, cancel := context.WithCancel(ctx)
|
|
go func() {
|
|
defer cancel()
|
|
defer func() {
|
|
_ = serverTransport.Close()
|
|
}()
|
|
if err := endpoint.serve(serveCtx, serverTransport); err != nil && !streamPartsExpectedTransportClose(err) {
|
|
logger.Debug(serveCtx, "chat stream parts closed", slog.Error(err))
|
|
}
|
|
}()
|
|
return newStreamPartsTransportSession(serveCtx, clientTransport), nil
|
|
}
|
|
}
|
|
|
|
func streamPartsDialerForServer(workerID uuid.UUID, local StreamPartsDialer, remote StreamPartsDialer) StreamPartsDialer {
|
|
return func(ctx context.Context, input StreamPartsDialInput) (StreamPartsSession, error) {
|
|
if local == nil && remote == nil {
|
|
return nil, xerrors.New("stream parts dialer is not configured")
|
|
}
|
|
if remote == nil || input.WorkerID == uuid.Nil || input.WorkerID == workerID {
|
|
if local == nil {
|
|
return nil, xerrors.New("local stream parts dialer is not configured")
|
|
}
|
|
return local(ctx, input)
|
|
}
|
|
return remote(ctx, input)
|
|
}
|
|
}
|