tmp-postgres-1.9.0.2: Start and stop a temporary postgres

Safe HaskellNone
LanguageHaskell2010

Database.Postgres.Temp

Contents

Description

This module provides functions for creating a temporary postgres instance. By default it will create a temporary data directory and a temporary directory for a UNIX domain socket for postgres to listen on.

Here is an example using the expection safe with function:

with $ \db -> bracket
   (connectPostgreSQL (toConnectionString db))
   close $
   \conn -> execute_ conn "CREATE TABLE foo (id int)"

To extend or override the defaults use withConfig (or startConfig).

tmp-postgres ultimately calls (optionally) initdb, postgres and (optionally) createdb.

All of the command line, environment variables and configuration files that are generated by default for the respective executables can be extended.

In general tmp-postgres is useful if you want a clean temporary postgres and do not want to worry about clashing with an existing postgres instance (or needing to ensure postgres is already running).

Here are some different use cases for tmp-postgres and their respective configurations:

  • The default with and start functions can be used to make a sandboxed temporary database for testing.
  • By disabling initdb one could run a temporary isolated postgres on a base backup to test a migration.
  • By using the stopPostgres and withRestart functions one can test backup strategies.

WARNING!! Ubuntu's PostgreSQL installation does not put initdb on the PATH. We need to add it manually. The necessary binaries are in the /usr/lib/postgresql/VERSION/bin/ directory, and should be added to the PATH

echo "export PATH=$PATH:/usr/lib/postgresql/VERSION/bin/" >> /home/ubuntu/.bashrc
Synopsis

Exception safe interface

with Source #

Arguments

:: (DB -> IO a)

action continuation.

-> IO (Either StartError a) 

Default expectation safe interface. Equivalent to

  with = withConfig defaultConfig

withConfig Source #

Arguments

:: Config

extra. Config combined with the generated Config. See startConfig for more info

-> (DB -> IO a)

action continuation

-> IO (Either StartError a) 

Exception safe database create with options. See startConfig for more details. Calls stop even in the face of exceptions.

withRestart :: DB -> (DB -> IO a) -> IO (Either StartError a) Source #

Exception safe version of restart

Separate start and stop interface.

start :: IO (Either StartError DB) Source #

Default start behavior. Equivalent to calling startConfig with the defaultConfig

startConfig Source #

Arguments

:: Config

extra configuration that is mappended last to the generated Config. generated <> extra

-> IO (Either StartError DB) 

Create zero or more temporary resources and use them to make a Config.

The passed in config is inspected and a generated config is created. The final config is built by

  generated <> extra

Returns a DB that requires cleanup. startConfig should be used with a bracket and stop, e.g.

  withConfig :: Config -> (DB -> IO a) -> IO (Either StartError a)
  withConfig plan f = bracket (startConfig plan) (either mempty stop) $
     either (pure . Left) (fmap Right . f)

or just use withConfig. If you are calling startConfig you probably want withConfig anyway.

Based on the value of socketClass a "postgresql.conf" is created with

  listen_addresses = 'IP_ADDRESS'

if it is IpSocket. If is UnixSocket then the lines

  listen_addresses = ''
  unix_socket_directories = 'SOCKET_DIRECTORY'

are added.

stop :: DB -> IO () Source #

Stop the postgres process and cleanup any temporary resources that might have been created.

restart :: DB -> IO (Either StartError DB) Source #

Restart the postgres from DB using the prior Plan

stopPostgres :: DB -> IO ExitCode Source #

Only stop the postgres process but leave any temporary resources. Useful for testing backup strategies when used in conjunction with restart or withRestart.

Main resource handle

data DB Source #

Handle for holding temporary resources, the postgres process handle and postgres connection information. The DB also includes the final plan used to start initdb, createdb and postgres. See toConnectionString or toConnectionOptions for converting a DB to postgresql connection string.

Instances
Pretty DB Source # 
Instance details

Defined in Database.Postgres.Temp.Internal

Methods

pretty :: DB -> Doc #

prettyList :: [DB] -> Doc #

DB accessors

toConnectionString :: DB -> ByteString Source #

Convert a DB to a connection string. Alternatively one can access the Options using toConnectionOptions

toConnectionOptions :: DB -> Options Source #

Convert a DB to a connection Options type.

toDataDirectory :: DB -> FilePath Source #

Access the data directory. This was either generated or specified explicitly when creating the Config

toTemporaryDirectory :: DB -> FilePath Source #

Get the directory that is used to create other temporary directories

DB mutators

makeDataDirPermanent :: DB -> DB Source #

Make the data directory permanent. Useful for debugging. If you are using with or withConfig this function will not modify the DB that is passed for cleanup. You will need to setup your own bracket like

   bracket (fmap makeDataDirPermanent start) (either mempty stop)

reloadConfig :: DB -> IO () Source #

Reload the configuration file without shutting down. Calls pg_reload_conf().

DB debugging

prettyPrintDB :: DB -> String Source #

Display a DB

Configuration

Defaults

defaultConfig :: Config Source #

