io.eezo.db.engine
Members list
Type members
Classlikes
No connection came out of the pool within the acquire timeout.
No connection came out of the pool within the acquire timeout.
An environment failure (ADR 0006): the database is down, or the pool is too small for the load, and no handler can do anything about either. So it is a plain exception that the request boundary answers as a 500, rather than an SQLException that a problems hook or an attempt[SQLException] would catch and turn into something that looks recoverable.
Attributes
- Source
- ConnectionUnavailable.scala
- Supertypes
-
class RuntimeExceptionclass Exceptionclass Throwabletrait Serializableclass Objecttrait Matchableclass AnyShow all
Attributes
- Companion
- class
- Source
- Database.scala
- Supertypes
- Self type
-
Database.type
A database, and the only thing that owns a Pool.
A database, and the only thing that owns a Pool.
Users never name this type. It is built once at the layer (EezoApp in production, the testkit in tests), installed, and reached only through transact and read.
Attributes
- Companion
- object
- Source
- Database.scala
- Supertypes
Connections for one database, owned by Database and by nothing else. DESIGN §8.7.
Connections for one database, owned by Database and by nothing else. DESIGN §8.7.
A real pool, because opening a Postgres connection costs a TCP handshake, authentication and a backend process, and a request that paid that on every read would spend more time connecting than querying. The pool is HikariCP rather than one written here: a pool's bugs are stalls under load, and HikariCP's are already found.
The size is fixed, minimumIdle equal to maximumPoolSize, because a pool that shrinks when idle pays the connect cost again on the first request after a quiet spell, which is exactly the request somebody is watching. The acquire timeout is short because detached borrows a second connection while the caller's transaction still holds its first: one thread can hold two connections, so a full pool can deadlock, and a timeout is what turns that into an error instead of a hang.
The pool starts empty (initializationFailTimeout negative) so that building one never waits on the network: an application whose database is down still boots, and fails the first request that needs Postgres, after the acquire timeout, rather than failing in main. HikariCP keeps retrying in the background, so the database coming back needs no restart.
init runs on every physical connection the pool opens, not once on a borrowed one. That distinction is what makes per suite search_path isolation work: search_path is per connection, so a suite that set it on one borrowed connection would silently read the wrong schema through the next. Production wants the same hook for application_name and statement timeouts.
Attributes
- Source
- Pool.scala
- Supertypes
A second scope opened while one was already open on this thread.
A second scope opened while one was already open on this thread.
Attributes
- Source
- Scope.scala
- Supertypes
-
trait Producttrait Equalsclass IllegalStateExceptionclass RuntimeExceptionclass Exceptionclass Throwabletrait Serializableclass Objecttrait Matchableclass AnyShow all
The non-inline hops behind Scopes.transact and Scopes.read.
The non-inline hops behind Scopes.transact and Scopes.read.
This is where the capture contract lives (DESIGN §8.4): body: Tx ?-> A on a non-inline method is what makes a scope unable to escape its block. An inline entry delegating to another inline method drops that contract and every capture guarantee with it, while still compiling — so the signatures below are load-bearing, and the split is not tidiness.
These must stay public. private[eezo] compiles — Scala 3 synthesizes inline accessors — and then fails at run time with NoClassDefFoundError: io/eezo/db/engine, because the expansion baked into the caller reaches for the package as a class. Measured both ways on a clean build.
It is worth knowing how this hid twice. The expansion lives in the caller's bytecode, so changing visibility here only shows up once every caller recompiles; an incremental build keeps the old expansion and reports whatever the previous setting did. That is also why renaming this package once appeared to fix it — the rename forced the full recompile, and the name was never involved.
Attributes
Which kind of scope is open on a thread.
Which kind of scope is open on a thread.
Attributes
- Source
- Scope.scala
- Supertypes
-
trait Enumtrait Serializabletrait Producttrait Equalsclass Objecttrait Matchableclass AnyShow all