From 5cbabe4a2129a48dc3bfc8c8d93e1f09f395da11 Mon Sep 17 00:00:00 2001 From: laurenceisla Date: Sat, 24 Jul 2021 16:27:02 -0500 Subject: [PATCH] Add database notification functionality and configuration variables for schema reloading --- admin.rst | 2 +- configuration.rst | 18 ++++++++++++++++++ postgrest.dict | 1 + releases/upcoming.rst | 7 +++++++ schema_cache.rst | 42 ++++++++++++++++++++++++++++++------------ 5 files changed, 57 insertions(+), 13 deletions(-) diff --git a/admin.rst b/admin.rst index 4a1c7ab26..7b5e5e95f 100644 --- a/admin.rst +++ b/admin.rst @@ -131,7 +131,7 @@ In order to increase performance, PostgREST uses prepared statements by default. If prepared statements are enabled, PostgREST will quit after detecting that transaction or statement pooling is being used. -You should also set the ``db-channel-enabled`` config option to ``false``, due to the ``LISTEN`` command not being compatible with transaction pooling, although it should not give any errors if it's left enabled by default. +You should also set the :ref:`db-channel-enabled` config option to ``false``, due to the ``LISTEN`` command not being compatible with transaction pooling, although it should not give any errors if it's left enabled by default. Debugging ========= diff --git a/configuration.rst b/configuration.rst index 066b117be..bed5a750d 100644 --- a/configuration.rst +++ b/configuration.rst @@ -39,6 +39,8 @@ db-anon-role String Y db-pool Int 10 db-pool-timeout Int 10 db-extra-search-path String public +db-channel String pgrst +db-channel-enabled Boolean True db-prepared-statements Boolean True db-tx-end String commit server-host String !4 @@ -135,6 +137,22 @@ db-extra-search-path Multiple schemas can be added in a comma-separated string, e.g. ``public, extensions``. +.. _db-channel: + +db-channel +---------- + + The name of the notification channel that PostgREST uses for :ref:`schema_reloading` and configuration reloading. + +.. _db-channel-enabled: + +db-channel-enabled +------------------ + + When this is set to :code:`true`, the notification channel specified in :ref:`db-channel` is enabled. + + You should set this to ``false`` when using PostgresSQL behind a connection pooler such as PgBouncer working in transaction pooling mode. See :ref:`this section ` for more information. + .. _db-prepared-statements: db-prepared-statements diff --git a/postgrest.dict b/postgrest.dict index 7c3644939..bc12f8438 100644 --- a/postgrest.dict +++ b/postgrest.dict @@ -91,6 +91,7 @@ Petr PgBouncer pgcrypto pgjwt +pgrst pgSQL phfts phraseto diff --git a/releases/upcoming.rst b/releases/upcoming.rst index 81c3a8a57..cda81ff1b 100644 --- a/releases/upcoming.rst +++ b/releases/upcoming.rst @@ -16,6 +16,9 @@ Added * Allow :ref:`s_procs_variadic`. |br| -- `@wolfgangwalther `_ +* Allow schema cache reloading using PostgreSQL :ref:`NOTIFY ` command. + |br| -- `@steve-chavez `_ + * Allow sending the header ``Prefer: headers-only`` to get a response with a ``Location`` header. See :ref:`insert_update`. |br| -- `@laurenceisla `_ @@ -53,6 +56,10 @@ Changed For more details, see `Docker image built with Nix `_. |br| -- `@monacoremo `_ +* The ``pg_listen`` `utility `_ is no longer needed to automatically reload the schema cache + and it's replaced entirely by database notifications. See :ref:`schema_reloading_notify`. + |br| -- `@steve-chavez `_ + * Improved error message for a not found RPC on a stale schema (see :ref:`stale_function_signature`) and for the unsupported case of overloaded functions with the same argument names but different types. |br| -- `@laurenceisla `_ diff --git a/schema_cache.rst b/schema_cache.rst index 9e994c75e..fe684b708 100644 --- a/schema_cache.rst +++ b/schema_cache.rst @@ -89,7 +89,7 @@ See the section :ref:`schema_reloading` to solve this issue. Schema Cache Reloading ---------------------- -To refresh the cache without restarting the PostgREST server, send the server process a SIGUSR1 signal: +To refresh the cache without restarting the PostgREST server, send a SIGUSR1 signal to the server process. .. code:: bash @@ -106,26 +106,44 @@ To refresh the cache without restarting the PostgREST server, send the server pr # or in docker-compose docker-compose kill -s SIGUSR1 -The above is the manual way to do it. To automate cache reloads, use a database trigger like this: +.. _schema_reloading_notify: + +Reloading with NOTIFY +~~~~~~~~~~~~~~~~~~~~~ + +There are environments where you can't send the SIGUSR1 Unix Signal (like on managed containers in cloud services or on Windows systems). For this reason, PostgREST also allows you to reload its schema cache through PostgreSQL `NOTIFY `_ as follows: .. code-block:: postgresql - CREATE OR REPLACE FUNCTION public.notify_ddl_postgrest() - RETURNS event_trigger - LANGUAGE plpgsql + NOTIFY pgrst, 'reload schema' + +The ``"pgrst"`` notification channel is enabled by default. For configuring the channel, see :ref:`db-channel` and :ref:`db-channel-enabled`. + +Automatic schema cache reloading +******************************** + +You can do automatic schema cache reloading in a pure SQL way with an `event trigger `_ and ``NOTIFY``. + +.. code-block:: postgresql + + -- Create an event trigger function + CREATE OR REPLACE FUNCTION public.pgrst_watch() RETURNS event_trigger + LANGUAGE plpgsql AS $$ BEGIN - NOTIFY ddl_command_end; + NOTIFY pgrst; END; $$; - CREATE EVENT TRIGGER ddl_postgrest ON ddl_command_end - EXECUTE PROCEDURE public.notify_ddl_postgrest(); + -- This event trigger will fire after every ddl_command_end event + CREATE EVENT TRIGGER pgrst_watch + ON ddl_command_end + EXECUTE PROCEDURE public.pgrst_watch(); -Then run the `pg_listen `_ utility to monitor for that event and send a SIGUSR1 when it occurs: +Now, whenever the ``pgrst_watch`` trigger is fired in the database, PostgREST will automatically reload the schema cache. -.. code-block:: bash +To disable auto reloading, drop the trigger: - pg_listen ddl_command_end $(which killall) -SIGUSR1 postgrest +.. code-block:: postgresql -Now, whenever the structure of the database changes, PostgreSQL will notify the ``ddl_command_end`` channel, which will cause ``pg_listen`` to send PostgREST the signal to reload its cache. Note that pg_listen requires full path to the executable in the example above. + DROP EVENT TRIGGER pgrst_watch \ No newline at end of file