|
6 | 6 | import subprocess |
7 | 7 | import time |
8 | 8 |
|
| 9 | +from collections import Iterable |
9 | 10 | from shutil import rmtree |
10 | 11 | from six import raise_from, iteritems, text_type |
11 | 12 | from tempfile import mkstemp, mkdtemp |
|
64 | 65 |
|
65 | 66 | from .pubsub import Publication, Subscription |
66 | 67 |
|
| 68 | +from .standby import First |
| 69 | + |
67 | 70 | from .utils import \ |
68 | 71 | PgVer, \ |
69 | 72 | eprint, \ |
@@ -699,7 +702,7 @@ def restart(self, params=[]): |
699 | 702 |
|
700 | 703 | def reload(self, params=[]): |
701 | 704 | """ |
702 | | - Reload config files using pg_ctl. |
| 705 | + Asynchronously reload config files using pg_ctl. |
703 | 706 |
|
704 | 707 | Args: |
705 | 708 | params: additional arguments for pg_ctl. |
@@ -1117,6 +1120,45 @@ def replicate(self, name=None, slot=None, **kwargs): |
1117 | 1120 | with clean_on_error(self.backup(**kwargs)) as backup: |
1118 | 1121 | return backup.spawn_replica(name=name, destroy=True, slot=slot) |
1119 | 1122 |
|
| 1123 | + def set_synchronous_standbys(self, standbys): |
| 1124 | + """ |
| 1125 | + Set standby synchronization options. This corresponds to |
| 1126 | + `synchronous_standby_names <https://www.postgresql.org/docs/current/static/runtime-config-replication.html#GUC-SYNCHRONOUS-STANDBY-NAMES>`_ |
| 1127 | + option. Note that :meth:`~.PostgresNode.reload` or |
| 1128 | + :meth:`~.PostgresNode.restart` is needed for changes to take place. |
| 1129 | +
|
| 1130 | + Args: |
| 1131 | + standbys: either :class:`.First` or :class:`.Any` object specifying |
| 1132 | + sychronization parameters or just a plain list of |
| 1133 | + :class:`.PostgresNode`s replicas which would be equivalent |
| 1134 | + to passing ``First(1, <list>)``. For PostgreSQL 9.5 and below |
| 1135 | + it is only possible to specify a plain list of standbys as |
| 1136 | + `FIRST` and `ANY` keywords aren't supported. |
| 1137 | +
|
| 1138 | + Example:: |
| 1139 | +
|
| 1140 | + from testgres import get_new_node, First |
| 1141 | +
|
| 1142 | + master = get_new_node().init().start() |
| 1143 | + with master.replicate().start() as standby: |
| 1144 | + master.append_conf("synchronous_commit = remote_apply") |
| 1145 | + master.set_synchronous_standbys(First(1, [standby])) |
| 1146 | + master.restart() |
| 1147 | +
|
| 1148 | + """ |
| 1149 | + if self._pg_version >= '9.6': |
| 1150 | + if isinstance(standbys, Iterable): |
| 1151 | + standbys = First(1, standbys) |
| 1152 | + else: |
| 1153 | + if isinstance(standbys, Iterable): |
| 1154 | + standbys = u", ".join( |
| 1155 | + u"\"{}\"".format(r.name) for r in standbys) |
| 1156 | + else: |
| 1157 | + raise TestgresException("Feature isn't supported in " |
| 1158 | + "Postgres 9.5 and below") |
| 1159 | + |
| 1160 | + self.append_conf("synchronous_standby_names = '{}'".format(standbys)) |
| 1161 | + |
1120 | 1162 | def catchup(self, dbname=None, username=None): |
1121 | 1163 | """ |
1122 | 1164 | Wait until async replica catches up with its master. |
|
0 commit comments