clarify schema cache and errors page

This commit is contained in:
steve-chavez
2023-05-05 12:04:46 -03:00
committed by Steve Chavez
parent 9de94274cf
commit 560ec79a90
3 changed files with 34 additions and 90 deletions
+14 -6
View File
@@ -1,9 +1,14 @@
.. _error_source:
Error Source
Error Format
============
For the most part, error messages will come directly from the database with the same `structure that PostgreSQL uses <https://www.postgresql.org/docs/current/error-style-guide.html>`_. PostgREST will convert the ``MESSAGE``, ``DETAIL``, ``HINT`` and ``ERRCODE`` from the PostgreSQL error to JSON and add an HTTP status code to the response. For instance, when querying a nonexistent table:
PostgREST error messages follow the PostgreSQL error structure. It includes ``MESSAGE``, ``DETAIL``, ``HINT``, ``ERRCODE`` and will add an HTTP status code to the response.
Errors from PostgreSQL
----------------------
PostgREST will forward errors coming from PostgreSQL. For instance, when querying a nonexistent table:
.. code-block:: http
@@ -23,7 +28,10 @@ For the most part, error messages will come directly from the database with the
"message": "relation \"api.nonexistent_table\" does not exist"
}
However, some errors do come from PostgREST itself (such as those related to the :doc:`Schema Cache <schema_cache>`). These have the same structure as the PostgreSQL errors but are differentiated by the ``PGRST`` prefix in the ``code`` field. For instance, when querying a function that does not exist:
Errors from PostgREST
---------------------
Errors that come from PostgREST itself maintain the same structure. But differ in the ``PGRST`` prefix in the ``code`` field. For instance, when querying a function that does not exist in the :doc:`schema cache <schema_cache>`:
.. code-block:: http
@@ -37,7 +45,7 @@ However, some errors do come from PostgREST itself (such as those related to the
.. code-block:: json
{
"hint": "If a new function was created in the database with this name and parameters, try reloading the schema cache.",
"hint": "...",
"details": null
"code": "PGRST202",
"message": "Could not find the api.nonexistent_function() function in the schema cache"
@@ -250,7 +258,7 @@ Related to a :ref:`stale schema cache <stale_schema>`. Most of the time, these e
+---------------+-------------+-------------------------------------------------------------+
| Code | HTTP status | Description |
+===============+=============+=============================================================+
| .. _pgrst200: | 400 | Caused by :ref:`stale_fk_relationships`, otherwise any of |
| .. _pgrst200: | 400 | Caused by stale foreign key relationships, otherwise any of |
| | | the embedding resources or the relationship itself may not |
| PGRST200 | | exist in the database. |
+---------------+-------------+-------------------------------------------------------------+
@@ -258,7 +266,7 @@ Related to a :ref:`stale schema cache <stale_schema>`. Most of the time, these e
| | | See :ref:`embed_disamb`. |
| PGRST201 | | |
+---------------+-------------+-------------------------------------------------------------+
| .. _pgrst202: | 404 | Caused by a :ref:`stale_function_signature`, otherwise |
| .. _pgrst202: | 404 | Caused by a stale function signature, otherwise |
| | | the function may not exist in the database. |
| PGRST202 | | |
+---------------+-------------+-------------------------------------------------------------+
+2 -2
View File
@@ -84,11 +84,11 @@ Changed
* Modified the default logging level from ``info`` to ``error``. See :ref:`log-level`.
|br| -- `@steve-chavez <https://github.com/steve-chavez>`_
* Changed the error message for a not found RPC on a stale schema (see :ref:`stale_function_signature`) and for the unsupported case of
* Changed the error message for a not found RPC on a stale schema (see :ref:`stale_schema`) and for the unsupported case of
overloaded functions with the same argument names but different types.
|br| -- `@laurenceisla <https://github.com/laurenceisla>`_
* Changed the error message for the no relationship found error. See :ref:`stale_fk_relationships`.
* Changed the error message for the no relationship found error. See :ref:`stale_schema`.
|br| -- `@laurenceisla <https://github.com/laurenceisla>`_
Fixed
+18 -82
View File
@@ -4,8 +4,7 @@
<h1>Schema Cache</h1>
Certain PostgREST features require metadata from the database schema. Getting this metadata requires executing expensive queries, so
in order to avoid repeating this work, PostgREST uses a schema cache.
Some PostgREST features need metadata from the database schema. Getting this metadata requires expensive queries. To avoid repeating this work, PostgREST uses a schema cache.
+--------------------------------------------+-------------------------------------------------------------------------------+
| Feature | Required Metadata |
@@ -30,84 +29,19 @@ in order to avoid repeating this work, PostgREST uses a schema cache.
.. _stale_schema:
The Stale Schema Cache
----------------------
Stale Schema Cache
------------------
When you make changes on the metadata mentioned above, the schema cache will turn stale on a running PostgREST. Future requests that use the above features will need the :ref:`schema cache to be reloaded <schema_reloading>`; otherwise, you'll get an error instead of the expected result.
One operational problem that comes a cache is that it can go stale. This can happen for PostgREST when you make changes to the metadata before mentioned. Requests that depend on the metadata will fail.
For instance, let's see what would happen if you have a stale schema cache for foreign key relationships and function signatures.
.. _stale_fk_relationships:
Stale Foreign Key Relationships
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Suppose you add a ``cities`` table to your database and define a foreign key that references an existing ``countries`` table. Then, you make a request to get the ``cities`` and their belonging ``countries``.
.. tabs::
.. code-tab:: http
GET /cities?select=name,country:countries(id,name) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/cities?select=name,country:countries(id,name)"
The result will be an error:
.. code-block:: json
{
"hint": "Verify that 'cities' and 'countries' exist in the schema 'api' and that there is a foreign key relationship between them. If a new relationship was created, try reloading the schema cache.",
"details": null,
"code": "PGRST200",
"message": "Could not find a relationship between 'cities' and 'countries' in the schema cache"
}
As you can see, PostgREST couldn't find the newly created foreign key in the schema cache. See :ref:`schema_reloading` and :ref:`auto_schema_reloading` to solve this issue.
.. _stale_function_signature:
Stale Function Signature
~~~~~~~~~~~~~~~~~~~~~~~~
The same issue will occur on newly created functions on a running PostgREST.
.. code-block:: plpgsql
CREATE FUNCTION plus_one(num integer)
RETURNS integer AS $$
SELECT num + 1;
$$ LANGUAGE SQL IMMUTABLE;
.. tabs::
.. code-tab:: http
GET /rpc/plus_one?num=1 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/plus_one?num=1"
.. code-block:: json
{
"hint": "If a new function was created in the database with this name and parameters, try reloading the schema cache.",
"details": null,
"code": "PGRST202",
"message": "Could not find the api.plus_one(num) function in the schema cache"
}
Here, PostgREST tries to find the function on the stale schema to no avail. See :ref:`schema_reloading` and :ref:`auto_schema_reloading` to solve this issue.
You can solve this by reloading the cache manually or automatically.
.. _schema_reloading:
Schema Cache Reloading
----------------------
To reload the cache without restarting the PostgREST server, send a SIGUSR1 signal to the server process.
To manually reload the cache without restarting the PostgREST server, send a SIGUSR1 signal to the server process.
.. code:: bash
@@ -123,27 +57,29 @@ For docker you can do:
# or in docker-compose
docker-compose kill -s SIGUSR1 <service>
There's no downtime when reloading the schema cache. The reloading will happen on a background thread while requests keep being served.
Theres no downtime when reloading the schema cache. The reloading will happen on a background thread while serving requests.
.. _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 <https://www.postgresql.org/docs/current/sql-notify.html>`_ as follows:
PostgREST also allows you to reload its schema cache through PostgreSQL `NOTIFY <https://www.postgresql.org/docs/current/sql-notify.html>`_.
.. code-block:: postgresql
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`.
This is useful in environments where you cant send the SIGUSR1 Unix Signal. Like on cloud managed containers or on Windows systems.
The ``pgrst`` notification channel is enabled by default. For configuring the channel, see :ref:`db-channel` and :ref:`db-channel-enabled`.
.. _auto_schema_reloading:
Automatic Schema Cache Reloading
--------------------------------
You can do automatic schema cache reloading in a pure SQL way and forget about stale schema cache errors with an `event trigger <https://www.postgresql.org/docs/current/event-trigger-definition.html>`_ and ``NOTIFY``.
You can do automatic schema cache reloading in a pure SQL way and forget about stale schema cache errors. For this use an `event trigger <https://www.postgresql.org/docs/current/event-trigger-definition.html>`_ and ``NOTIFY``.
.. code-block:: postgresql
@@ -161,9 +97,9 @@ You can do automatic schema cache reloading in a pure SQL way and forget about s
ON ddl_command_end
EXECUTE PROCEDURE pgrst_watch();
Now, whenever the ``pgrst_watch`` trigger is fired in the database, PostgREST will automatically reload the schema cache.
Now, whenever the ``pgrst_watch`` trigger fires, PostgREST will auto-reload the schema cache.
To disable auto reloading, drop the trigger:
To disable auto reloading, drop the trigger.
.. code-block:: postgresql
@@ -172,12 +108,12 @@ To disable auto reloading, drop the trigger:
Finer-Grained Event Trigger
~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can refine the previous event trigger and only react to the events relevant to the schema cache. This also prevents unnecessary
reloading when creating temporary tables(``CREATE TEMP TABLE``) inside functions.
You can refine the previous event trigger to only react to the events relevant to the schema cache. This also prevents unnecessary
reloading when creating temporary tables inside functions.
.. code-block:: postgresql
-- watch create and alter
-- watch CREATE and ALTER
CREATE OR REPLACE FUNCTION pgrst_ddl_watch() RETURNS event_trigger AS $$
DECLARE
cmd record;
@@ -204,7 +140,7 @@ reloading when creating temporary tables(``CREATE TEMP TABLE``) inside functions
END LOOP;
END; $$ LANGUAGE plpgsql;
-- watch drop
-- watch DROP
CREATE OR REPLACE FUNCTION pgrst_drop_watch() RETURNS event_trigger AS $$
DECLARE
obj record;