···
(** {1 DNS Resolution} *)
let resolve_endpoint (pool : ('clock, 'net) internal) endpoint =
-
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))
-
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);
-
m "Failed to resolve hostname: %s" (Endpoint.host endpoint));
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
-
if attempt > retry_count then begin
-
m "Failed to connect to %a after %d attempts" Endpoint.pp endpoint
-
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
-
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 =
-
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)
-
m "Found existing endpoint pool for %a" Endpoint.pp endpoint);
-
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
-
m "Another fiber created pool for %a" Endpoint.pp endpoint);
(* Create new endpoint pool *)
···
let mutex = Eio.Mutex.create () in
-
m "Creating new endpoint pool for %a (max_connections=%d)"
(Config.max_connections_per_endpoint pool.config));
-
m "About to create Eio.Pool for %a" Endpoint.pp endpoint);
(Config.max_connections_per_endpoint pool.config)
-
m "Validate called for connection to %a" Endpoint.pp
-
(* Called before reusing from pool *)
let healthy = is_healthy pool ~check_readable:false conn in
-
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)
-
"Connection to %a failed validation, creating new \
(* Called when removing from pool *)
Eio.Cancel.protect (fun () ->
···
Eio.Mutex.use_rw ~protect:true mutex (fun () ->
stats.total_closed <- stats.total_closed + 1)))
-
m "Factory function called for %a" Endpoint.pp endpoint);
let conn = create_connection pool endpoint in
-
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);
-
m "Factory function failed for %a: %s" Endpoint.pp
-
endpoint (Printexc.to_string e));
-
(* Update error stats *)
Eio.Mutex.use_rw ~protect:true mutex (fun () ->
stats.errors <- stats.errors + 1);
-
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;
-
m "Endpoint pool added to hashtable for %a" Endpoint.pp
(** {1 Public API - Pool Creation} *)
···
-
(* Error - close connection so it won't be reused *)
-
m "Error with connection to %a: %s" Endpoint.pp endpoint
-
(Printexc.to_string e));
close_internal pool conn;