My agentic slop goes here. Not intended for anyone else!
1(** Conpool - Protocol-agnostic TCP/IP connection pooling library for Eio *)
2
3(** {1 Logging} *)
4
5val src : Logs.Src.t
6(** Logs source for conpool. Configure logging with:
7 {[
8 Logs.Src.set_level Conpool.src (Some Logs.Debug);
9 Logs.set_reporter (Logs_fmt.reporter ());
10 ]}
11*)
12
13(** {1 Core Types} *)
14
15(** Network endpoint *)
16module Endpoint : sig
17 type t
18 (** Network endpoint identified by host and port *)
19
20 val make : host:string -> port:int -> t
21 (** Create an endpoint *)
22
23 val host : t -> string
24 (** Get the hostname *)
25
26 val port : t -> int
27 (** Get the port number *)
28
29 val pp : Format.formatter -> t -> unit
30 (** Pretty-print an endpoint *)
31
32 val equal : t -> t -> bool
33 (** Compare two endpoints for equality *)
34
35 val hash : t -> int
36 (** Hash an endpoint *)
37end
38
39(** TLS configuration *)
40module Tls_config : sig
41 type t
42 (** TLS configuration applied to all connections in a pool *)
43
44 val make : config:Tls.Config.client -> ?servername:string -> unit -> t
45 (** Create TLS configuration.
46 @param config TLS client configuration
47 @param servername Optional SNI server name override. If None, uses endpoint host *)
48
49 val config : t -> Tls.Config.client
50 (** Get the TLS client configuration *)
51
52 val servername : t -> string option
53 (** Get the SNI server name override *)
54
55 val pp : Format.formatter -> t -> unit
56 (** Pretty-print TLS configuration *)
57end
58
59(** Connection handle *)
60module Connection : sig
61 type t
62 (** Opaque connection handle with metadata *)
63
64 val flow : t -> [ `Close | `Flow | `R | `Shutdown | `W] Eio.Resource.t
65 (** Extract underlying Eio flow from connection *)
66
67 val endpoint : t -> Endpoint.t
68 (** Get the endpoint this connection is connected to *)
69
70 val created_at : t -> float
71 (** Get the creation timestamp *)
72
73 val last_used : t -> float
74 (** Get the last used timestamp *)
75
76 val use_count : t -> int
77 (** Get the number of times this connection has been used *)
78
79 val pp : Format.formatter -> t -> unit
80 (** Pretty-print connection metadata *)
81end
82
83(** Pool configuration *)
84module Config : sig
85 type t
86 (** Pool configuration *)
87
88 val make :
89 ?max_connections_per_endpoint:int ->
90 ?max_idle_time:float ->
91 ?max_connection_lifetime:float ->
92 ?max_connection_uses:int ->
93 ?health_check:([ `Close | `Flow | `R | `Shutdown | `W] Eio.Resource.t -> bool) ->
94 ?connect_timeout:float ->
95 ?connect_retry_count:int ->
96 ?connect_retry_delay:float ->
97 ?on_connection_created:(Endpoint.t -> unit) ->
98 ?on_connection_closed:(Endpoint.t -> unit) ->
99 ?on_connection_reused:(Endpoint.t -> unit) ->
100 unit -> t
101 (** Create pool configuration with optional parameters.
102 See field descriptions for defaults. *)
103
104 val default : t
105 (** Sensible defaults for most use cases:
106 - max_connections_per_endpoint: 10
107 - max_idle_time: 60.0s
108 - max_connection_lifetime: 300.0s
109 - max_connection_uses: None (unlimited)
110 - health_check: None
111 - connect_timeout: 10.0s
112 - connect_retry_count: 3
113 - connect_retry_delay: 0.1s
114 - hooks: None *)
115
116 val max_connections_per_endpoint : t -> int
117 val max_idle_time : t -> float
118 val max_connection_lifetime : t -> float
119 val max_connection_uses : t -> int option
120 val health_check : t -> ([ `Close | `Flow | `R | `Shutdown | `W] Eio.Resource.t -> bool) option
121 val connect_timeout : t -> float option
122 val connect_retry_count : t -> int
123 val connect_retry_delay : t -> float
124
125 val pp : Format.formatter -> t -> unit
126 (** Pretty-print configuration *)
127end
128
129(** Statistics for an endpoint *)
130module Stats : sig
131 type t
132 (** Statistics for a specific endpoint *)
133
134 val active : t -> int
135 (** Connections currently in use *)
136
137 val idle : t -> int
138 (** Connections in pool waiting to be reused *)
139
140 val total_created : t -> int
141 (** Total connections created (lifetime) *)
142
143 val total_reused : t -> int
144 (** Total times connections were reused *)
145
146 val total_closed : t -> int
147 (** Total connections closed *)
148
149 val errors : t -> int
150 (** Total connection errors *)
151
152 val pp : Format.formatter -> t -> unit
153 (** Pretty-print endpoint statistics *)
154end
155
156(** {1 Connection Pool} *)
157
158type ('clock, 'net) t
159(** Connection pool managing multiple endpoints, parameterized by clock and network types *)
160
161val create :
162 sw:Eio.Switch.t ->
163 net:'net Eio.Net.t ->
164 clock:'clock Eio.Time.clock ->
165 ?tls:Tls_config.t ->
166 ?config:Config.t ->
167 unit -> ('clock Eio.Time.clock, 'net Eio.Net.t) t
168(** Create connection pool bound to switch.
169 All connections will be closed when switch is released.
170
171 @param sw Switch for resource management
172 @param net Network interface for creating connections
173 @param clock Clock for timeouts and time-based validation
174 @param tls Optional TLS configuration applied to all connections
175 @param config Optional pool configuration (uses Config.default if not provided) *)
176
177(** {1 Connection Acquisition & Release} *)
178
179val with_connection :
180 ('clock Eio.Time.clock, 'net Eio.Net.t) t ->
181 Endpoint.t ->
182 ([ `Close | `Flow | `R | `Shutdown | `W] Eio.Resource.t -> 'a) ->
183 'a
184(** Acquire connection, use it, automatically release.
185
186 If idle connection available and healthy:
187 - Reuse from pool
188 Else:
189 - Create new connection (may block if endpoint at limit)
190
191 On success: connection returned to pool
192 On error: connection closed, not returned to pool
193
194 Example:
195 {[
196 let endpoint = Conpool.Endpoint.make ~host:"example.com" ~port:443 in
197 Conpool.with_connection pool endpoint (fun conn ->
198 (* Use conn for HTTP request, Redis command, etc. *)
199 Eio.Flow.copy_string "GET / HTTP/1.1\r\n\r\n" conn;
200 let buf = Eio.Buf_read.of_flow conn ~max_size:4096 in
201 Eio.Buf_read.take_all buf
202 )
203 ]}
204*)
205
206val acquire :
207 sw:Eio.Switch.t ->
208 ('clock Eio.Time.clock, 'net Eio.Net.t) t ->
209 Endpoint.t ->
210 Connection.t
211(** Manually acquire connection bound to switch. Must call [release] or [close] later.
212 Use [with_connection] instead unless you need explicit control.
213
214 The connection is bound to the provided switch and will be automatically
215 closed (but not released back to pool) when the switch finishes. *)
216
217val release :
218 ('clock Eio.Time.clock, 'net Eio.Net.t) t ->
219 Connection.t ->
220 unit
221(** Return connection to pool. Connection must be in clean state.
222 If connection is unhealthy, call [close] instead. *)
223
224val close :
225 ('clock Eio.Time.clock, 'net Eio.Net.t) t ->
226 Connection.t ->
227 unit
228(** Close connection immediately, remove from pool. *)
229
230(** {1 Connection Validation} *)
231
232val is_healthy :
233 ('clock Eio.Time.clock, 'net Eio.Net.t) t ->
234 ?check_readable:bool ->
235 Connection.t ->
236 bool
237(** Check if connection is healthy.
238
239 Validates:
240 - Not past max_connection_lifetime
241 - Not idle past max_idle_time
242 - Not exceeded max_connection_uses
243 - Optional: health_check function (from config)
244 - Optional: check_readable=true tests if socket still connected via 0-byte read
245
246 @param check_readable If true, performs a non-blocking read test on the socket *)
247
248val validate_and_release :
249 ('clock Eio.Time.clock, 'net Eio.Net.t) t ->
250 Connection.t ->
251 unit
252(** Validate connection health, then release to pool if healthy or close if not.
253 Equivalent to: if is_healthy pool conn then release pool conn else close pool conn *)
254
255(** {1 Statistics & Monitoring} *)
256
257val stats :
258 ('clock Eio.Time.clock, 'net Eio.Net.t) t ->
259 Endpoint.t ->
260 Stats.t
261(** Get statistics for specific endpoint *)
262
263val all_stats :
264 ('clock Eio.Time.clock, 'net Eio.Net.t) t ->
265 (Endpoint.t * Stats.t) list
266(** Get statistics for all endpoints in pool *)
267
268(** {1 Pool Management} *)
269
270(** Close all idle connections for endpoint (keeps active ones) *)
271val close_all_connections :
272 ('clock Eio.Time.clock, 'net Eio.Net.t) t ->
273 Endpoint.t ->
274 unit
275(** Close all connections for endpoint (blocks until active ones released) *)
276
277val close_pool :
278 ('clock Eio.Time.clock, 'net Eio.Net.t) t ->
279 unit
280(** Close entire pool. Blocks until all active connections released.
281 Automatically called when switch releases. *)