``psycopg`` release notes
=========================
+Python 3.2.6 (unreleased)
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- Fix connection semantic when using ``target_session_attrs=prefer-standby``
+ (:ticket:`#1021`).
+
+
Current release
---------------
"""
last_exc = None
attempts = []
+ if prefer_standby := (
+ get_param(params, "target_session_attrs") == "prefer-standby"
+ ):
+ params = {k: v for k, v in params.items() if k != "target_session_attrs"}
+
for attempt in split_attempts(params):
try:
attempts.extend(_resolve_hostnames(attempt))
if get_param(params, "load_balance_hosts") == "random":
shuffle(attempts)
+ # Order matters: first try all the load-balanced host in standby mode,
+ # then allow primary
+ if prefer_standby:
+ attempts = [
+ {**a, "target_session_attrs": "standby"} for a in attempts
+ ] + attempts
+
return attempts
"""
last_exc = None
attempts = []
+ if prefer_standby := get_param(params, "target_session_attrs") == "prefer-standby":
+ params = {k: v for k, v in params.items() if k != "target_session_attrs"}
+
for attempt in split_attempts(params):
try:
attempts.extend(await _resolve_hostnames(attempt))
if get_param(params, "load_balance_hosts") == "random":
shuffle(attempts)
+ # Order matters: first try all the load-balanced host in standby mode,
+ # then allow primary
+ if prefer_standby:
+ attempts = [
+ {**a, "target_session_attrs": "standby"} for a in attempts
+ ] + attempts
+
return attempts
# This check is here to monitor if the behaviour on Window chamge.
# Rreceiving the same exception of other platform will be acceptable.
assert type(ex.value) is want_ex
+
+
+# NOTE: these "tsa" tests assume that the database we use for tests is a primary.
+
+
+@pytest.mark.parametrize("mode", ["any", "read-write", "primary", "prefer-standby"])
+def test_connect_tsa(conn_cls, dsn, mode):
+ params = conninfo_to_dict(dsn, target_session_attrs=mode)
+ with conn_cls.connect(**params) as conn:
+ assert conn.pgconn.status == pq.ConnStatus.OK
+
+
+@pytest.mark.parametrize("mode", ["read-only", "standby", "nosuchmode"])
+def test_connect_tsa_bad(conn_cls, dsn, mode):
+ params = conninfo_to_dict(dsn, target_session_attrs=mode)
+ with pytest.raises(psycopg.OperationalError, match=mode):
+ conn_cls.connect(**params)
# This check is here to monitor if the behaviour on Window chamge.
# Rreceiving the same exception of other platform will be acceptable.
assert type(ex.value) is want_ex
+
+
+# NOTE: these "tsa" tests assume that the database we use for tests is a primary.
+
+
+@pytest.mark.parametrize("mode", ["any", "read-write", "primary", "prefer-standby"])
+async def test_connect_tsa(aconn_cls, dsn, mode):
+ params = conninfo_to_dict(dsn, target_session_attrs=mode)
+ async with await aconn_cls.connect(**params) as aconn:
+ assert aconn.pgconn.status == pq.ConnStatus.OK
+
+
+@pytest.mark.parametrize("mode", ["read-only", "standby", "nosuchmode"])
+async def test_connect_tsa_bad(aconn_cls, dsn, mode):
+ params = conninfo_to_dict(dsn, target_session_attrs=mode)
+ with pytest.raises(psycopg.OperationalError, match=mode):
+ await aconn_cls.connect(**params)
],
None,
),
+ (
+ "host=1.1.1.1,2.2.2.2 target_session_attrs=prefer-standby",
+ [
+ "host=1.1.1.1 hostaddr=1.1.1.1 target_session_attrs=standby",
+ "host=2.2.2.2 hostaddr=2.2.2.2 target_session_attrs=standby",
+ "host=1.1.1.1 hostaddr=1.1.1.1",
+ "host=2.2.2.2 hostaddr=2.2.2.2",
+ ],
+ None,
+ ),
(
"port=5432",
[
["host=dup.com hostaddr=3.3.3.3", "host=dup.com hostaddr=3.3.3.4"],
None,
),
+ (
+ "host=dup.com target_session_attrs=prefer-standby",
+ [
+ "host=dup.com hostaddr=3.3.3.3 target_session_attrs=standby",
+ "host=dup.com hostaddr=3.3.3.4 target_session_attrs=standby",
+ "host=dup.com hostaddr=3.3.3.3",
+ "host=dup.com hostaddr=3.3.3.4",
+ ],
+ None,
+ ),
],
)
def test_conninfo_attempts(conninfo, want, env, fake_resolve):
],
None,
),
+ (
+ "host=1.1.1.1,2.2.2.2 target_session_attrs=prefer-standby",
+ [
+ "host=1.1.1.1 hostaddr=1.1.1.1 target_session_attrs=standby",
+ "host=2.2.2.2 hostaddr=2.2.2.2 target_session_attrs=standby",
+ "host=1.1.1.1 hostaddr=1.1.1.1",
+ "host=2.2.2.2 hostaddr=2.2.2.2",
+ ],
+ None,
+ ),
(
"port=5432",
[
["host=dup.com hostaddr=3.3.3.3", "host=dup.com hostaddr=3.3.3.4"],
None,
),
+ (
+ "host=dup.com target_session_attrs=prefer-standby",
+ [
+ "host=dup.com hostaddr=3.3.3.3 target_session_attrs=standby",
+ "host=dup.com hostaddr=3.3.3.4 target_session_attrs=standby",
+ "host=dup.com hostaddr=3.3.3.3",
+ "host=dup.com hostaddr=3.3.3.4",
+ ],
+ None,
+ ),
],
)
async def test_conninfo_attempts(conninfo, want, env, fake_resolve):