EezoApp

io.eezo.EezoApp
trait EezoApp extends HttpApp, LiveApp, DbApp

The entry point an application on the umbrella extends: both layers, one trait, one package.

object Main extends EezoApp {
 override def schema: Schema     = AppSchema
 override def routes: RouteTable = Routes.table()
}

Nothing here is new: HttpApp brings routes, the server's overrides, boot's default of serving, and the dev and routes commands; LiveApp brings the live socket and client, so Live.mount works with no configuration; DbApp brings schema, the database lifecycle, and the schema commands. boot is concrete in HttpApp and abstract in DbApp, so an application inherits "serve" regardless of which of the two supertypes below is written first, and a Main that overrides boot still wins.

What is this trait's own is the one idea both overrides spell: the http layer runs under the database. program is concrete in both layers, boot() in one and withDatabase(boot()) in the other, so the compiler refuses any trait that stacks the two until it overrides program and says which; this one says the database layer's. A user's own extends DbApp with HttpApp fails the same way, in either order, instead of booting with no Database installed. dev composes through devServer alike: the drift check before the server comes up, and the refusal page in place of the app while the drift is dangerous, all under the same Database.

Attributes

Source
EezoApp.scala
Graph
Supertypes
trait DbApp
trait DbInit
trait LiveApp
trait HttpApp
trait Dispatch
class Object
trait Matchable
class Any
Show all

Members list

Value members

Concrete methods

override protected def devServer(): Unit

What dev serves. The umbrella overrides it to run the drift check first and serve the drift page when the check blocks.

What dev serves. The umbrella overrides it to run the drift check first and serve the drift page when the check blocks.

Attributes

Definition Classes
Source
EezoApp.scala
override protected def program(): Unit

The http layer's boot under the database layer's lifecycle: the one line the compiler makes this trait write.

The http layer's boot under the database layer's lifecycle: the one line the compiler makes this trait write.

Attributes

Definition Classes
Source
EezoApp.scala

Inherited methods

protected def allowedOrigins: Set[String]

Origins other than the server's own whose pages may open a live socket, each written scheme://host or scheme://host:port. Empty by default, because the page and its socket come from the same server unless something in between rewrites the Host the browser asked for. That something is usually a proxy, and forwarding the browser's Host is the better fix; this list is for when it cannot. Matching is exact, with no wildcard, since a pattern that admits a subdomain admits whoever controls that subdomain. An entry that is not an origin fails the boot.

Origins other than the server's own whose pages may open a live socket, each written scheme://host or scheme://host:port. Empty by default, because the page and its socket come from the same server unless something in between rewrites the Host the browser asked for. That something is usually a proxy, and forwarding the browser's Host is the better fix; this list is for when it cannot. Matching is exact, with no wildcard, since a pattern that admits a subdomain admits whoever controls that subdomain. An entry that is not an origin fails the boot.

Attributes

Inherited from:
LiveApp
Source
LiveApp.scala
def boot(): Unit

The application. The default serves routes on port, which is what makes the minimal application one override and nothing else. Override it for anything more: background work, another setup, no server at all.

The application. The default serves routes on port, which is what makes the minimal application one override and nothing else. Override it for anything more: background work, another setup, no server at all.

Attributes

Inherited from:
HttpApp
Source
HttpApp.scala
override protected def commands: PartialFunction[List[String], Int]

The commands this application answers, as first argument :: rest. Nil is program and is answered here, once, so no layer owns it. Each layer writes own orElse super.commands for its own commands, so the later mixin's arms are consulted first.

The commands this application answers, as first argument :: rest. Nil is program and is answered here, once, so no layer owns it. Each layer writes own orElse super.commands for its own commands, so the later mixin's arms are consulted first.

Attributes

Definition Classes
Inherited from:
DbApp
Source
DbApp.scala

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

Inherited from:
DbInit
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

Inherited from:
DbInit
Source
DbInit.scala
def databasePassword: String

Attributes

Inherited from:
DbInit
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

Inherited from:
DbInit
Source
DbInit.scala
def databaseSchema: String

The Postgres schema the drift commands introspect. search_path is set per connection in databaseInit; this is the same name, told to the side that reads catalogs.

The Postgres schema the drift commands introspect. search_path is set per connection in databaseInit; this is the same name, told to the side that reads catalogs.

Attributes

Inherited from:
DbApp
Source
DbApp.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

Inherited from:
DbInit
Source
DbInit.scala
def databaseUser: String

Attributes

Inherited from:
DbInit
Source
DbInit.scala
override protected def frameworkRoutes: Seq[Route]

Routes the framework itself contributes, appended to whatever table serve is given so that every caller — boot's default, a user's own serve in an overridden boot, dev — serves them without knowing they exist. Empty here: eezo-live's LiveApp overrides it with the live socket and its client script, and EezoApp mixes that in. Appended, so the user's table keeps winning any path both name; they show in the boot listing (they are served, and the listing does not lie) but not in eezo routes, which is the user's table.

