gizdb:pg/cluster
gizdb cluster: many databases behind one port. Each database is a directory under the root, served by a gizdb process of its own that starts at its first connection and stops once it has had none for --idle: an idle database costs no memory, and one database's process cannot reach another's files. The router reads a client's startup message for the database it names and relays the connection to that database's process, which authenticates it as it would alone. On connections to the cluster's own database, postgres, the router answers CREATE, DROP and ALTER DATABASE and SELECT datname FROM pg_database itself, once that process has accepted the client; every other statement goes on to the process.
Each database's limits live in <root>/<name>.conf (key=value lines, written by CREATE and ALTER DATABASE) and reach its process as flags when it next starts: connection_limit (--max-connections), statement_timeout (--statement-timeout), quota (--quota), memory (GIZLANG_MEMORY_LIMIT); and the host settings, which only the host sets (hostSetting): the server paths archive (--archive) and backups (--backups), and password, the database's own login (else the cluster's). The cluster password then reaches only the cluster's own database. A process gets its listener from the router (--port handed) and the cluster password in its environment, and exits when the router's end of its stdin closes.
import * as Cluster from "gizdb:pg/cluster";Types
ClusterOptions
type ClusterOptions = { host: string; port: i64; root: string; program: string; password: string; idleMs: i64; socket: string; tlsCert: string; tlsKey: string; }host "" leaves TCP off; socket: a directory where the cluster also listens at
.s.PGSQL.<port>, as gizdb --socket. program: the gizdb binary each database's process runs. idleMs: how long a process
without connections lives. password: every process's own password (its superuser's).
host:stringport:i64root:stringprogram:stringpassword:stringidleMs:i64socket:stringtlsCert:string— PEM files (the chain and its key): the router ends TLS itself and refuses a client in the clear. They are read again each hour, so a renewed certificate serves within that.tlsKey:string
Functions
serveClusterUntilStopped
function serveClusterUntilStopped(sys: System, options: ClusterOptions, bound: Task.Cell<i64>): Result<i64, string>serveCluster that also ends on TERM or INT, as gizdb cluster runs.
Effects: fail, read, write, console, io.
serveCluster
function serveCluster(sys: System, options: ClusterOptions, bound: Task.Cell<i64>): Result<i64, string>Runs the cluster until its listener fails; bound gets the port (-1 when startup failed).
Effects: fail, read, write, console, io.
bytesOf
function bytesOf(v: string): Option<i64>512, 64K, 10G: a number of bytes.
Effects: fail.
hostSetting
function hostSetting(sys: System, root: string, name: string, key: string, value: string): Result<bool, string>Sets KEY (one of HOST_SETTINGS: a server path, or the password of the database's process) of database NAME under the cluster root ROOT to VALUE, for the next start of its process. It is the host's way, through the folder; false when it was already so.
Effects: fail, read, write, console, io.
databasePassword
function databasePassword(sys: System, root: string, name: string): Result<string, string>The password of database NAME under the cluster root ROOT (its host setting), made the first time: the login that reaches that database alone.
Effects: fail, read, write, console, io.