Spindle_postgres.PoolConnections, made up front and borrowed one at a time: the Postgres backend's pool (Rowtype_postgres.Pool), each connection bounded as Spindle_postgres.connect bounds one, and a transaction on a borrow.
val create :
sw:Eio.Switch.t ->
net:_ Eio.Net.t ->
mono_clock:_ Eio.Time.Mono.t ->
?size:int ->
?wait:Mtime.Span.t ->
?statement_timeout:Mtime.Span.t ->
?idle_in_transaction_timeout:Mtime.Span.t ->
?parameters:(string * string) list ->
?timeout:Mtime.Span.t ->
?statement_cache:int ->
?reset:bool ->
?max_lifetime:Mtime.Span.t ->
?idle_check:Mtime.Span.t ->
Rowtype_postgres.Conninfo.t ->
(t, [> Rowtype.error ]) Stdlib.resultThe pool Rowtype_postgres.Pool.create makes, to the database target names, every option but the bounds passed through. The bounds and parameters are Spindle_postgres.connect's.
val use :
?wait:Mtime.Span.t ->
t ->
(Rowtype_postgres.conn ->
('a, [> `Pool of [ `Busy | `Closed ] ] as 'e) Stdlib.result) ->
('a, 'e) Stdlib.resultBorrow a connection for work, as Rowtype_postgres.Pool.use lends one, and give it back when work returns. `Pool `Busy -- no connection within the wait -- joins the work's own failures, so that an overloaded server says so instead of answering late, and so does `Pool `Closed, at once, for a pool closed or closing under the borrow, which will never lend again; Spindle_postgres.refusal words both.
val exec :
?wait:Mtime.Span.t ->
t ->
('p, 'r) Rowtype.statement ->
'p ->
('r, [> `Pool of [ `Busy | `Closed ] | Rowtype.error ]) Stdlib.resultval transaction :
?wait:Mtime.Span.t ->
?keep:('e -> bool) ->
?isolation:Rowtype_postgres.Transaction.isolation ->
?retries:int ->
t ->
(Rowtype_postgres.conn ->
('a,
[> Rowtype_postgres.Transaction.failure | `Pool of [ `Busy | `Closed ] ] as 'e)
Stdlib.result) ->
('a, 'e) Stdlib.resultuse and Rowtype_postgres.Transaction.within together: borrow a connection and run one transaction on it, at isolation and run again up to retries times, Ok committing and Error rolling back unless keep says otherwise. A retry keeps the connection it borrowed. Every failure of its own -- no connection within the wait, a transaction that did not commit -- arrives in the caller's error type:
Spindle_postgres.Pool.transaction pool (fun db ->
let* id = Pg.run db add_user (name, email) in
let* () = Pg.run db log_event (id, "signed_up") in
Ok id)val measure : ?name:string -> t -> Spindle.Metrics.t -> unitThe pool's connections as gauges, read from stats whenever the metrics are, so the pool keeps no count of its own: OpenTelemetry's db.client.connection.count by db.client.connection.state, idle or used, and db.client.connection.pending_requests, the borrows waiting -- each under db.client.connection.pool.name, postgres unless named, so two pools measured on one registry are two series of each.
Spindle_postgres.Pool.measure pool metricsval check : ?name:string -> t -> Spindle.Health.checkThe pool as a readiness check, postgres unless named: a connection borrowed and select 1 answered, within the pool's wait and the statement timeout. A pool with no connection idle passes without a borrow, since every one of them is lent to a request the database is answering -- failing it would take a server out of service for being busy, which is when it is needed most. A pool closed, or closing, fails it.
val close : t -> unitAs Rowtype_postgres.Pool.close.
val run :
?size:int ->
?wait:Mtime.Span.t ->
?statement_timeout:Mtime.Span.t ->
?idle_in_transaction_timeout:Mtime.Span.t ->
?parameters:(string * string) list ->
?timeout:Mtime.Span.t ->
?statement_cache:int ->
?reset:bool ->
?max_lifetime:Mtime.Span.t ->
?idle_check:Mtime.Span.t ->
< net : _ Eio.Net.t ; mono_clock : _ Eio.Time.Mono.t.. > ->
string ->
(t -> 'a) ->
'arun env target f is a program's pool: created on a switch of its own, with the network and the monotonic clock taken from env, handed to f, and closed when f returns or raises; cancelled, it passes the cancellation on, its connections ending with the switch --
Eio_main.run @@ fun env ->
Spindle_postgres.Pool.run env target @@ fun pool ->
Spindle.serve env ~resources:[ Spindle.Dep.resource db pool ] routestarget is a connection string, a postgres:// URL or a keyword list, read once by Rowtype_postgres.Conninfo.of_string. Every option is create's. A pool that cannot be opened -- a database that refuses, a connection string that does not parse -- is an error line on spindle-postgres saying why, and the program exits with status 1, because a server that cannot reach its database has nothing to serve. A program that would rather go on without one calls create.