@cryptotaxi247 / netdata-1 / commits / 70efc0f3c

WebSocket: Increase inactivity timeout from 5 to 30 minutes (#21244)

* WebSocket: Increase inactivity timeout from 5 to 30 minutes The WebSocket inactivity timeout has been increased from 5 minutes (300 seconds) to 30 minutes (1800 seconds) to accommodate long-running queries and operations that may take extended time to complete. Changes: - Define timeout constants in websocket-internal.h for maintainability - WS_INACTIVITY_TIMEOUT increased from 300 to 1800 seconds - All timeout values now use named constants instead of magic numbers - Error message now dynamically shows timeout value in minutes This prevents premature disconnection of WebSocket clients waiting for responses from long-running operations while still detecting truly idle or dead connections. * updated models and pricing for mcp-web-client

Costa Tsaousis committed Oct 30, 2025 at 17:41 UTC 70efc0f3cea1f94df187cbe74c6e213341f3e20e
3 files changed +44 -20
src/web/mcp/mcp-web-client/llm-proxy.js
+29 -11
@@ -63,15 +63,23 @@ const MODEL_DEFINITIONS = {
63 contextWindow: 128000,
64 pricing: { input: 0.25, cacheRead: 0.025, output: 2.00 }
65 },
66 - 'gpt-5-nano': {
67 - contextWindow: 128000,
68 - pricing: { input: 0.05, cacheRead: 0.005, output: 0.40 }
66 + 'gpt-5-nano': {
67 + contextWindow: 128000,
68 + pricing: { input: 0.05, cacheRead: 0.005, output: 0.40 }
69 },
70 - 'gpt-5-chat-latest': {
71 - contextWindow: 128000,
72 - pricing: { input: 1.25, cacheRead: 0.125, output: 10.00 }
70 + 'gpt-5-chat-latest': {
71 + contextWindow: 128000,
72 + pricing: { input: 1.25, cacheRead: 0.125, output: 10.00 }
73 },
74 -
74 + 'gpt-5-pro': {
75 + contextWindow: 128000,
76 + pricing: { input: 15.00, cacheRead: 0.00, output: 120.00 }
77 + },
78 + 'gpt-5-codex': {
79 + contextWindow: 128000,
80 + pricing: { input: 1.25, cacheRead: 0.125, output: 10.00 }
81 + },
82 +
83 // GPT-4o Series
84 'gpt-4o': {
85 contextWindow: 128000,
@@ -407,11 +415,21 @@ const MODEL_DEFINITIONS = {
415 },
416
417 // Claude Sonnet 4
410 - 'claude-sonnet-4-20250514': {
411 - contextWindow: 200000,
412 - pricing: { input: 3.00, cacheWrite: 3.75, cacheRead: 0.30, output: 15.00 }
418 + 'claude-sonnet-4-20250514': {
419 + contextWindow: 200000,
420 + pricing: { input: 3.00, cacheWrite: 3.75, cacheRead: 0.30, output: 15.00 }
421 },
414 -
422 +
423 + // Claude 4.5 Series
424 + 'claude-sonnet-4-5': {
425 + contextWindow: 200000,
426 + pricing: { input: 3.00, cacheWrite: 3.75, cacheRead: 0.30, output: 15.00 }
427 + },
428 + 'claude-haiku-4-5': {
429 + contextWindow: 200000,
430 + pricing: { input: 1.00, cacheWrite: 1.25, cacheRead: 0.10, output: 5.00 }
431 + },
432 +
433 // Claude Sonnet 3.7
434 'claude-3-7-sonnet-20250219': {
435 contextWindow: 200000,
src/web/websocket/websocket-internal.h
+6
@@ -48,6 +48,12 @@ struct websocket_thread;
48 #define WS_MAX_OUTGOING_FRAME_SIZE (4ULL * 1024 * 1024) // 4MB max outgoing frame size for browser compatibility
49 #define WS_MAX_DECOMPRESSED_SIZE (200ULL * 1024 * 1024) // 200MB max inbound uncompressed message
50
51 +// WebSocket timeout constants (in seconds)
52 +#define WS_PERIODIC_PING_INTERVAL 60 // Send periodic ping every 60 seconds
53 +#define WS_IDLE_CHECK_INTERVAL 120 // Check if client is idle after 120 seconds
54 +#define WS_INACTIVITY_TIMEOUT 1800 // Disconnect after 30 minutes (1800 seconds) of inactivity
55 +#define WS_CLOSING_STATE_TIMEOUT 5 // Force close if stuck in closing state for 5 seconds
56 +
57 // WebSocket frame header structure - used for processing frame headers
58 typedef struct websocket_frame_header {
59 unsigned char fin:1;
src/web/websocket/websocket-thread.c
+9 -9
@@ -439,28 +439,28 @@ void websocket_thread(void *ptr) {
439 WS_CLIENT *next = wsc->next; // Save next in case we remove this client
440
441 if(wsc->state == WS_STATE_OPEN) {
442 - // Check if client is idle (no activity for over 120 seconds)
443 - if(now - wsc->last_activity_t > 120) {
442 + // Check if client is idle (no activity for over WS_IDLE_CHECK_INTERVAL seconds)
443 + if(now - wsc->last_activity_t > WS_IDLE_CHECK_INTERVAL) {
444 // Client is idle - send a ping to check if it's still alive
445 worker_is_busy(WORKERS_WEBSOCKET_SEND_PING);
446 websocket_protocol_send_ping(wsc, NULL, 0);
447
448 - // If no activity for over 300 seconds (5 minutes), consider it dead
449 - if(now - wsc->last_activity_t > 300) {
448 + // If no activity for over WS_INACTIVITY_TIMEOUT seconds, consider it dead
449 + if(now - wsc->last_activity_t > WS_INACTIVITY_TIMEOUT) {
450 worker_is_busy(WORKERS_WEBSOCKET_CLIENT_TIMEOUT);
451 - websocket_error(wsc, "Client timed out (no activity for over 5 minutes)");
451 + websocket_error(wsc, "Client timed out (no activity for over %d minutes)", WS_INACTIVITY_TIMEOUT / 60);
452 websocket_protocol_exception(wsc, WS_CLOSE_GOING_AWAY, "Timeout - no activity");
453 }
454 }
455 - // For normal clients, send periodic pings (every 60 seconds)
456 - else if(now - wsc->last_activity_t > 60) {
455 + // For normal clients, send periodic pings (every WS_PERIODIC_PING_INTERVAL seconds)
456 + else if(now - wsc->last_activity_t > WS_PERIODIC_PING_INTERVAL) {
457 worker_is_busy(WORKERS_WEBSOCKET_SEND_PING);
458 websocket_protocol_send_ping(wsc, NULL, 0);
459 }
460 }
461 else if(wsc->state == WS_STATE_CLOSING_SERVER || wsc->state == WS_STATE_CLOSING_CLIENT) {
462 - // If a client is in any CLOSING state for more than 5 seconds, force close it
463 - if(now - wsc->last_activity_t > 5) {
462 + // If a client is in any CLOSING state for more than WS_CLOSING_STATE_TIMEOUT seconds, force close it
463 + if(now - wsc->last_activity_t > WS_CLOSING_STATE_TIMEOUT) {
464 worker_is_busy(WORKERS_WEBSOCKET_CLIENT_STUCK);
465 websocket_error(wsc, "Forcing close (stuck in %s state)",
466 wsc->state == WS_STATE_CLOSING_SERVER ? "CLOSING_SERVER" : "CLOSING_CLIENT");