Routes the framework itself contributes, appended to whatever table serve is given so that every caller — boot's default, a user's own serve in an overridden boot, dev — serves them without knowing they exist. Empty here: eezo-live's LiveApp overrides it with the live socket and its client script, and EezoApp mixes that in. Appended, so the user's table keeps winning any path both name; they show in the boot listing (they are served, and the listing does not lie) but not in eezo routes, which is the user's table.

Attributes

Definition Classes
Inherited from:
LiveApp
Source
LiveApp.scala
def layout: Layout

The frame every HTML reply comes back in, the derived pages, the login page and the error page included. eezo's plain one unless the application names its own here, which is the one place a frame can be chosen, so that no route has to remember to ask for it.

The frame every HTML reply comes back in, the derived pages, the login page and the error page included. eezo's plain one unless the application names its own here, which is the one place a frame can be chosen, so that no route has to remember to ask for it.

Attributes

Inherited from:
HttpApp
Source
HttpApp.scala
final def main(args: Array[String]): Unit

Attributes

Inherited from:
Dispatch
Source
Dispatch.scala
def maxBodySize: Long

The request body cap, and the WebSocket text message cap with it.

The request body cap, and the WebSocket text message cap with it.

Attributes

Inherited from:
HttpApp
Source
HttpApp.scala
override protected def notes: List[String]

What help says after the command table and before its footer: the caveats that belong to no single row. Each layer writes own ++ super.notes, and they are kept apart from usage so a stacked application prints one table and then every layer's notes, rather than one layer's notes in the middle of the other's commands.

What help says after the command table and before its footer: the caveats that belong to no single row. Each layer writes own ++ super.notes, and they are kept apart from usage so a stacked application prints one table and then every layer's notes, rather than one layer's notes in the middle of the other's commands.

Attributes

Definition Classes
Inherited from:
DbApp
Source
DbApp.scala
def port: Int

Where boot's default and the dev command serve.

Where boot's default and the dev command serve.

Attributes

Inherited from:
HttpApp
Source
HttpApp.scala
def problems: PartialFunction[Throwable, Problem]

How the application's own failures are answered: a partial function from what a handler threw to the problem the client sees. What it does not cover, the boundary answers as 500.

How the application's own failures are answered: a partial function from what a handler threw to the problem the client sees. What it does not cover, the boundary answers as 500.

Attributes

Inherited from:
HttpApp
Source
HttpApp.scala
def secret: Secret

The key the session cookie is signed with. EEZO_SECRET by default. The sbt plugin's dev loop sets it to one secret per sbt session, so a restart on edit keeps the developer signed in. A run outside that loop with nothing set gets a throwaway announced at WARNING, so that hello runs with no configuration and a deployment that forgot is told. Read once, when serve boots.

The key the session cookie is signed with. EEZO_SECRET by default. The sbt plugin's dev loop sets it to one secret per sbt session, so a restart on edit keeps the developer signed in. A run outside that loop with nothing set gets a throwaway announced at WARNING, so that hello runs with no configuration and a deployment that forgot is told. Read once, when serve boots.

Attributes

Inherited from:
HttpApp
Source
HttpApp.scala
final protected def serve(table: RouteTable, dev: Boolean = ...): Unit

The only caller of HttpServer.run: boots the server on this trait's overrides and blocks until it stops. dev turns the listing and the reload client on.

The only caller of HttpServer.run: boots the server on this trait's overrides and blocks until it stops. dev turns the listing and the reload client on.

Attributes

Inherited from:
HttpApp
Source
HttpApp.scala
override protected def usage: List[Usage]

One row per command, for help. Each layer writes own ++ super.usage, and names only the spelling and the description: the columns are help's to lay out, once, over every layer's rows together, so no layer has to guess how wide the others' spellings are.

One row per command, for help. Each layer writes own ++ super.usage, and names only the spelling and the description: the columns are help's to lay out, once, over every layer's rows together, so no layer has to guess how wide the others' spellings are.

Attributes

Definition Classes
Inherited from:
DbApp
Source
DbApp.scala
final protected def withDatabase[A](f: => A): A

The lifecycle, scoped to one command: built, installed, closed. Final, and protected rather than private so the umbrella can wrap the dev server in it.

The lifecycle, scoped to one command: built, installed, closed. Final, and protected rather than private so the umbrella can wrap the dev server in it.

Attributes

Inherited from:
DbApp
Source
DbApp.scala

Inherited and Abstract methods

The route table, usually Routes.table() from the sbt plugin's generated object. Abstract: an http layer is its routes, and an application without any is a mistake.

The route table, usually Routes.table() from the sbt plugin's generated object. Abstract: an http layer is its routes, and an application without any is a mistake.

Attributes

Inherited from:
HttpApp
Source
HttpApp.scala
def schema: Schema

The application's schema, object AppSchema extends Schema named here. Abstract: a database layer is its schema, and an application without one is a mistake.

The application's schema, object AppSchema extends Schema named here. Abstract: a database layer is its schema, and an application without one is a mistake.

Attributes

Inherited from:
DbApp
Source
DbApp.scala