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
Tests added:
TestTCPBackpressure: Verifies TCP backpressure handling with slow client
TestConcurrentSSEStreams: Confirms HTTP/2 multiplexing works correctly
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
**#32 HTTP/2 multiplexing for concurrent streams**
- Enable HTTP/2 in server config via http2.ConfigureServer()
- Increase MaxConnsPerHost to 10 for better concurrency
- 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
**Tests added:**
- TestTCPBackpressure: Verifies TCP backpressure handling with slow client
- TestConcurrentSSEStreams: Confirms HTTP/2 multiplexing works correctly
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.
Enable X-Service: workflow routing to Temporal via ServiceAdapter.
Users can now specify namespace/domain in request payload for multi-tenant
workflow access.
Changes:
- Implement WorkflowAdapter in serviceadapter/workflow_adapter.go
* Defines 10 workflow resources: start, describe, list, history,
terminate, cancel, signal, query, reset, update
* Each resource validates namespace parameter in payload
* Forwards requests to Temporal gRPC handler
- Add GetWorkflowSpec() to define ServiceAdapter spec with:
* Upstream: grpc://temporal:7233
* Auth requirements per operation (execute, read, signal, query)
* Request/response schemas for validation
- Wire WorkflowAdapter into main.go:
* Register workflow adapter in serviceadapter registry
* Initialize with temporal handler for gRPC forwarding
- Remove old empty WorkflowAdapter stub from adapters.go
Usage:
curl -X POST https://api.riotpiao.com/ \
-H 'X-Service: workflow' \
-H 'X-Resource: start' \
-H 'Authorization: Bearer TOKEN' \
-d '{
"namespace": "default",
"workflow_id": "my-workflow",
"workflow_type": "MyWorkflow",
"task_queue": "default"
}'
Namespace is required in all workflow operations and must be specified
by the client in the request payload. This enables multi-tenant support
where different teams access their own Temporal namespaces.
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.
Addresses three critical network issues for LLM streaming performance:
#33 Disable proxy buffering for SSE
#32 HTTP/2 multiplexing for concurrent streams
#31 TCP backpressure for streaming LLM responses
Tests added:
be4d33eb87tocc9a32f53aRemove deprecated /workflows HTTP endpoint in favor of unified X-Service header routing. All workflow operations now route through: X-Service: workflow X-Resource: {action} (start, describe, signal, query, etc) This consolidates routing patterns and allows users to specify domain/ namespace via request payload instead of path prefixes. Changes: - Remove internal/proxy/workflows.go (484 lines of predefined workflows) - Remove internal/proxy/workflows_test.go - Remove /workflows handler from proxy.ServeHTTP() - Update README.md to document X-Service routing pattern - Add migration note: use X-Service: workflow instead of /workflows WorkflowAdapter in serviceadapter/ handles X-Service: workflow requests and forwards to Temporal gRPC API. Users can now specify domain/namespace in request payload for multi-tenant workflow access. Related: #26Enable X-Service: workflow routing to Temporal via ServiceAdapter. Users can now specify namespace/domain in request payload for multi-tenant workflow access. Changes: - Implement WorkflowAdapter in serviceadapter/workflow_adapter.go * Defines 10 workflow resources: start, describe, list, history, terminate, cancel, signal, query, reset, update * Each resource validates namespace parameter in payload * Forwards requests to Temporal gRPC handler - Add GetWorkflowSpec() to define ServiceAdapter spec with: * Upstream: grpc://temporal:7233 * Auth requirements per operation (execute, read, signal, query) * Request/response schemas for validation - Wire WorkflowAdapter into main.go: * Register workflow adapter in serviceadapter registry * Initialize with temporal handler for gRPC forwarding - Remove old empty WorkflowAdapter stub from adapters.go Usage: curl -X POST https://api.riotpiao.com/ \ -H 'X-Service: workflow' \ -H 'X-Resource: start' \ -H 'Authorization: Bearer TOKEN' \ -d '{ "namespace": "default", "workflow_id": "my-workflow", "workflow_type": "MyWorkflow", "task_queue": "default" }' Namespace is required in all workflow operations and must be specified by the client in the request payload. This enables multi-tenant support where different teams access their own Temporal namespaces.