···
| Invalid_config msg -> Fmt.pf ppf "Invalid configuration: %s" msg
| Invalid_endpoint msg -> Fmt.pf ppf "Invalid endpoint: %s" msg
46
+
type Eio.Exn.err += E of error
48
+
let err e = Eio.Exn.create (E e)
51
+
Eio.Exn.register_pp (fun f -> function
53
+
Fmt.string f "Conpool ";
58
+
(** {1 Connection Types} *)
60
+
type connection_ty = [Eio.Resource.close_ty | Eio.Flow.two_way_ty]
61
+
type connection = connection_ty Eio.Resource.t
···
155
-
(socket :> [ `Close | `Flow | `R | `Shutdown | `W ] Eio.Resource.t)
172
+
(socket :> connection)
m "Initiating TLS handshake with %a" Endpoint.pp endpoint);
···
m "TLS connection established to %a" Endpoint.pp endpoint);
170
-
(tls_flow :> [ `Close | `Flow | `R | `Shutdown | `W ] Eio.Resource.t)
187
+
(tls_flow :> connection)
let now = get_time pool in
···
(** {1 Public API - Connection Management} *)
477
-
let with_connection (T pool) endpoint f =
494
+
let connection_internal ~sw (T pool) endpoint =
Log.debug (fun m -> m "Acquiring connection to %a" Endpoint.pp endpoint);
let ep_pool = get_or_create_endpoint_pool pool endpoint in
498
+
(* Create promises for connection handoff and cleanup signal *)
499
+
let conn_promise, conn_resolver = Eio.Promise.create () in
500
+
let done_promise, done_resolver = Eio.Promise.create () in
(* Increment active count *)
Eio.Mutex.use_rw ~protect:true ep_pool.mutex (fun () ->
ep_pool.stats.active <- ep_pool.stats.active + 1);
486
-
~finally:(fun () ->
487
-
(* Decrement active count *)
488
-
Eio.Mutex.use_rw ~protect:true ep_pool.mutex (fun () ->
489
-
ep_pool.stats.active <- ep_pool.stats.active - 1);
490
-
Log.debug (fun m -> m "Released connection to %a" Endpoint.pp endpoint))
492
-
(* Use Eio.Pool for resource management *)
493
-
Eio.Pool.use ep_pool.pool (fun conn ->
494
-
Log.debug (fun m ->
495
-
m "Using connection to %a (uses=%d)" Endpoint.pp endpoint
496
-
(Connection.use_count conn));
506
+
(* Fork a daemon fiber to manage the connection lifecycle *)
507
+
Eio.Fiber.fork_daemon ~sw (fun () ->
509
+
~finally:(fun () ->
510
+
(* Decrement active count *)
511
+
Eio.Mutex.use_rw ~protect:true ep_pool.mutex (fun () ->
512
+
ep_pool.stats.active <- ep_pool.stats.active - 1);
513
+
Log.debug (fun m -> m "Released connection to %a" Endpoint.pp endpoint))
515
+
(* Use Eio.Pool for resource management *)
516
+
Eio.Pool.use ep_pool.pool (fun conn ->
517
+
Log.debug (fun m ->
518
+
m "Using connection to %a (uses=%d)" Endpoint.pp endpoint
519
+
(Connection.use_count conn));
521
+
(* Update last used time and use count *)
522
+
Connection.update_usage conn ~now:(get_time pool);
524
+
(* Update idle stats (connection taken from idle pool) *)
525
+
Eio.Mutex.use_rw ~protect:true ep_pool.mutex (fun () ->
526
+
ep_pool.stats.idle <- max 0 (ep_pool.stats.idle - 1));
528
+
(* Hand off connection to caller *)
529
+
Eio.Promise.resolve conn_resolver conn.flow;
532
+
(* Wait for switch to signal cleanup *)
533
+
Eio.Promise.await done_promise;
535
+
(* Success - connection will be returned to pool by Eio.Pool *)
536
+
(* Update idle stats (connection returned to idle pool) *)
537
+
Eio.Mutex.use_rw ~protect:true ep_pool.mutex (fun () ->
538
+
ep_pool.stats.idle <- ep_pool.stats.idle + 1);
542
+
(* Error - close connection so it won't be reused *)
544
+
m "Error with connection to %a: %s" Endpoint.pp endpoint
545
+
(Printexc.to_string e));
546
+
close_internal pool conn;
498
-
(* Update last used time and use count *)
499
-
Connection.update_usage conn ~now:(get_time pool);
548
+
(* Update error stats *)
549
+
Eio.Mutex.use_rw ~protect:true ep_pool.mutex (fun () ->
550
+
ep_pool.stats.errors <- ep_pool.stats.errors + 1);
501
-
(* Update idle stats (connection taken from idle pool) *)
502
-
Eio.Mutex.use_rw ~protect:true ep_pool.mutex (fun () ->
503
-
ep_pool.stats.idle <- max 0 (ep_pool.stats.idle - 1));
506
-
let result = f conn.flow in
554
+
(* Signal cleanup when switch ends *)
555
+
Eio.Switch.on_release sw (fun () ->
556
+
Eio.Promise.resolve done_resolver ());
508
-
(* Success - connection will be returned to pool by Eio.Pool *)
509
-
(* Update idle stats (connection returned to idle pool) *)
510
-
Eio.Mutex.use_rw ~protect:true ep_pool.mutex (fun () ->
511
-
ep_pool.stats.idle <- ep_pool.stats.idle + 1);
558
+
(* Return the connection *)
559
+
Eio.Promise.await conn_promise
515
-
(* Error - close connection so it won't be reused *)
517
-
m "Error using connection to %a: %s" Endpoint.pp endpoint
518
-
(Printexc.to_string e));
519
-
close_internal pool conn;
561
+
let connection ~sw t endpoint = connection_internal ~sw t endpoint
521
-
(* Update error stats *)
522
-
Eio.Mutex.use_rw ~protect:true ep_pool.mutex (fun () ->
523
-
ep_pool.stats.errors <- ep_pool.stats.errors + 1);
563
+
let with_connection t endpoint f =
564
+
Eio.Switch.run (fun sw -> f (connection ~sw t endpoint))
566
+
let with_connection_exn t endpoint f =
567
+
try with_connection t endpoint f with Pool_error e -> raise (err e)
(** {1 Public API - Statistics} *)