-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
db settings: reload on connection recovery, only get them from global/current-database scope and change dash to underscore #1760
Conversation
It would be really nice, if we could add a test for reload recovery. This would go a long way in terms of test coverage. In general, I think we're not testing any of the "recover from an error" situations, yet. However, I can't come up with a way to do this with our current io test setup. |
I think this is more or less fixed and I'm in the process of adding python tests. However these tests will fail with the latest commit: postgrest/test/io-tests/test_io.py Lines 341 to 347 in 0ddd676
This is because the config file for the tests uses postgrest/test/io-tests/configs/secret-from-file.config Lines 3 to 4 in 0ddd676
And since the config file reload is now done in a subthread, stdin will not reach it. Because AFAICT, stdin only reaches the parent process: https://stackoverflow.com/questions/55602283/how-to-write-data-to-stdin-to-be-consumed-by-a-separate-thread-waiting-on-input Seems the workaround is to create a named pipe somehow for stdin to work, but it looks too complicated to fix this in postgrest(also not sure if possible). How about if I just change the tests for not using stdin? @wolfgangwalther Thoughts? |
Was "reading the secret from stdin" just a hack to test "reading the secret from file"? So we don't actually support/advertise reading from stdin here? In that case I agree: Just use a proper temp file created with python (have a look at some of the other tests, I think there is a nice pytest-way of doing it). |
Cool. I'll do that.
I've managed to create a couple of utilitarian functions that seem to be working. def pg_stop():
"Stop postgresql"
subprocess.run(["pg_ctl", "stop", "-m", "i"])
time.sleep(1)
def pg_start():
"Start postgresql"
PGHOST = os.getenv("PGHOST")
subprocess.run(["pg_ctl", "start", "-o", f'-F -c listen_addresses="" -k {PGHOST}']) I'm not sure if they'll hold up when writing the actual tests though. I'm all ears for a better way to do this. |
I think the problem with that approach is, that it will break running the io tests in parallel. We're using the same database instance for all tests, so those other tests will have a stopped postgres, too. Maybe we can add some kind of a postgres proxy - pgbouncer or something? I am not familiar with that, but that could be a base to test support for that in general, too. If we keep postgres running, but only start the proxy/pgbouncer after we started postgrest.. that could work. WDYT? |
Not that I'm aware of. Seems this was inherited from previous bash tests: Line 373 in 0c25f12
Though it does seem to be a legitimate use case: kubernetes/kubernetes#54200 (comment) (Personally I've never done it) |
It does seem interesting. But if the problem is the parallelism of the io tests, perhaps I'd be easier to separate the recovery tests(in a (I'm definitely up for including pgbouncer later though) |
It should be possible to nest with_tmp_db instances with no issues. So what we could do is:
Then it should be possible to stop just that db without affecting the parent db. Edit: simpler solution |
I don't think this will work like that. Now we have 2 postgres instances running - which instance will |
Maybe instead of running a full pgbouncer as a proxy, we can just set up a port forwarding via So in the test, we'd:
No need to fiddle with restarting postgres etc. either. |
I didn't want to break any use cases(perhaps UNIX-savy users use The main problem was that the files(db-uri, jwt-secret) were read several times and reading What I've changed is that external config files are now only read one time. Also untangled the logic a bit, I think the code is also clearer this way.
Hm, could you guys help me with the recovery tests on another PR? @monacoremo @wolfgangwalther. I can put a list of the manual tests I make for ensuring the recovery is working. Still have to do some changes here(like verify SIGUSR2 reloads the external config files) and it would take me a while to figure out how to change the setup for the recovery tests. |
I didn't go through the latest commit, yet, but is my understanding correct as follows?
If so, that's a lot better, I agree!
Absolutely. A list of all your manual tests to reproduce would be great! |
Yes, the external files will be read only when manually requesting so, with SIGUSR2 or NOTIFY. They'll not be re-read when recovering, here only the db config will be re-read when the Testing with Only reading external files when requested avoids that issue. Also seemed more in line with the connection worker behavior.
No, the db config is also read on the main thread. This is needed because of the
Yes, correct.
Cool :)!. I'll put the list here when I'm done with some changes. |
a98c620
to
837e71f
Compare
a36f949
to
6c5f31b
Compare
GUC settings with dashes cannot be shown with show or current_setting. https://www.postgresql.org/message-id/flat/20210209144059.GA21360%40depesz.com
6c5f31b
to
0a2002f
Compare
@@ -358,12 +358,12 @@ reReadConfig startingUp pool gucConfigEnabled env path refConf dbUriFile secretF | |||
Left err -> | |||
if startingUp | |||
then panic err -- die on invalid config if the program is starting up | |||
else hPutStrLn stderr $ "Failed config load. " <> err | |||
else hPutStrLn stderr $ "Failed loading in-database config. " <> err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The term in-database config is much clearer.
Perhaps the db-load-guc-config
option should be changed to config-in-db
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, I see your point about db-load-guc-config
- it's clumsy. I'd like to keep the db-
prefix, though.
What about db-has-config = true|false
? Or just db-config
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The has
looks a bit weird inside a config option. I'll go with db-config
, it's already much better than db-load-guc-config
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wolfgangwalther What do you think of having db-config
to be false
by default
The main argument for it being true
was to have the least amount of config options: #1729 (comment). But that isn't possible atm, because db-anon-role
and db-schemas
are required.
However I'm thinking that only defining db-uri
could be done and still maintain the required fields restriction. This by having an DbUriAppConfig
that is used previous to AppConfig
. With that even non-reloadable config options(like db-pool
) could be set with the db-config
.
But anyway the above is still not done, so db-config
is not an advantage now regarding few config options.
It's just that I feel db-config=false
is right because most users will not use it(or won't be able, as mentioned on #1729 (comment)). It's a special use case. Having it by default gives potential for errors(because of the query done, twice) on all instances.
WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
db-anon-role and db-schemas are required.
This by having an DbUriAppConfig that is used previous to AppConfig
Actually, a better solution for this would be to:
- make
db-anon-role
optional. Makedb-anon-role
optional #1689 - make
db-schemas
default topublic
. This seems like a nice default that will always work. We can put a message on stdout to make it clear when the default is used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
db-anon-role and db-schemas are required.
This by having an DbUriAppConfig that is used previous to AppConfigActually, a better solution for this would be to:
* make `db-anon-role` optional. #1689 * make `db-schemas` default to `public`. This seems like a nice default that will always work. We can put a message on stdout to make it clear when the default is used.
Much, much better, yes!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's just that I feel
db-config=false
is right because most users will not use it(or won't be able, as mentioned on #1729 (comment)). It's a special use case. Having it by default gives potential for errors(because of the query done, twice) on all instances.WDYT?
I think the risk involved is very small. There is no overhead either - even though it's a separate statement, it's basically just part of reloading the schema cache. And in the big picture, loading config options from the database is just a tiny piece of reading the whole schema.
tbh: I actually wonder whether we really need the config option at all. It could just be enabled all the time. It's probably most useful for writing tests - but that's about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And in the big picture, loading config options from the database is just a tiny piece of reading the whole schema.
Ah, you're totally right here! I remember trying to do this at first, but I had some issues with the code.
I think it could be done now. We'd have to enable reloading only a part of the schema cache(the guc settings) for SIGUSR2/NOTIFY. Also make the --dump-config
wait for the connectionWoker
to finish(maybe an MVar) and only print the config contents to stdout(no Attempt to connect to db..
or tests fail).
tbh: I actually wonder whether we really need the config option at all. It could just be enabled all the time.
I think the same way now. If the guc settings are part of the schema cache, we can remove the config option.
Deleted the previous comment. I've now opened another issue for the recovery tests #1766. |
Global settings are overriden by database specific settings if they share common ones.
* Separate reading files from whole config re-read * Only reload external file on SIGUSR2/NOTIFY
Make clear that in-db config is being read
775aadd
to
980c4cd
Compare
Corrections of db settings discussed on: #1729 (comment)
pgrst.xxx-yyy
variables to use_
instead of-
.ALTER ROLE ... IN DATABASE B SET ...
should not affect postgrest in database AALTER ROLE ... IN DATABASE ... SET
should overrideALTER ROLE ... SET
)