···
(** {1 DNS Resolution} *)
let resolve_endpoint (pool : ('clock, 'net) internal) endpoint =
114
-
Log.debug (fun m -> m "Resolving %a..." Endpoint.pp endpoint);
114
+
Log.debug (fun m -> m "Resolving %a" Endpoint.pp endpoint);
Eio.Net.getaddrinfo_stream pool.net (Endpoint.host endpoint)
~service:(string_of_int (Endpoint.port endpoint))
120
-
Log.debug (fun m -> m "Got address list for %a" Endpoint.pp endpoint);
m "Resolved %a to %a" Endpoint.pp endpoint Eio.Net.Sockaddr.pp addr);
128
-
m "Failed to resolve hostname: %s" (Endpoint.host endpoint));
126
+
(* Raise exception with error code - context will be added when caught *)
raise (err (Dns_resolution_failed { hostname = Endpoint.host endpoint }))
let bt = Printexc.get_raw_backtrace () in
···
let rec create_connection_with_retry (pool : ('clock, 'net) internal) endpoint
let retry_count = Config.connect_retry_count pool.config in
139
-
if attempt > retry_count then begin
141
-
m "Failed to connect to %a after %d attempts" Endpoint.pp endpoint
143
-
raise (err (Connection_failed { endpoint; attempts = retry_count; last_error }))
137
+
if attempt > retry_count then
138
+
(* Raise exception with error code - context will be added when caught *)
139
+
raise (err (Connection_failed { endpoint; attempts = retry_count; last_error }));
m "Connecting to %a (attempt %d/%d)" Endpoint.pp endpoint attempt
···
let addr = resolve_endpoint pool endpoint in
152
-
Log.debug (fun m -> m "Resolved %a to address" Endpoint.pp endpoint);
(* Connect with optional timeout *)
···
(Config.on_connection_closed pool.config)
let get_or_create_endpoint_pool (pool : ('clock, 'net) internal) endpoint =
326
-
Log.debug (fun m ->
327
-
m "Getting or creating endpoint pool for %a" Endpoint.pp endpoint);
(* First try with read lock *)
Eio.Mutex.use_ro pool.endpoints_mutex (fun () ->
Hashtbl.find_opt pool.endpoints endpoint)
335
-
Log.debug (fun m ->
336
-
m "Found existing endpoint pool for %a" Endpoint.pp endpoint);
339
-
Log.debug (fun m ->
340
-
m "No existing pool, need to create for %a" Endpoint.pp endpoint);
(* Need to create - use write lock *)
Eio.Mutex.use_rw ~protect:true pool.endpoints_mutex (fun () ->
(* Check again in case another fiber created it *)
match Hashtbl.find_opt pool.endpoints endpoint with
346
-
Log.debug (fun m ->
347
-
m "Another fiber created pool for %a" Endpoint.pp endpoint);
(* Create new endpoint pool *)
···
let mutex = Eio.Mutex.create () in
355
-
m "Creating new endpoint pool for %a (max_connections=%d)"
340
+
m "Creating endpoint pool for %a (max_connections=%d)"
(Config.max_connections_per_endpoint pool.config));
359
-
Log.debug (fun m ->
360
-
m "About to create Eio.Pool for %a" Endpoint.pp endpoint);
(Config.max_connections_per_endpoint pool.config)
366
-
Log.debug (fun m ->
367
-
m "Validate called for connection to %a" Endpoint.pp
369
-
(* Called before reusing from pool *)
let healthy = is_healthy pool ~check_readable:false conn in
373
-
Log.debug (fun m ->
374
-
m "Reusing connection to %a from pool" Endpoint.pp
(* Update stats for reuse *)
Eio.Mutex.use_rw ~protect:true mutex (fun () ->
stats.total_reused <- stats.total_reused + 1);
···
try check (Connection.flow conn) with _ -> false)
392
-
Log.debug (fun m ->
394
-
"Connection to %a failed validation, creating new \
396
-
Endpoint.pp endpoint);
(* Called when removing from pool *)
Eio.Cancel.protect (fun () ->
···
Eio.Mutex.use_rw ~protect:true mutex (fun () ->
stats.total_closed <- stats.total_closed + 1)))
408
-
Log.debug (fun m ->
409
-
m "Factory function called for %a" Endpoint.pp endpoint);
let conn = create_connection pool endpoint in
413
-
Log.debug (fun m ->
414
-
m "Connection created successfully for %a" Endpoint.pp
Eio.Mutex.use_rw ~protect:true mutex (fun () ->
stats.total_created <- stats.total_created + 1);
···
(Config.on_connection_created pool.config);
429
-
m "Factory function failed for %a: %s" Endpoint.pp
430
-
endpoint (Printexc.to_string e));
431
-
(* Update error stats *)
388
+
with Eio.Io _ as ex ->
389
+
(* Eio.Io exceptions already have full context from create_connection.
390
+
Just update error stats and let the exception propagate. *)
Eio.Mutex.use_rw ~protect:true mutex (fun () ->
stats.errors <- stats.errors + 1);
437
-
Log.debug (fun m ->
438
-
m "Eio.Pool created successfully for %a" Endpoint.pp endpoint);
let ep_pool = { pool = eio_pool; stats; mutex } in
Hashtbl.add pool.endpoints endpoint ep_pool;
443
-
Log.debug (fun m ->
444
-
m "Endpoint pool added to hashtable for %a" Endpoint.pp
(** {1 Public API - Pool Creation} *)
···
537
-
(* Error - close connection so it won't be reused *)
539
-
m "Error with connection to %a: %s" Endpoint.pp endpoint
540
-
(Printexc.to_string e));
489
+
(* Error during connection usage - close so it won't be reused.
490
+
The exception already has context from where it was raised. *)
close_internal pool conn;