···
| Invalid_config of string
| Invalid_endpoint of string
31
-
exception Pool_error of error
let pp_error ppf = function
| Dns_resolution_failed { hostname } ->
Fmt.pf ppf "DNS resolution failed for hostname: %s" hostname
···
let resolve_endpoint (pool : ('clock, 'net) internal) endpoint =
Log.debug (fun m -> m "Resolving %a..." Endpoint.pp endpoint);
118
-
Eio.Net.getaddrinfo_stream pool.net (Endpoint.host endpoint)
119
-
~service:(string_of_int (Endpoint.port endpoint))
121
-
Log.debug (fun m -> m "Got address list for %a" Endpoint.pp endpoint);
124
-
Log.debug (fun m ->
125
-
m "Resolved %a to %a" Endpoint.pp endpoint Eio.Net.Sockaddr.pp addr);
129
-
m "Failed to resolve hostname: %s" (Endpoint.host endpoint));
132
-
(Dns_resolution_failed { hostname = Endpoint.host endpoint }))
117
+
Eio.Net.getaddrinfo_stream pool.net (Endpoint.host endpoint)
118
+
~service:(string_of_int (Endpoint.port endpoint))
120
+
Log.debug (fun m -> m "Got address list for %a" Endpoint.pp endpoint);
123
+
Log.debug (fun m ->
124
+
m "Resolved %a to %a" Endpoint.pp endpoint Eio.Net.Sockaddr.pp addr);
128
+
m "Failed to resolve hostname: %s" (Endpoint.host endpoint));
129
+
raise (err (Dns_resolution_failed { hostname = Endpoint.host endpoint }))
130
+
with Eio.Io _ as ex ->
131
+
let bt = Printexc.get_raw_backtrace () in
132
+
Eio.Exn.reraise_with_context ex bt "resolving %a" Endpoint.pp endpoint
(** {1 Connection Creation with Retry} *)
···
m "Failed to connect to %a after %d attempts" Endpoint.pp endpoint
145
-
(Connection_failed { endpoint; attempts = retry_count; last_error }))
143
+
raise (err (Connection_failed { endpoint; attempts = retry_count; last_error }))
···
(* Connect with optional timeout *)
158
-
match Config.connect_timeout pool.config with
160
-
Eio.Time.with_timeout_exn pool.clock timeout (fun () ->
161
-
Eio.Net.connect ~sw:pool.sw pool.net addr)
162
-
| None -> Eio.Net.connect ~sw:pool.sw pool.net addr
157
+
match Config.connect_timeout pool.config with
159
+
Eio.Time.with_timeout_exn pool.clock timeout (fun () ->
160
+
Eio.Net.connect ~sw:pool.sw pool.net addr)
161
+
| None -> Eio.Net.connect ~sw:pool.sw pool.net addr
162
+
with Eio.Io _ as ex ->
163
+
let bt = Printexc.get_raw_backtrace () in
164
+
Eio.Exn.reraise_with_context ex bt "connecting to %a" Endpoint.pp endpoint
···
173
-
Log.debug (fun m ->
174
-
m "Initiating TLS handshake with %a" Endpoint.pp endpoint);
176
-
Domain_name.(host_exn (of_string_exn (Endpoint.host endpoint)))
178
-
let tls_flow = Tls_eio.client_of_flow ~host tls_config socket in
180
-
m "TLS connection established to %a" Endpoint.pp endpoint);
181
-
(tls_flow :> connection)
176
+
Log.debug (fun m ->
177
+
m "Initiating TLS handshake with %a" Endpoint.pp endpoint);
179
+
Domain_name.(host_exn (of_string_exn (Endpoint.host endpoint)))
181
+
let tls_flow = Tls_eio.client_of_flow ~host tls_config socket in
183
+
m "TLS connection established to %a" Endpoint.pp endpoint);
184
+
(tls_flow :> connection)
185
+
with Eio.Io _ as ex ->
186
+
let bt = Printexc.get_raw_backtrace () in
187
+
Eio.Exn.reraise_with_context ex bt "TLS handshake with %a" Endpoint.pp endpoint
let now = get_time pool in
···
mutex = Eio.Mutex.create ();
195
-
| Eio.Time.Timeout as e ->
201
+
| Eio.Time.Timeout ->
m "Connection timeout to %a (attempt %d)" Endpoint.pp endpoint attempt);
198
-
let error_msg = Printexc.to_string e in
if attempt >= Config.connect_retry_count pool.config then
(* Last attempt - convert to our error type *)
match Config.connect_timeout pool.config with
203
-
raise (Pool_error (Connection_timeout { endpoint; timeout }))
208
+
raise (err (Connection_timeout { endpoint; timeout }))
208
-
{ endpoint; attempts = attempt; last_error = error_msg }))
210
+
raise (err (Connection_failed
211
+
{ endpoint; attempts = attempt; last_error = "Timeout" }))
(* Retry with exponential backoff *)
···
*. (2.0 ** float_of_int (attempt - 1))
Eio.Time.sleep pool.clock delay;
216
-
create_connection_with_retry pool endpoint (attempt + 1) error_msg
219
+
create_connection_with_retry pool endpoint (attempt + 1) "Timeout"
219
-
(* Other errors - retry with backoff *)
220
-
let error_msg = Printexc.to_string e in
221
+
| Eio.Io _ as ex ->
222
+
(* Eio IO errors - retry with backoff and add context on final failure *)
223
+
let error_msg = Printexc.to_string ex in
m "Connection attempt %d to %a failed: %s" attempt Endpoint.pp
···
Eio.Time.sleep pool.clock delay;
create_connection_with_retry pool endpoint (attempt + 1) error_msg)
235
-
{ endpoint; attempts = attempt; last_error = error_msg }))
235
+
let bt = Printexc.get_raw_backtrace () in
236
+
Eio.Exn.reraise_with_context ex bt "after %d retry attempts" attempt
let create_connection (pool : ('clock, 'net) internal) endpoint =
create_connection_with_retry pool endpoint 1 "No attempts made"
···
let with_connection t endpoint f =
Eio.Switch.run (fun sw -> f (connection ~sw t endpoint))
560
-
let with_connection_exn t endpoint f =
561
-
try with_connection t endpoint f with Pool_error e -> raise (err e)
(** {1 Public API - Statistics} *)