Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ All notable changes to this project will be documented in this file. From versio
- Log error when `db-schemas` config contains schema `pg_catalog` or `information_schema` by @taimoorzaeem in #4359
+ Now fails at startup. Prior to this, it failed with `PGRST205` on requests related to these schemas.

### Fixed
- Shutdown should wait for in flight requests by @mkleczek in #4702

## [14.7] - 2026-03-20

### Fixed
Expand Down
47 changes: 47 additions & 0 deletions nix/overlays/haskell-packages.nix
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,53 @@ let
hasql-pool = lib.dontCheck prev.hasql-pool_1_0_1;
hasql-transaction = lib.dontCheck prev.hasql-transaction_1_1_0_1;
postgresql-binary = lib.dontCheck (lib.doJailbreak prev.postgresql-binary_0_13_1_3);

http2 =
prev.callHackageDirect
{
pkg = "http2";
ver = "5.4.0";
sha256 = "sha256-PeEWVd61bQ8G7LvfLeXklzXqNJFaAjE2ecRMWJZESPE=";
}
{ };

http-semantics =
prev.callHackageDirect
{
pkg = "http-semantics";
ver = "0.4.0";
sha256 = "sha256-rh0z51EKvsu5rQd5n2z3fSRjjEObouNZSBPO9NFYOF0=";
}
{ };

network-run =
prev.callHackageDirect
{
pkg = "network-run";
ver = "0.5.0";
sha256 = "sha256-vbXh+CzxDsGApjqHxCYf/ijpZtUCApFbkcF5gyN0THU=";
}
{ };

time-manager =
prev.callHackageDirect
{
pkg = "time-manager";
ver = "0.2.4";
sha256 = "sha256-sAt/331YLQ2IU3z90aKYSq1nxoazv87irsuJp7ZG3pw=";
}
{ };

warp =
lib.dontCheck (prev.callCabal2nixWithOptions "warp"
(super.fetchFromGitHub {
owner = "mkleczek";
repo = "wai";
rev = "7ca66f023ccaf2e3862ad97392f1f11afea3b6ff";
#sha256 = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
sha256 = "sha256-Z/1yikmlDZhjv4LhewjRvW7g5s8KZrHztFRnefEDu7Y=";
}) "--subpath=warp"
{ });
};
in
{
Expand Down
11 changes: 9 additions & 2 deletions src/PostgREST/App.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import GHC.IO.Exception (IOErrorType (..))
import System.IO.Error (ioeGetErrorType)

import Control.Monad.Except (liftEither)
import Control.Monad.Extra (whenJust)
import Data.Either.Combinators (mapLeft, whenLeft)
import Data.Maybe (fromJust)
import Data.String (IsString (..))
Expand Down Expand Up @@ -79,8 +80,10 @@ run appState = do

AppState.schemaCacheLoader appState -- Loads the initial SchemaCache
(mainSocket, adminSocket) <- initSockets conf

Unix.installSignalHandlers observer (AppState.getMainThreadId appState) (AppState.schemaCacheLoader appState) (AppState.readInDbConfig False appState)
let closeSockets = do
whenJust adminSocket NS.close
NS.close mainSocket
Unix.installSignalHandlers observer closeSockets (AppState.schemaCacheLoader appState) (AppState.readInDbConfig False appState)

Listener.runListener appState

Expand All @@ -92,6 +95,10 @@ run appState = do
address <- resolveSocketToAddress mainSocket
observer $ AppServerAddressObs address

-- Hardcoding maximum graceful shutdown timeout (arbitrary set to 5 seconds)
-- This is unfortunate but necessary becase graceful shutdowns don't work with HTTP keep-alive
-- causing Warp to handle requests on already opened connections even if the listen socket is closed
-- See: https://github.com/yesodweb/wai/issues/853
Warp.runSettingsSocket (serverSettings conf & setOnException onWarpException) mainSocket app
where
observer = AppState.getObserver appState
Expand Down
5 changes: 2 additions & 3 deletions src/PostgREST/Unix.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ import System.Directory (removeFile)
import System.IO.Error (isDoesNotExistError)

-- | Set signal handlers, only for systems with signals
installSignalHandlers :: Observation.ObservationHandler -> ThreadId -> IO () -> IO () -> IO ()
installSignalHandlers :: Observation.ObservationHandler -> IO () -> IO () -> IO () -> IO ()
#ifndef mingw32_HOST_OS
installSignalHandlers observer tid usr1 usr2 = do
let interrupt = throwTo tid UserInterrupt
installSignalHandlers observer interrupt usr1 usr2 = do
install Signals.sigINT $ observer (Observation.TerminationUnixSignalObs "SIGINT") >> interrupt
install Signals.sigTERM $ observer (Observation.TerminationUnixSignalObs "SIGTERM") >> interrupt
install Signals.sigUSR1 usr1
Expand Down
1 change: 0 additions & 1 deletion test/io/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ def sleep():
t.join()


@pytest.mark.xfail(reason="Graceful shutdown is currently failing", strict=True)
def test_graceful_shutdown_waits_for_in_flight_request(defaultenv):
"SIGTERM should allow in-flight requests to finish before exiting"

Expand Down