DbInit

io.eezo.db.DbInit
See theDbInit companion object
trait DbInit

How an application names its database: the connection settings and the per connection hook.

Split out of DbApp so that a front end which is not the application's entry point (a deploy runner, the testkit) can build the same Database from the same settings without inheriting boot. DbApp extends this, and the umbrella's EezoApp through it; users override members here and never name the trait.

Named for databaseInit, its one member that is not a string, because it is the one people get wrong; see its comment.

Two spellings of the environment, one mechanism. EEZO_DB_URL/EEZO_DB_USER/ EEZO_DB_PASS are eezo's own and always win. When they are absent and DATABASE_URL is present (the postgres://user:pass@host/db form every PaaS injects: Fly, Heroku, Render), it is parsed into the three, so a deployed application configures itself from the one secret the platform already set. This is a fallback, not a second configuration system: the members below are still the only way the settings are read.

EEZO_DB_POOL_SIZE (default 10) and EEZO_DB_ACQUIRE_TIMEOUT (milliseconds, default 5000) size the pool; DATABASE_URL has no say in either.

Attributes

Companion
object
Source
DbInit.scala
Graph
Supertypes
class Object
trait Matchable
class Any
Known subtypes
trait DbApp
trait EezoApp

Members list

Value members

Concrete methods

Short on purpose. detached borrows a second connection while the caller still holds its first, so one thread can hold two, and a full pool can deadlock on itself; the timeout is the only thing that turns that into an error. HikariCP's own 30 seconds reads as a hang to whoever is waiting on the request, and a request that cannot get a connection in 5 seconds is better answered with a 500 than left open.

Short on purpose. detached borrows a second connection while the caller still holds its first, so one thread can hold two, and a full pool can deadlock on itself; the timeout is the only thing that turns that into an error. HikariCP's own 30 seconds reads as a hang to whoever is waiting on the request, and a request that cannot get a connection in 5 seconds is better answered with a 500 than left open.

Attributes

Source
DbInit.scala
def databaseInit: Connection => Unit

Run on every connection the pool creates, not once on a borrowed one (DESIGN §8.7).

Run on every connection the pool creates, not once on a borrowed one (DESIGN §8.7).

This is where search_path, application_name and statement timeouts belong. Without it an application that works in a non-public schema silently splits in two: its own connections see one schema and eezo's see another, which shows up as a migration that appears not to have run.

Attributes

Source
DbInit.scala
def databasePassword: String

Attributes

Source
DbInit.scala
def databasePoolSize: Int

Small on purpose. HikariCP's sizing rule is connections = cores * 2 + spindles, because Postgres does its work on CPU and disk, and connections beyond what those can serve only queue inside the database instead of in the pool, where queueing is cheaper. Virtual threads make requests cheap, not connections: thousands of requests waiting briefly on a small saturated pool is the intended shape, not a sign the pool is too small.

Small on purpose. HikariCP's sizing rule is connections = cores * 2 + spindles, because Postgres does its work on CPU and disk, and connections beyond what those can serve only queue inside the database instead of in the pool, where queueing is cheaper. Virtual threads make requests cheap, not connections: thousands of requests waiting briefly on a small saturated pool is the intended shape, not a sign the pool is too small.

Attributes

Source
DbInit.scala
def databaseUrl: String

Overridable, so a test or a second environment can point elsewhere without touching boot.

Overridable, so a test or a second environment can point elsewhere without touching boot.

Attributes

Source
DbInit.scala
def databaseUser: String

Attributes

Source
DbInit.scala