Skip to content

Commit 502832a

Browse files
committed
fix (chat): resolving buffering issues (WIP)
1 parent e67b899 commit 502832a

4 files changed

Lines changed: 38 additions & 30 deletions

File tree

src/client/app/api/chat/message/route.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ export const POST = withAuth(async function POST(request, { authHeader }) {
7272
"Content-Type": "application/x-ndjson",
7373
"Cache-Control": "no-cache",
7474
Connection: "keep-alive",
75-
"X-Accel-Buffering": "no" // Disable buffering on Netlify/Vercel
75+
"X-Accel-Buffering": "no", // Disable buffering on Netlify/Vercel
76+
"Content-Encoding": "identity"
7677
}
7778
})
7879
} catch (error) {

src/client/netlify.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
[build]
22
command = "npm run build"
3-
publish = ".next"
3+
publish = ".next"
4+
[[headers]]
5+
for = "/api/chat/message"
6+
[headers.values]
7+
Cache-Control = "no-cache, no-store, must-revalidate"
8+
Content-Encoding = "identity"
9+
X-Accel-Buffering = "no"

src/server/main/chat/routes.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ async def chat_endpoint(
4141

4242
async def event_stream_generator():
4343
try:
44-
# Pass the full message history directly to the LLM stream generator
4544
async for event in generate_chat_llm_stream(
4645
user_id,
4746
request_body.messages,
@@ -53,16 +52,28 @@ async def event_stream_generator():
5352
enable_maps=request_body.enable_maps,
5453
enable_shopping=request_body.enable_shopping
5554
):
56-
if not event: continue
57-
yield json.dumps(event) + "\n"
55+
if not event:
56+
continue
57+
# yield as bytes and flush
58+
chunk = (json.dumps(event) + "\n").encode("utf-8")
59+
yield chunk
60+
await asyncio.sleep(0) # Force control back to event loop
5861
except asyncio.CancelledError:
59-
logger.info(f"Client disconnected, stream cancelled for user {user_id}.")
62+
logger.info(f"Client disconnected, stream cancelled for user {user_id}.")
6063
except Exception as e:
6164
logger.error(f"Error in chat stream for user {user_id}: {e}", exc_info=True)
6265
error_response = {
6366
"type": "error",
6467
"message": "Sorry, I encountered an error while processing your request."
6568
}
66-
yield json.dumps(error_response) + "\n"
69+
yield (json.dumps(error_response) + "\n").encode("utf-8")
6770

68-
return StreamingResponse(event_stream_generator(), media_type="application/x-ndjson")
71+
return StreamingResponse(
72+
event_stream_generator(),
73+
media_type="application/x-ndjson",
74+
headers={
75+
"Cache-Control": "no-cache",
76+
"X-Accel-Buffering": "no", # Disable Nginx buffering
77+
"Transfer-Encoding": "chunked", # Hint chunked encoding
78+
}
79+
)

src/server/nginx.conf

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,35 +15,25 @@ server {
1515
location /chat/message {
1616
proxy_pass http://backend_app;
1717

18-
# Streaming-Specific Settings
19-
proxy_set_header Host $host;
20-
proxy_set_header X-Real-IP $remote_addr;
21-
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
22-
proxy_set_header X-Forwarded-Proto $scheme;
23-
24-
# Critical: Disable buffering for this endpoint
18+
# Prevent buffering
2519
proxy_buffering off;
20+
proxy_cache off;
21+
proxy_request_buffering off;
2622

27-
# Increase timeouts for long-lived stream
28-
proxy_read_timeout 86400s;
29-
proxy_send_timeout 86400s;
23+
# Disable gzip (interferes with chunked encoding)
24+
gzip off;
3025

31-
# Required for keep-alive connections
26+
# Streaming-friendly headers
3227
proxy_http_version 1.1;
3328
proxy_set_header Connection '';
34-
35-
# Add CORS headers if needed, though your app likely handles this.
36-
add_header 'Access-Control-Allow-Origin' '*' always;
37-
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
38-
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
39-
if ($request_method = 'OPTIONS') {
40-
add_header 'Access-Control-Max-Age' 1728000;
41-
add_header 'Content-Type' 'text/plain; charset=utf-8';
42-
add_header 'Content-Length' 0;
43-
return 204;
44-
}
29+
chunked_transfer_encoding on;
30+
31+
# CORS and other headers (keep yours)
32+
add_header Cache-Control "no-cache";
33+
add_header X-Accel-Buffering "no" always; # Netlify/Vercel/CDNs respect this
4534
}
4635

36+
4737
# ADDED: Location block for WebSocket notifications
4838
location /api/ws/notifications {
4939
proxy_pass http://backend_app;

0 commit comments

Comments
 (0)