diff --git a/CHANGELOG.md b/CHANGELOG.md
index 40d968830..0ab1cb272 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## Unreleased
+### Added
+
+- Reload database schema on SIGHUP - @begriffs
+
### Fixed
- Prevent role from being changed twice - @begriffs
diff --git a/docs/api/reading.md b/docs/api/reading.md
index 22cce4b3e..87f99c293 100644
--- a/docs/api/reading.md
+++ b/docs/api/reading.md
@@ -328,14 +328,14 @@ OPTIONS /my_view
This will include the row names, their types, primary key
information, and foreign keys for the given table or view.
-
-
Deprecation Warning
+
+
Schema Changes
-
Although we currently use the OPTIONS verb for this, some
- people argue that
- this is inappropriate. We are considering a describedby
- header link instead.
+
Note that when the schema of your database changes PostgREST will not reflect
+ the change. You have to either restart PostgREST or send its running process
+ a HUP signal:
+
+
killall -HUP postgrest
### CORS
diff --git a/postgrest.cabal b/postgrest.cabal
index 0b32e0326..9df7351bc 100644
--- a/postgrest.cabal
+++ b/postgrest.cabal
@@ -52,6 +52,7 @@ executable postgrest
, string-conversions
, text
, time
+ , transformers
, unordered-containers
, vector
, wai >= 3.0.1
diff --git a/src/PostgREST/App.hs b/src/PostgREST/App.hs
index be620e865..2a7d74cba 100644
--- a/src/PostgREST/App.hs
+++ b/src/PostgREST/App.hs
@@ -8,6 +8,7 @@ module PostgREST.App (
import Control.Applicative
import Data.Bifunctor (first)
+import Data.IORef (IORef, readIORef)
import Data.List (find, delete)
import Data.Maybe (isJust, fromMaybe, fromJust, mapMaybe)
import Data.Ranged.Ranges (emptyRange)
@@ -59,13 +60,14 @@ import PostgREST.Types
import Prelude
-postgrest :: AppConfig -> DbStructure -> P.Pool -> Application
-postgrest conf dbStructure pool =
+postgrest :: AppConfig -> IORef DbStructure -> P.Pool -> Application
+postgrest conf refDbStructure pool =
let middle = (if configQuiet conf then id else logStdout) . defaultMiddle in
middle $ \ req respond -> do
time <- getPOSIXTime
body <- strictRequestBody req
+ dbStructure <- readIORef refDbStructure
let schema = cs $ configSchema conf
apiRequest = userApiRequest schema req body
diff --git a/src/PostgREST/Main.hs b/src/PostgREST/Main.hs
index 68d3a12c1..b26dbab50 100644
--- a/src/PostgREST/Main.hs
+++ b/src/PostgREST/Main.hs
@@ -11,6 +11,7 @@ import PostgREST.Config (AppConfig (..),
import PostgREST.DbStructure
import Control.Monad
+import Control.Monad.IO.Class (liftIO)
import Data.Monoid ((<>))
import Data.String.Conversions (cs)
import qualified Hasql.Query as H
@@ -26,6 +27,7 @@ import Web.JWT (secret)
#ifndef mingw32_HOST_OS
import System.Posix.Signals
import Control.Concurrent (myThreadId)
+import Data.IORef
import Control.Exception.Base (throwTo, AsyncException(..))
#endif
@@ -58,15 +60,6 @@ main = do
pool <- P.acquire (configPool conf, 10, pgSettings)
-#ifndef mingw32_HOST_OS
- tid <- myThreadId
- forM_ [sigINT, sigTERM] $ \sig ->
- void $ installHandler sig (Catch $ do
- P.release pool
- throwTo tid UserInterrupt
- ) Nothing
-#endif
-
result <- P.use pool $ do
supported <- isServerVersionSupported
unless supported $ error (
@@ -74,5 +67,21 @@ main = do
<> show minimumPgVersion)
getDbStructure (cs $ configSchema conf)
- let dbStructure = either (error.show) id result
- runSettings appSettings $ postgrest conf dbStructure pool
+ refDbStructure <- newIORef $ either (error.show) id result
+
+#ifndef mingw32_HOST_OS
+ tid <- myThreadId
+ forM_ [sigINT, sigTERM] $ \sig ->
+ void $ installHandler sig (Catch $ do
+ P.release pool
+ throwTo tid UserInterrupt
+ ) Nothing
+
+ void $ installHandler sigHUP (
+ Catch . void . P.use pool $ do
+ s <- getDbStructure (cs $ configSchema conf)
+ liftIO $ atomicWriteIORef refDbStructure s
+ ) Nothing
+#endif
+
+ runSettings appSettings $ postgrest conf refDbStructure pool
diff --git a/test/Main.hs b/test/Main.hs
index a8758aacf..4e0c47efb 100644
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -7,6 +7,7 @@ import qualified Hasql.Pool as P
import PostgREST.DbStructure (getDbStructure)
import PostgREST.App (postgrest)
+import Data.IORef
import Data.String.Conversions (cs)
import qualified Feature.AuthSpec
@@ -27,10 +28,10 @@ main = do
pool <- P.acquire (3, 10, cs testDbConn)
result <- P.use pool $ getDbStructure "test"
- let dbStructure = either (error.show) id result
- withApp = return $ postgrest testCfg dbStructure pool
- ltdApp = return $ postgrest testLtdRowsCfg dbStructure pool
- unicodeApp = return $ postgrest testUnicodeCfg dbStructure pool
+ refDbStructure <- newIORef $ either (error.show) id result
+ let withApp = return $ postgrest testCfg refDbStructure pool
+ ltdApp = return $ postgrest testLtdRowsCfg refDbStructure pool
+ unicodeApp = return $ postgrest testUnicodeCfg refDbStructure pool
hspec $ do
mapM_ (beforeAll_ resetDb . before withApp) specs