Giter Site home page Giter Site logo

gvolpe / postgresql-resilient Goto Github PK

View Code? Open in Web Editor NEW
16.0 3.0 0.0 48 KB

Automatic re-connection support for PostgreSQL.

Home Page: https://hackage.haskell.org/package/postgresql-resilient-0.1.0.0

License: Apache License 2.0

Haskell 80.84% Nix 19.16%
postgresql postgresql-database postgres haskell resilient reconnection

postgresql-resilient's Introduction

postgresql-resilient

CI Status

Automatic reconnection support for PostgreSQL, built on top of postgresql-simple.

Motivation

The postgresql-simple package gives us the two following functions (see connection management).

connect :: ConnectInfo -> IO Connection
close :: Connection -> IO ()

Once we acquire a Connection, it would work as long as there are no connectivity issues. However, if the PostgreSQL server becomes unreachable even for a second, such Connection will no longer be valid and you will need to close it and try to connect again, which could also fail if the server is still down.

So the tiny postgresql-resilient package provides a ResilientConnection from which we can always get a healthy connection. A background process will take care of checking the connection status and reconnecting when necessary. All with configurable retries and exponential back-offs as well as closing the connection once done using it (guaranteed by bracket).

Therefore, instead of using connect, you can leverage the following function.

withResilientConnection
  :: forall a
   . ResilientSettings
  -> LogHandler
  -> P.ConnectInfo
  -> (ResilientConnection IO -> IO a)
  -> IO a

Note: it only depends on exceptions and postgresql-simple, yielding a tiny footprint.

Quick Start

import           Database.PostgreSQL.Resilient
import qualified Database.PostgreSQL.Simple    as P

withResilientConnection defaultResilientSettings logHandler connectInfo $ \pool ->
  (conn :: P.Connection) <- getConnection pool
  res <- P.query_ conn "SELECT * FROM foo"
  putStrLn $ show res

logHandler :: String -> IO ()
logHandler = putStrLn

connectInfo :: P.ConnectInfo
connectInfo = P.ConnectInfo
  { P.connectHost     = "localhost"
  , P.connectPort     = 5432
  , P.connectUser     = "postgres"
  , P.connectPassword = ""
  , P.connectDatabase = "store"
  }

defaultResilientSettings :: ResilientSettings
defaultResilientSettings = ResilientSettings
  { healthCheckEvery            = 3
  , exponentialBackoffThreshold = 10
  }

E.g. using the managed library for your resources.

import           Control.Monad.Managed

mkConnection :: Managed (ResilientConnection IO)
mkConnection = managed $ withResilientConnection
  defaultResilientSettings logHandler connectInfo

main :: IO ()
main = with mkConnection $ \pool ->
  (conn :: P.Connection) <- getConnection pool
  doSomething conn

Reconnection

Here are the logs of a simple connection example where the PostgreSQL server is shutdown on purpose and it's then brought back up a few seconds later.

$ cabal new-run postgresql-resilient-demo
Up to date
Connecting to PostgreSQL

Checking PostgreSQL connection status
[Only {fromOnly = "PostgreSQL 13.0 on x86_64-pc-linux-musl, compiled by gcc (Alpine 9.3.0) 9.3.0, 64-bit"}]

Checking PostgreSQL connection status
[Only {fromOnly = "PostgreSQL 13.0 on x86_64-pc-linux-musl, compiled by gcc (Alpine 9.3.0) 9.3.0, 64-bit"}]

Checking PostgreSQL connection status
Closing no longer valid PostgreSQL connection
Connecting to PostgreSQL
libpq: failed (could not connect to server: Connection refused
	Is the server running on host "localhost" (::1) and accepting
	TCP/IP connections on port 5432?
could not connect to server: Connection refused
	Is the server running on host "localhost" (127.0.0.1) and accepting
	TCP/IP connections on port 5432?
)
 > Retrying in 1 seconds.

Connecting to PostgreSQL
libpq: failed (could not connect to server: Connection refused
	Is the server running on host "localhost" (::1) and accepting
	TCP/IP connections on port 5432?
could not connect to server: Connection refused
	Is the server running on host "localhost" (127.0.0.1) and accepting
	TCP/IP connections on port 5432?
)
 > Retrying in 2 seconds.

Connecting to PostgreSQL
libpq: failed (could not connect to server: Connection refused
	Is the server running on host "localhost" (::1) and accepting
	TCP/IP connections on port 5432?
could not connect to server: Connection refused
	Is the server running on host "localhost" (127.0.0.1) and accepting
	TCP/IP connections on port 5432?
)
 > Retrying in 4 seconds.

Connecting to PostgreSQL
Checking PostgreSQL connection status
[Only {fromOnly = "PostgreSQL 13.0 on x86_64-pc-linux-musl, compiled by gcc (Alpine 9.3.0) 9.3.0, 64-bit"}]

Checking PostgreSQL connection status
[Only {fromOnly = "PostgreSQL 13.0 on x86_64-pc-linux-musl, compiled by gcc (Alpine 9.3.0) 9.3.0, 64-bit"}]

^CClosing PostgreSQL connection
Shutdown PostgreSQL reconnection process

The health-check is performed every 3 seconds by default but it is configurable via the healthCheckEvery setting. The retries are exponential by ^2 seconds with a threshold of 10 seconds, also configurable via exponentialThreshold.

postgresql-resilient's People

Contributors

gvolpe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.