Addresses three critical network issues for LLM streaming performance:
**#33 Disable proxy buffering for SSE**
- Add X-Accel-Buffering: no header to response
- Tells nginx/Ingress to stream events immediately instead of buffering
- Paired with ResponseController.Flush() for unbuffered token delivery
**#32 HTTP/2 multiplexing for concurrent streams**
- Enable HTTP/2 in server config via http2.ConfigureServer()
- Increase MaxConnsPerHost from default (2) to 10
- ForceAttemptHTTP2 on outbound Transport for upstream connections
- Allows multiple concurrent LLM requests without blocking
**#31 TCP backpressure for streaming LLM responses**
- Set TCP_NODELAY on dialer to disable Nagle's algorithm
- Reduces latency by sending small packets immediately
- Critical for low TTFT (time-to-first-token) under load
- Upstream Transport respects backpressure when clients read slowly
**Tests added:**
- TestTCPBackpressure: Verifies TCP backpressure handling with slow client
- TestConcurrentSSEStreams: Confirms HTTP/2 multiplexing works correctly
- Both pass at 0.11s and 0.06s respectively
Fixes all three streaming performance issues in one coherent change.
- Add sendGotify method to send notifications to Gotify server
- Support format: 'gotify' in SendMsgRequest
- Extract message ID from Gotify response
- Configurable via GOTIFY_URL and GOTIFY_TOKEN env vars
- Fallback graceful error if Gotify not configured
The workflow service is deployed in the temporal namespace:
temporal-frontend.temporal.svc.cluster.local:7233
Update ServiceAdapter to use correct namespace for workflow routing.
When the upstream LLM server expects a different model name than what
clients send, the gateway now rewrites the 'model' field in the request
body before forwarding.
Config example:
models:
- name: "ornith:35b" # client-facing name
address: "ornith-predictor:80"
upstreamModel: "qwen2.5:72b" # what upstream expects
Fixes 400 'model is required' errors when upstream model names differ.
- Wire WorkflowAdapter as internal handler (JSON-to-gRPC bridge)
- Add ServeHTTP to WorkflowAdapter: maps X-Resource to Temporal action
- Rename resource 'start' to 'execute' for consistency
- Add GET methods for describe/list/history resources
- Remove unused workflowAdapterImpl variable
- SDK clients can now send JSON, gateway translates to gRPC
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Time-to-First-Token (TTFT) and Inter-Token Latency (ITL) metrics for LLM inference observability
Metrics: llm_ttft_seconds, llm_itl_seconds, llm_tokens_total
Closes #31 #32 #33
When the upstream LLM server expects a different model name than what clients send, the gateway now rewrites the 'model' field in the request body before forwarding. Config example: models: - name: "ornith:35b" # client-facing name address: "ornith-predictor:80" upstreamModel: "qwen2.5:72b" # what upstream expects Fixes 400 'model is required' errors when upstream model names differ.ef79bf9a80tod999b02943