The default configuration. This will create a database called "postgres" via initdb (it's default behavior). It will create a temporary directory for the data and a temporary directory for a unix socket on a random port. Additionally it will use the following "postgresql.conf" which is optimized for performance.

   shared_buffers = 12MB
   fsync = off
   synchronous_commit = off
   full_page_writes = off
   log_min_duration_statement = 0
   log_connections = on
   log_disconnections = on
   client_min_messages = ERROR

defaultConfig also passes the --no-sync flag to initdb.

If you would like to customize this behavior you can start with the defaultConfig and overwrite fields or combine a defaultConfig with another Config using <> (mappend).

Alternatively you can eschew defaultConfig altogether, however your postgres might start and run faster if you use defaultConfig.

defaultConfig also sets the initDbConfig to pure standardProcessConfig and postgresConfig to standardProcessConfig.

To append additional lines to "postgresql.conf" file create a custom Config like the following.

 custom = defaultConfig <> mempty
   { plan = mempty
     { postgresConfigFile =
         [ "wal_level = replica"
         , "archive_mode = on"
         , "max_wal_senders = 2"
         , "fsync = on"
         , "synchronous_commit = on"
         ]
     }
   }

Or using the provided lenses and your favorite lens library

 custom = defaultConfig & planL . postgresConfigFile <>~
   [ "wal_level = replica"
   , "archive_mode = on"
   , "max_wal_senders = 2"
   , "fsync = on"
   , "synchronous_commit = on"
   ]

This is common enough there is defaultPostgresConf which is a helper to do this.

As an alternative to using defaultConfig one could create a config from connections parameters using optionsToDefaultConfig

defaultPostgresConf :: [String] -> Config Source #

mappend the defaultConfig with a Config that provides additional "postgresql.conf" lines. Equivalent to

defaultPostgresConf extra = defaultConfig <> mempty
  { plan = mempty
    { postgresConfigFile = extra
    }
  }

or with lenses

defaultPostgresConf extra = defaultConfig & planL . postgresConfigFile <>~ extra

standardProcessConfig :: ProcessConfig Source #

The standardProcessConfig sets the handles to stdin, stdout and stderr and inherits the environment variables from the calling process.

Custom Config builder helpers

optionsToDefaultConfig :: Options -> Config Source #

Attempt to create a Config from a Options. Useful if you want to create a database owned by a specific user you will also login with among other use cases.

Config

data Config Source #

The high level options for overriding default behavior.

Constructors

Config 

Fields

Instances
Generic Config Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Associated Types

type Rep Config :: Type -> Type #

Methods

from :: Config -> Rep Config x #

to :: Rep Config x -> Config #

Semigroup Config Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Monoid Config Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Pretty Config Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Methods

pretty :: Config -> Doc #

prettyList :: [Config] -> Doc #

type Rep Config Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Config Lenses

Plan

data Plan Source #

Describe how to run initdb, createdb and postgres

Instances
Generic Plan Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Associated Types

type Rep Plan :: Type -> Type #

Methods

from :: Plan -> Rep Plan x #

to :: Rep Plan x -> Plan #

Semigroup Plan Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Methods

(<>) :: Plan -> Plan -> Plan #

sconcat :: NonEmpty Plan -> Plan #

stimes :: Integral b => b -> Plan -> Plan #

Monoid Plan Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Methods

mempty :: Plan #

mappend :: Plan -> Plan -> Plan #

mconcat :: [Plan] -> Plan #

Pretty Plan Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Methods

pretty :: Plan -> Doc #

prettyList :: [Plan] -> Doc #

type Rep Plan Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Plan lenses

PostgresPlan

data PostgresPlan Source #

postgres process config and corresponding client connection Options.

Constructors

PostgresPlan 

Fields

PostgresPlan lenses

ProcessConfig

data ProcessConfig Source #

Process configuration

Constructors

ProcessConfig 

Fields

Instances
Eq ProcessConfig Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Show ProcessConfig Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Generic ProcessConfig Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Associated Types

type Rep ProcessConfig :: Type -> Type #

Semigroup ProcessConfig Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Monoid ProcessConfig Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Pretty ProcessConfig Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

type Rep ProcessConfig Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

ProcessConfig Lenses

EnvironmentVariables

data EnvironmentVariables Source #

The environment variables can be declared to inherit from the running process or they can be specifically added.

Instances
Eq EnvironmentVariables Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Show EnvironmentVariables Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Generic EnvironmentVariables Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Associated Types

type Rep EnvironmentVariables :: Type -> Type #

Semigroup EnvironmentVariables Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Monoid EnvironmentVariables Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Pretty EnvironmentVariables Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

type Rep EnvironmentVariables Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

type Rep EnvironmentVariables = D1 (MetaData "EnvironmentVariables" "Database.Postgres.Temp.Internal.Config" "tmp-postgres-1.9.0.2-FLIHg8XKN1U6yEkdooj617" False) (C1 (MetaCons "EnvironmentVariables" PrefixI True) (S1 (MetaSel (Just "inherit") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 (Last Bool)) :*: S1 (MetaSel (Just "specific") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 (Map String String))))

EnvironmentVariables Lenses

CommandLineArgs

data CommandLineArgs Source #

A type to help combine command line Args.

Constructors

CommandLineArgs 

Fields

  • keyBased :: Map String (Maybe String)

    Args of the form -h foo, --host=foo and --switch. The key is mappended with value so the key should include the space or equals (as shown in the first two examples respectively). The Dual monoid is used so the last key wins.

  • indexBased :: Map Int String

    Args that appear at the end of the key based Args. The Dual monoid is used so the last key wins.

Instances
Eq CommandLineArgs Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Show CommandLineArgs Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Generic CommandLineArgs Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Associated Types

type Rep CommandLineArgs :: Type -> Type #

Semigroup CommandLineArgs Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Monoid CommandLineArgs Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Pretty CommandLineArgs Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

type Rep CommandLineArgs Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

type Rep CommandLineArgs = D1 (MetaData "CommandLineArgs" "Database.Postgres.Temp.Internal.Config" "tmp-postgres-1.9.0.2-FLIHg8XKN1U6yEkdooj617" False) (C1 (MetaCons "CommandLineArgs" PrefixI True) (S1 (MetaSel (Just "keyBased") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 (Map String (Maybe String))) :*: S1 (MetaSel (Just "indexBased") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 (Map Int String))))

CommandLineArgs Lenses

DirectoryType

data DirectoryType Source #

Used to specify a Temporary folder that is automatically cleaned up or a Permanent folder which is not automatically cleaned up.

Constructors

Permanent FilePath

A permanent file that should not be generated.

Temporary

A temporary file that needs to generated.

Instances
Eq DirectoryType Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Ord DirectoryType Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Show DirectoryType Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Semigroup DirectoryType Source #

Takes the last Permanent value.

Instance details

Defined in Database.Postgres.Temp.Internal.Config

Monoid DirectoryType Source #

Temporary as mempty

Instance details

Defined in Database.Postgres.Temp.Internal.Config

Pretty DirectoryType Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

SocketClass

data SocketClass Source #

The monoidial version of CompleteSocketClass. Used to combine overrides with defaults when creating a CompleteSocketClass. The monoid instance and combines the

Constructors

IpSocket (Last String)

The monoid for combining IP address configuration

UnixSocket DirectoryType

The monoid for combining UNIX socket configuration

Instances
Eq SocketClass Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Ord SocketClass Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Show SocketClass Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Generic SocketClass Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

Associated Types

type Rep SocketClass :: Type -> Type #

Semigroup SocketClass Source #

Last IpSocket wins. UnixSocket DirectoryType as mappended together.

Instance details

Defined in Database.Postgres.Temp.Internal.Config

Monoid SocketClass Source #

Treats 'UnixSocket mempty' as mempty

Instance details

Defined in Database.Postgres.Temp.Internal.Config

Pretty SocketClass Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

type Rep SocketClass Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Config

type Rep SocketClass = D1 (MetaData "SocketClass" "Database.Postgres.Temp.Internal.Config" "tmp-postgres-1.9.0.2-FLIHg8XKN1U6yEkdooj617" False) (C1 (MetaCons "IpSocket" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 (Last String))) :+: C1 (MetaCons "UnixSocket" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 DirectoryType)))

Logger

type Logger = Event -> IO () Source #

A way to log internal Events

Internal events passed to the logger .

data Event Source #

Internal events for debugging

Constructors

StartPlan String

The first event. This useful for debugging what is actual passed to the initdb, createdb and postgres.

StartPostgres

The second event. Postgres is about to get called

WaitForDB

The third event. Postgres started. We are now about to setup a reconnect loop (racing with a process checker)

TryToConnect

The fourth event and (possibly all subsequent events). We are looping trying to successfully connect to the postgres process.

Instances
Eq Event Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Core

Methods

(==) :: Event -> Event -> Bool #

(/=) :: Event -> Event -> Bool #

Ord Event Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Core

Methods

compare :: Event -> Event -> Ordering #

(<) :: Event -> Event -> Bool #

(<=) :: Event -> Event -> Bool #

(>) :: Event -> Event -> Bool #

(>=) :: Event -> Event -> Bool #

max :: Event -> Event -> Event #

min :: Event -> Event -> Event #

Show Event Source # 
Instance details

Defined in Database.Postgres.Temp.Internal.Core

Methods

showsPrec :: Int -> Event -> ShowS #

show :: Event -> String #

showList :: [Event] -> ShowS #

Errors

data StartError Source #

A list of failures that can occur when starting. This is not and exhaustive list but covers the errors that the system catches for the user.

Constructors

StartPostgresFailed ExitCode

postgres failed before a connection succeeded. Most likely this is due to invalid configuration

InitDbFailed ExitCode

initdb failed. This can be from invalid configuration or using a non-empty data directory

CreateDbFailed ExitCode

createdb failed. This can be from invalid configuration or the database might already exist.

CompletePlanFailed String [String]

The Plan was missing info and a complete CompletePlan could not be created.