add: load schema cache dump from URI at startup#5031
Conversation
ecd794f to
d6968c9
Compare
d6968c9 to
3541b96
Compare
This comment was marked as outdated.
This comment was marked as outdated.
|
Helping to clarify, the motivation is to solve the same problems on #4999. This by loading the schema cache from a file. |
|
Q: If the schema cache file is stale, we still pick it up and serve requests as "best effort"? |
@steve-chavez I am still working on the right design and will provide more details soon. I believe now that we can solve in this PR all pain points we want to solve with materialized views. |
Yes the idea is to treat schema cache preloaded from the dump as stale and trigger asynchronous load from the db. |
3541b96 to
6417d00
Compare
6417d00 to
25e4372
Compare
1d96a81 to
a51ed0b
Compare
| def test_slow_schema_cache_dump_uri_does_not_delay_startup(defaultenv): | ||
| "A slow schema cache dump URI should not delay database-backed startup." |
There was a problem hiding this comment.
So if the URI is slow then we will prefer querying the schema cache.
Won't this will always be the case when doing HTTP requests? It seems like this feature will only make sense when it's obtained from a file since that'd be faster.
There was a problem hiding this comment.
So if the URI is slow then we will prefer querying the schema cache.
Won't this will always be the case when doing HTTP requests? It seems like this feature will only make sense when it's obtained from a file since that'd be faster.
Well... given performance issues with schema cache queries we've seen reported, I wouldn't be so sure.
HTTP is needed because:
- In
k8senvironment it is rare to have a shared filesystem to read the file from. - Since we provide schema cache dump from admin server it is very convenient for blue/green deployments - just configure each to point to the other one's admin endpoint and you have schema cache pre-loading for free.
Besides: why would HTTP be slow? The most important thing here is not the access protocol but the fact that we serve the dump from memory. I am sure establishing database session and then querying the catalog is going to be much slower than HTTP GET from localhost.
I am pretty sure HTTP is going to be faster than reading from a materialized view as well.
But really we don't want to decide up front which method is preferred. We need to query the database anyway because pre-loaded dump might be stale. So why wait if we are going to do it anyway? It is better to race - that way we are going to have startup as fast as possible - we really don't care which method wins. We only need to make sure the database result is not overwritten.
There is also another angle: we want to deal with thundering herd issue when querying the db. In clustered environments HTTP gives us a natural way to load balance initial schema cache load among existing PostgREST instances. Once we have #4643 or similar it will become even more important as it might affect startup time.
There was a problem hiding this comment.
Good points. So we're always going to race here to get the fastest possible startup, got it. We should make this clear on the docs.
a51ed0b to
6fd483f
Compare
|
Since this is about fast startups, I was wondering if you have considered the in-db config + role settings queries, which if used are also required for startup (done prior to the schema cache): postgrest/src/PostgREST/Config/Database.hs Lines 96 to 134 in 6191243 postgrest/src/PostgREST/Config/Database.hs Lines 136 to 185 in 6191243 The in-db configs are not cached but the role settings are cached here: postgrest/src/PostgREST/Config.hs Lines 128 to 129 in 6191243 When adding those I wondered if they should go into schema cache or not, I decided to make them separate to save some work on filtering them for the openAPI output. But with this feature, it looks we should make them part of the schema cache to really get the faster startup? |
Actually I don't think the "in-db config" can be put inside the schema cache because it depends on it ( |
249ef2e to
bfbc506
Compare
| Tries to load the initial :ref:`schema_cache` from the given URI when starting PostgREST. | ||
| The load is asynchronous and does not block application startup. If the URI cannot be | ||
| loaded, PostgREST logs the failure and continues with the regular database-backed | ||
| schema cache load. |
There was a problem hiding this comment.
We should be clear here that even if we load the schema cache from URL, this will be overridden later when the schema cache comes from the db.
| Load From a Local File | ||
| ~~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| First, write a schema cache dump to a file: | ||
|
|
||
| .. code:: bash | ||
| $ postgrest --dump-schema > /var/lib/postgrest/schema-cache.json | ||
| Then start PostgREST with a ``file:`` URI: | ||
|
|
||
| .. code:: bash | ||
| $ postgrest --schema-cache-uri file:///var/lib/postgrest/schema-cache.json | ||
| Load From Another PostgREST Instance | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| The :ref:`admin_server` exposes the current runtime schema cache on the | ||
| ``/schema_cache`` endpoint. If one PostgREST instance exposes its admin server on | ||
| ``localhost:3001``, a new instance can load from it with: | ||
|
|
||
| .. code:: bash | ||
| $ postgrest --schema-cache-uri http://localhost:3001/schema_cache | ||
| In Kubernetes, the same pattern can use an internal Service that points at ready | ||
| PostgREST pods: | ||
|
|
||
| .. code:: bash | ||
| $ postgrest --schema-cache-uri http://postgrest-admin:3001/schema_cache | ||
| The admin endpoint should stay internal to your deployment or be protected by your | ||
| platform's networking controls. | ||
|
|
There was a problem hiding this comment.
This section is more like a part of a how-to. I think we have two options:
- Remove it. Simplest option.
- The reference is already pretty clear IMO.
- Or make it part of a new how-to, like "Fast cold starts for PostgREST".
- Maybe it could fit into an explanation too.
bfbc506 to
053ce13
Compare
| <*> o .: "pdHasVariadic" | ||
| <*> pure Nothing | ||
| <*> o .: "pdFuncSettings" | ||
|
|
There was a problem hiding this comment.
Once #5083 gets merged, this can be remove by just adding:
deriving instance JSON.FromJSON SQL.IsolationLeveland deriving the instance for Routine type like:
data Routine = ...
...
deriving (Eq, Show, Generic, JSON.ToJSON, JSON.FromJSON)|
@mkleczek Please address the feedback here 🙏 |
053ce13 to
bfcfcb2
Compare
Resolves #4999
by making it unnecessary.