Repository navigation
Releases: hyphatech/postgres-eio
Release list
0.5.0
- Breaking: the words are the stack's own.
connect's,Listener.connect's andPool.create's~clockis~mono_clock,Listener.connect's?heartbeatis?keep_alive, andreset, which reconnects, isrevive;Pool.create's?reset, which cleans a session, keeps its name. - Breaking:
Postgres_eio.erroris a polymorphic variant, asPool.use's errors already were, and every function that fails answers[> error], so a connection's failures and a pool's join in one result.Timeout,IoandProtocolare one tag,`Lost: the statement was sent and no answer came back, so it may have run.Closedis`Connection `Closedand now means the statement was never sent: an answer acloseor a failure leaves unread is`Lost. A connection that cannot be made, byconnect,revive,Listener.connectorPool.create, answers`Unsentfor what wasTimeout,IoorProtocol, since nothing was done.ServerandRefusedare`Serverand`Refused.Pool.error_to_stringprints a connection's errors as well as the pool's. - A SCRAM sign-in whose server asks for more than a million iterations is refused before the first. The count was unbounded, and computing it never yields, so a server asking for a hundred million held the connect, its timeout and every fiber on its domain for over a minute.
- A
Pool.createcancelled partway closes the connections it had made. They were left open, sessions held at the server, until their switch ended. connect_timeoutbounds a host's name lookup. eio_posix looks a name up in a system thread no cancellation reaches, so a slow resolver heldconnectfor as long as it took; the lookup now runs beside the wait, on the connection's switch, and is left to finish there. APostgres_eio.Resolver, whichconnectandListener.connecttake as?resolver, does lookups on its own fiber for a connection revived on any domain, since Eio forks onto a switch only from its own; a pool keeps one for its connections, so a borrower's revive is bounded on every domain.- Breaking: every connection, a
Listener's too, sets the settings the decoders read text by --client_encoding=UTF8,DateStyle=ISO,IntervalStyle=postgresandextra_float_digits=3-- over a database's and a role's defaults. Nothing setclient_encoding, so in aLATIN1database UTF-8 text was stored as mojibake, and withextra_float_digits=0a float read back rounded. A parameter or anoptionssetting giving one of them another value is`Refused;client_encodingis compared by encoding, soUTF-8orUnicodeisUTF8. - Breaking: with no
sslmode, a host on another machine needs TLS, and only a host on this one --localhost, 127.0.0.0/8,::1or a Unix socket, judged byhostaddrwhen given -- isprefer. Every host wasprefer, so a server that declined TLS, or a network that stripped it, had the password and every query sent in the clear. A server that offers no TLS is refused with an error namingsslmode=disableandprefer.sslnegotiation=directwith nosslmodeneeds TLS of every host.Conninfo.t'sssl_modeis an option,Nonewhen the string gives none, and eachConninfo.endpointhas thessl_modeit is reached with. - Breaking:
sslrootcertis refused unlesssslmodeisverify-fullorverify-ca, the only modes that read it: with any other, or none, the file was silently ignored and no certificate checked. Writesslmode=verify-full, orverify-ca, to check against it.
0.4.0
- Breaking:
Conninfo.t,Conninfo.endpointandConninfo.auth_methodsare private records. Their fields are read as before, and one is made byConninfo.of_string, so a key the driver comes to read is not a breaking change.{ c with database = name }isConninfo.with_database c name,{ c with connect_timeout = Some span }isConninfo.with_connect_timeout c span, and any other key is set in the connection string. - Breaking:
Postgres_eio.ProtocolandPostgres_eio.Authare no longer exported, so a message the protocol gains is not a breaking change.statusreturnsPostgres_eio.transaction_status: matchPostgres_eio.Idle, notPostgres_eio.Protocol.Idle.Column.formatis a type of its own, with the same constructors.
0.3.0
-
Breaking: every duration is an
Mtime.Span.tnamed for what it bounds, not a float of seconds named for its unit, so a wait in the wrong unit no longer compiles.connect's andListener.connect's?timeout_sis?timeout,Listener.connect's?heartbeat_sis?heartbeat,Pool.create's?timeout_s,?wait_s,?max_lifetime_sand?idle_check_sare?timeout,?wait,?max_lifetimeand?idle_check, andPool.use's?wait_sis?wait: write~timeout:Mtime.Span.(10 * s). -
Breaking:
timeout_sistimeout, andset_timeouttakes~timeout:Mtime.Span.t option. -
Breaking: the
Conninfo.tfieldconnect_timeout_s : float optionisconnect_timeout : Mtime.Span.t option. The connection string still gives it in whole seconds, as libpq reads it, andto_urlwrites it in whole seconds, rounded up. Only a zero span now falls back to the connection's timeout, since a span is never negative. -
Breaking:
abandonandresumeare gone. The pool has stopped a cancelled borrower through Eio cancellation since 0.2.0, and nothing else called them. To stop a statement, cancel the fiber running it: the statement is cancelled at the server and the connection closed.
0.2.0
- Breaking: OCaml 5.5 or later is required. The opam files asked for 5.4, which CI tested and nothing else did; every switch the code is written in is 5.5.
- A row function that raises while
Pool.usedrains its unread answers no longer takes the connection out of the pool for good: the connection goes back, is made again at the next lend, and the exception reaches the caller as raised, not wrapped inFun.Finally_raised. - Breaking: an Eio cancellation stops a
Pool.useborrower at once, wherever it waits.fwas shielded until it returned, so a cancelled borrower waited for work nobody wanted, or forever on something the cancellation had stopped. Its statement is still cancelled at the server; its connection is now closed and made again at the next lend. - A
Timeout, or an Eio cancellation of a statement under way, cancels the statement at the server as it closes the connection. Before, only a pool's cancelled borrower did; elsewhere the server ran the statement to its end with nobody to read it. The request has 5 s, or the timeout if that is shorter, and a pool's cancelled borrower's has the pool's timeout: with the timeout lifted, a server that never closed the request's connection held the caller forever. Listener.nextreturns a notification that arrived in the same read as the end of the listener's own answer (aLISTEN, or the heartbeat's empty query) at once. It waited for the next heartbeat, ten seconds by default, though the notification was already read.- Cancelling
Listener.nextwhile it waits keeps the connection. It closed it, so a loop racingnextagainst a tick reconnected at every tick and lost what was sent meanwhile. Only the read after the socket is readable is shielded, and what it reads is kept for the next call. - A loop racing
Listener.nextagainst a tick shorter thanheartbeat_ssends its heartbeats, and notices a dead server within heartbeat + timeout. Eachnextcounted the heartbeat from its own start, so such a loop never sent one. The heartbeat now counts from the last time the listener heard the server, and one under way whennextis cancelled is finished, within the timeout, rather than closing the connection. - Breaking: a
Listenerwhose server is restarting waits for it: an error of class 57P while it reconnects (57P03, the server starting up) is retried with backoff, as a lost connection is, and no longer returned bynext. It ended the loop with the error, though the server would take the sign-in a moment later. Any other server refusal is still returned. Pool.error_to_stringprints aPool.error, whatPool.useanswers, aserror_to_stringprints a connection's error.- Connecting keeps a random generator the application set as mirage-crypto's default, and sets one only where none is. Every connection replaced it with
Mirage_crypto_rng_unix.use_default (). - A connection's read buffer goes back to 4 KiB once it is empty after a message over 128 KiB. It kept the size of the largest message it had read, so one large row held that memory for a pooled connection's life.
- A keyword connection string whose password holds an unquoted space no longer quotes the part after the space in its error, which was part of the password. A word after
password=is never quoted; the error says to quote the password,password='a b'. - Breaking:
Pool.erroris[ `Pool of [ `Busy | `Closed ] ], the pool's states under the pool, so an error merged with others says which resource refused.Pool.useanswers`Pool `Busywhere it answered`Busy, and`Pool `Closedon a closed pool, at once, as it does to a borrow waiting when the pool closes. A closed pool waited outwait_s, logged that no connection came free, and returned`Busy, though none ever would. - The cancel request of
abandonhas 5 s, or the timeout if that is shorter, as a timeout's does. It had the connection's timeout alone, so with the timeout lifted, as a migration lifts it, a server that never closed the request's connection held the lender forever. - A row or chunk function that raises cancels its statement at the server as the connection closes, as a timeout does, and its exception still propagates as raised. The connection closed alone, and the server ran the statement to its end with nobody to read it.
- Breaking:
Conninfo.protocol_minoris no longer exported. It was a step of the start-up, the minor version a StartupMessage carries, and nothing outside the driver used it. - A
connect_timeout_sof zero or less falls back to the connection'stimeout_s, asConninfodocuments. AConninfo.tbuilt by hand withSome 0.timed out every attempt at once; a parsed connection string never carried one.
0.1.0
First release.
- Protocol 3.0 and 3.2 over TCP, Unix sockets and TLS, with multi-host failover, load balancing and
target_session_attrs. - Sign-in by SCRAM-SHA-256 with channel binding, MD5, client certificates, trust, and a cleartext password inside TLS only, held to
require_auth. - libpq's connection strings, both forms, with the
PG*variables and.pgpasson request. - Statements cached, pipelined and batched in one round trip, with text or binary results.
- Cells read as OCaml values, text or binary alike: dates and instants as
Ptimevalues, uuids asUuidm.t, intervals as their months, days and microseconds, and the whole of anint8as anint64. - COPY in and out, streamed.
- LISTEN/NOTIFY with heartbeats and reconnection.
- A timeout on every wait for the server, and a running statement cancelled at the server.
- A connection pool that lends every connection in a clean state, shared by borrowers on every domain.
- Every failure a value: a
resultwith a variant error, never an exception.