(globals: Arc<Globals>, tcp_listener: TcpListener)
| 296 | } |
| 297 | |
| 298 | async fn tcp_acceptor(globals: Arc<Globals>, tcp_listener: TcpListener) -> Result<(), Error> { |
| 299 | let runtime_handle = globals.runtime_handle.clone(); |
| 300 | let timeout = globals.tcp_timeout; |
| 301 | let concurrent_connections = globals.tcp_concurrent_connections.clone(); |
| 302 | let active_connections = globals.tcp_active_connections.clone(); |
| 303 | loop { |
| 304 | let (mut client_connection, client_addr) = match tcp_listener.accept().await { |
| 305 | Ok(x) => x, |
| 306 | Err(e) => { |
| 307 | if e.kind() == std::io::ErrorKind::WouldBlock { |
| 308 | continue; |
| 309 | } |
| 310 | error!("TCP accept error: {}", e); |
| 311 | |
| 312 | // Rate limit repeated errors to avoid spinning |
| 313 | let is_resource_error = matches!( |
| 314 | e.kind(), |
| 315 | std::io::ErrorKind::ConnectionRefused |
| 316 | | std::io::ErrorKind::ConnectionReset |
| 317 | | std::io::ErrorKind::ConnectionAborted |
| 318 | | std::io::ErrorKind::AddrInUse |
| 319 | | std::io::ErrorKind::AddrNotAvailable |
| 320 | ); |
| 321 | |
| 322 | if is_resource_error { |
| 323 | // For resource-related errors, try to free up connections |
| 324 | let mut connections = active_connections.lock(); |
| 325 | let freed = connections.len().min(5); |
| 326 | for _ in 0..freed { |
| 327 | if let Some(tx_oldest) = connections.pop_back() { |
| 328 | let _ = tx_oldest.send(()); |
| 329 | } |
| 330 | } |
| 331 | info!("Freed {} connections to recover from resource error", freed); |
| 332 | } |
| 333 | |
| 334 | // Add delay to prevent CPU spinning on persistent errors |
| 335 | tokio::time::sleep(Duration::from_secs(1)).await; |
| 336 | continue; |
| 337 | } |
| 338 | }; |
| 339 | |
| 340 | if let Some(ref rate_limiter) = globals.rate_limiter { |
| 341 | if !rate_limiter.is_allowed(client_addr.ip()) { |
| 342 | debug!("Rate limit exceeded for {}", client_addr.ip()); |
| 343 | #[cfg(feature = "metrics")] |
| 344 | globals.varz.client_queries_rate_limited.inc(); |
| 345 | continue; |
| 346 | } |
| 347 | } |
| 348 | |
| 349 | let (tx, rx) = oneshot::channel::<()>(); |
| 350 | let tx_channel_index = { |
| 351 | let mut active_connections = active_connections.lock(); |
| 352 | if active_connections.is_full() { |
| 353 | let tx_oldest = active_connections.pop_back().unwrap(); |
| 354 | let _ = tx_oldest.send(()); |
| 355 | } |
no test coverage detected