pg_ctl: Add wait option to promote action

When waiting is selected for the promote action, look into pg_control
until the state changes, then use the PQping-based waiting until the
server is reachable.

Reviewed-by: Michael Paquier <michael.paquier@gmail.com>
This commit is contained in:
Peter Eisentraut 2016-08-05 21:35:19 -04:00
parent ebdf5bf7d1
commit e7010ce479
3 changed files with 72 additions and 20 deletions

View File

@ -91,6 +91,8 @@ PostgreSQL documentation
<cmdsynopsis>
<command>pg_ctl</command>
<arg choice="plain"><option>promote</option></arg>
<arg choice="opt"><option>-w</option></arg>
<arg choice="opt"><option>-t</option> <replaceable>seconds</replaceable></arg>
<arg choice="opt"><option>-s</option></arg>
<arg choice="opt"><option>-D</option> <replaceable>datadir</replaceable></arg>
</cmdsynopsis>
@ -361,8 +363,8 @@ PostgreSQL documentation
<term><option>--timeout</option></term>
<listitem>
<para>
The maximum number of seconds to wait when waiting for startup or
shutdown to complete. Defaults to the value of the
The maximum number of seconds to wait when waiting for an operation
to complete (see option <option>-w</option>). Defaults to the value of the
<envar>PGCTLTIMEOUT</> environment variable or, if not set, to 60
seconds.
</para>
@ -383,8 +385,23 @@ PostgreSQL documentation
<term><option>-w</option></term>
<listitem>
<para>
Wait for the startup or shutdown to complete.
Waiting is the default option for shutdowns, but not startups.
Wait for an operation to complete. This is supported for the
modes <literal>start</literal>, <literal>stop</literal>,
<literal>restart</literal>, <literal>promote</literal>,
and <literal>register</literal>.
</para>
<para>
Waiting is the default option for shutdowns, but not startups,
restarts, or promotions. This is mainly for historical reasons; the
waiting option is almost always preferable. If waiting is not
selected, the requested action is triggered, but there is no feedback
about its success. In that case, the server log file or an external
monitoring system would have to be used to check the progress and
success of the operation.
</para>
<para>
When waiting for startup, <command>pg_ctl</command> repeatedly
attempts to connect to the server.
When waiting for shutdown, <command>pg_ctl</command> waits for
@ -400,8 +417,8 @@ PostgreSQL documentation
<term><option>-W</option></term>
<listitem>
<para>
Do not wait for startup or shutdown to complete. This is the
default for start and restart modes.
Do not wait for an operation to complete. This is the opposite of the
option <option>-w</option>.
</para>
</listitem>
</varlistentry>

View File

@ -1228,7 +1228,34 @@ do_promote(void)
exit(1);
}
print_msg(_("server promoting\n"));
if (do_wait)
{
DBState state = DB_STARTUP;
print_msg(_("waiting for server to promote..."));
while (wait_seconds > 0)
{
state = get_control_dbstate();
if (state == DB_IN_PRODUCTION)
break;
print_msg(".");
pg_usleep(1000000); /* 1 sec */
wait_seconds--;
}
if (state == DB_IN_PRODUCTION)
{
print_msg(_(" done\n"));
print_msg(_("server promoted\n"));
}
else
{
print_msg(_(" stopped waiting\n"));
print_msg(_("server is still promoting\n"));
}
}
else
print_msg(_("server promoting\n"));
}
@ -2405,18 +2432,10 @@ main(int argc, char **argv)
if (!wait_set)
{
switch (ctl_command)
{
case RESTART_COMMAND:
case START_COMMAND:
do_wait = false;
break;
case STOP_COMMAND:
do_wait = true;
break;
default:
break;
}
if (ctl_command == STOP_COMMAND)
do_wait = true;
else
do_wait = false;
}
if (ctl_command == RELOAD_COMMAND)

View File

@ -3,7 +3,7 @@ use warnings;
use PostgresNode;
use TestLib;
use Test::More tests => 9;
use Test::More tests => 12;
my $tempdir = TestLib::tempdir;
@ -37,3 +37,19 @@ command_ok([ 'pg_ctl', '-D', $node_standby->data_dir, 'promote' ],
ok($node_standby->poll_query_until('postgres', 'SELECT NOT pg_is_in_recovery()'),
'promoted standby is not in recovery');
# same again with wait option
$node_standby = get_new_node('standby2');
$node_standby->init_from_backup($node_primary, 'my_backup', has_streaming => 1);
$node_standby->start;
is($node_standby->safe_psql('postgres', 'SELECT pg_is_in_recovery()'),
't', 'standby is in recovery');
command_ok([ 'pg_ctl', '-D', $node_standby->data_dir, '-w', 'promote' ],
'pg_ctl -w promote of standby runs');
# no wait here
is($node_standby->safe_psql('postgres', 'SELECT pg_is_in_recovery()'),
'f', 'promoted standby is not in recovery');