Skip to content

fix(streaming): add heartbeat keepalive + connection pooling#27

Open
garywhat wants to merge 2 commits into
vibe-coding-labs:mainfrom
garywhat:fix/streaming-heartbeat
Open

fix(streaming): add heartbeat keepalive + connection pooling#27
garywhat wants to merge 2 commits into
vibe-coding-labs:mainfrom
garywhat:fix/streaming-heartbeat

Conversation

@garywhat

Copy link
Copy Markdown

Summary

Upstream JoyCode API buffers the entire response before sending anything (TTFB 10-30s for reasoning models). Without keepalive, downstream clients (Claude Code, OpenAI clients) time out or show "no response" during this gap.

  • Add SSE heartbeat goroutines for OpenAI (pkg/openai/chat.go) and Anthropic (pkg/anthropic/handler.go) streaming paths that send comment lines (": ...") every 15s while waiting for upstream
  • Parse usage from SSE data lines in OpenAI streaming so token consumption is logged correctly (previously missing for streaming requests)
  • Add shared http.Transport with connection pooling in pkg/joycode/client.go so clients reuse TCP connections instead of dialing anew for every request
  • Add graceful shutdown via stopCh for background goroutines in cmd/JoyCode2Api/serve.go
  • Add pkg/common.IsTimeoutError helper for timeout detection across packages

Background

This addresses the streaming stability issues reported in #2 and #12 (the "stream failed / read first line: EOF" symptom that occurs when the upstream TTFB exceeds client timeouts).

Test plan

  • Go build passes
  • Started server locally, verified OpenAI streaming endpoint sends heartbeat comments during upstream wait
  • Verified Anthropic streaming endpoint sends ping events during upstream wait
  • Verified token usage is logged for streaming requests (checked dashboard stats)
  • Verified graceful shutdown exits background goroutines cleanly

Generated with Devin

garywhat and others added 2 commits June 30, 2026 15:08
Upstream JoyCode API buffers the entire response before sending anything
(TTFB 10-30s for reasoning models). Without keepalive, downstream clients
(Claude Code, OpenAI clients) time out or show "no response" during this
gap.

- Add SSE heartbeat goroutines for OpenAI and Anthropic streaming paths
  that send comment lines (": ...") every 15s while waiting for upstream
- Parse usage from SSE data lines in OpenAI streaming for token logging
- Add shared http.Transport with connection pooling in joycode client
- Add graceful shutdown via stopCh for background goroutines in serve
- Add pkg/common.IsTimeoutError helper for timeout detection

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Resolve conflict in pkg/joycode/client.go: keep both defaultTransport
(connection pooling from this PR) and envOr (configurable BaseURL from
upstream vibe-coding-labs#24).

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant