From 88aad4b1b68d54b07dcd75f5064537c79adbf1bc Mon Sep 17 00:00:00 2001 From: Joe Nelson Date: Tue, 26 Apr 2016 07:50:23 -0700 Subject: [PATCH] Reload schema definition on SIGHUP (#570) --- CHANGELOG.md | 4 ++++ docs/api/reading.md | 14 +++++++------- postgrest.cabal | 1 + src/PostgREST/App.hs | 6 ++++-- src/PostgREST/Main.hs | 31 ++++++++++++++++++++----------- test/Main.hs | 9 +++++---- 6 files changed, 41 insertions(+), 24 deletions(-) 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