Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit60b2b1c

Browse files
committed
Add set_synchronous_standbys() method
1 parent221df4f commit60b2b1c

File tree

4 files changed

+122
-2
lines changed

4 files changed

+122
-2
lines changed

‎docs/source/testgres.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,12 @@ testgres.node
5959
..automethod::__init__
6060

6161
..autoclass::testgres.node.ProcessProxy
62-
:members:
62+
:members:
63+
64+
testgres.standby
65+
----------------
66+
67+
..automodule::testgres.standby
68+
:members:
69+
:undoc-members:
70+
:show-inheritance:

‎testgres/node.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
importsubprocess
77
importtime
88

9+
fromcollectionsimportIterable
910
fromshutilimportrmtree
1011
fromsiximportraise_from,iteritems
1112
fromtempfileimportmkstemp,mkdtemp
@@ -62,6 +63,8 @@
6263

6364
from .loggerimportTestgresLogger
6465

66+
from .standbyimportFirst
67+
6568
from .utilsimport \
6669
eprint, \
6770
get_bin_path, \
@@ -656,7 +659,7 @@ def restart(self, params=[]):
656659

657660
defreload(self,params=[]):
658661
"""
659-
Reload config files using pg_ctl.
662+
Asynchronously reload config files using pg_ctl.
660663
661664
Args:
662665
params: additional arguments for pg_ctl.
@@ -1022,6 +1025,33 @@ def replicate(self, name=None, slot=None, **kwargs):
10221025
withclean_on_error(self.backup(**kwargs))asbackup:
10231026
returnbackup.spawn_replica(name=name,destroy=True,slot=slot)
10241027

1028+
defset_synchronous_standbys(self,standbys):
1029+
"""
1030+
Set standby synchronization options. This corresponds to
1031+
`synchronous_standby_names <https://www.postgresql.org/docs/current/static/runtime-config-replication.html#GUC-SYNCHRONOUS-STANDBY-NAMES>`_
1032+
option. Note that :meth:`~.PostgresNode.reload` or
1033+
:meth:`~.PostgresNode.restart` is needed for changes to take place.
1034+
1035+
Args:
1036+
standbys: either :class:`.First` or :class:`.Any` object specifying
1037+
sychronization parameters. It is also possible to pass simply
1038+
a list of replicas which would be equivalent to passing
1039+
``First(1, <list>)``
1040+
1041+
Example::
1042+
1043+
master = get_new_node().init().start()
1044+
with master.replicate.start() as standby:
1045+
master.append_conf("synchronous_commit = remote_apply")
1046+
master.set_synchronous_standbys(First(1, [standby]))
1047+
master.restart()
1048+
1049+
"""
1050+
ifisinstance(standbys,Iterable):
1051+
standbys=First(1,standbys)
1052+
1053+
self.append_conf("synchronous_standby_names = '{}'".format(standbys))
1054+
10251055
defcatchup(self,dbname=None,username=None):
10261056
"""
10271057
Wait until async replica catches up with its master.

‎testgres/standby.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# coding: utf-8
2+
3+
importsix
4+
5+
6+
@six.python_2_unicode_compatible
7+
classFirst:
8+
"""
9+
Specifies a priority-based synchronous replication and makes transaction
10+
commits wait until their WAL records are replicated to ``num_sync``
11+
synchronous standbys chosen based on their priorities.
12+
13+
Args:
14+
sync_num (int): the number of standbys that transaction need to wait
15+
for replies from
16+
standbys (:obj:`list` of :class:`.PostgresNode`): the list of standby
17+
nodes
18+
"""
19+
20+
def__init__(self,sync_num,standbys):
21+
self.sync_num=sync_num
22+
self.standbys=standbys
23+
24+
def__str__(self):
25+
returnu"{} ({})".format(self.sync_num,u", ".join(
26+
u"\"{}\"".format(r.name)forrinself.standbys))
27+
28+
29+
@six.python_2_unicode_compatible
30+
classAny:
31+
"""
32+
Specifies a quorum-based synchronous replication and makes transaction
33+
commits wait until their WAL records are replicated to at least ``num_sync``
34+
listed standbys. Only available for Postgres 10 and newer.
35+
36+
Args:
37+
sync_num (int): the number of standbys that transaction need to wait
38+
for replies from
39+
standbys (:obj:`list` of :class:`.PostgresNode`): the list of standby
40+
nodes
41+
"""
42+
43+
def__init__(self,sync_num,standbys):
44+
self.sync_num=sync_num
45+
self.standbys=standbys
46+
47+
def__str__(self):
48+
returnu"ANY {} ({})".format(self.sync_num,u", ".join(
49+
u"\"{}\"".format(r.name)forrinself.standbys))

‎tests/test_simple.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
fromtestgresimportbound_ports
4343
fromtestgres.utilsimportpg_version_ge
4444
fromtestgres.enumsimportProcessType
45+
fromtestgres.standbyimportFirst,Any
4546

4647

4748
defutil_exists(util):
@@ -402,6 +403,38 @@ def test_replicate(self):
402403
res=node.execute('select * from test')
403404
self.assertListEqual(res, [])
404405

406+
deftest_synchronous_replication(self):
407+
withget_new_node()asmaster:
408+
master.init(allow_streaming=True).start()
409+
master.append_conf('synchronous_commit = remote_apply')
410+
411+
# create standby
412+
withmaster.replicate()asstandby1,master.replicate()asstandby2:
413+
standby1.start()
414+
standby2.start()
415+
416+
# check formatting
417+
self.assertEqual('1 ("{}", "{}")'.format(
418+
standby1.name,standby2.name),
419+
str(First(1, (standby1,standby2))))
420+
self.assertEqual('ANY 1 ("{}", "{}")'.format(
421+
standby1.name,standby2.name),
422+
str(Any(1, (standby1,standby2))))
423+
424+
# set synchronous_standby_names
425+
master.set_synchronous_standbys([standby1,standby2])
426+
master.restart()
427+
master.safe_psql('create table abc(a int)')
428+
429+
# Create a large transaction that will take some time to apply
430+
# on standby to check that it applies synchronously
431+
# (If set synchronous_commit to 'on' or other lower level then
432+
# standby most likely won't catchup so fast and test will fail)
433+
master.safe_psql(
434+
'insert into abc select generate_series(1, 1000000)')
435+
res=standby1.safe_psql('select count(*) from abc')
436+
self.assertEqual(res,b'1000000\n')
437+
405438
deftest_replication_slots(self):
406439
withget_new_node()asnode:
407440
node.init(allow_streaming=True).start()

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp