A Sequel extension that retires pooled connections once they pass a maximum age.
See the motivation for why it exists.
DB = Sequel.connect(url, connection_max_lifetime: 90)
DB.extension :pg_reaper-
connection_max_lifetimeis in seconds and defaults to 120 -
The age is checked as a connection is checked out of the pool, so the cost is one hash lookup
-
A connection that is too old is disconnected and replaced before your code sees it
-
A connection already checked out, such as inside a transaction, is never reaped
-
Idle connections are not closed in the background, see Idle connections
-
Single and sharded single pools are not supported
The lifetime can also be changed at runtime with DB.pool.connection_max_lifetime = 60.
Nothing in this extension, or in Sequel’s connection_validator, closes an idle socket in the background.
Both act when a connection is checked out:
-
pg_reaperreplaces any connection older thanconnection_max_lifetime, however long it sat idle -
connection_validatorruns a query on connections idle longer thanconnection_validation_timeoutand replaces the ones that fail
For a pgdog rollout pg_reaper is enough, if two conditions hold that this extension does not enforce:
-
The pod’s shutdown grace is longer than
connection_max_lifetime, as with pgdog’s 180s against the default 120s -
New connections stop reaching a pod once it is terminating
Connection age does not tell you a connection is alive. If the grace is shorter than the lifetime, a connection opened just before SIGTERM is still young when the pod dies, and it is handed out dead.
Load connection_validator as well to cover connections that die for other reasons, such as a pgdog crash
or a network failure:
DB = Sequel.connect(url, connection_max_lifetime: 120)
DB.extension :connection_validator, :pg_reaper
DB.pool.connection_validation_timeout = 30-
connection_validation_timeoutis an idle threshold, not a detection deadline, so the 30 above is not a promise that a dead connection is found within 30s -
Only a connection idle longer than the threshold is validated at checkout, and an unused dead connection is not found until something checks it out
-
Set it to
-1to validate on every checkout, which costs a query each time -
Load order does not matter
A connection checked out for longer than the time left before the pod terminates is not interrupted, keep transactions short
mise install
bundle exec rakeTests use Sequel.mock, so no database is needed.
Commits and PR titles must follow Conventional Commits to be included in the changelog and release notes.
The hooks in .githooks enforce it, and mise run setup enables them.
Releases are cut by release-please and published to rubygems.org.