`~zoneinfo.ZoneInfo` (ambiguous offset, see :ticket:`#652`).
- Handle gracefully EINTR on signals instead of raising `InterruptedError`,
consistently with :pep:`475` guideline (:ticket:`#667`).
-- Fix support for connection strings with multiple hosts (:ticket:`#674`).
+- Fix support for connection strings with multiple hosts/ports and for the
+ ``load_balance_hosts`` connection parameter (:ticket:`#674`).
Current release
import socket
import asyncio
from typing import Any, Iterator, AsyncIterator
+from random import shuffle
from pathlib import Path
from datetime import tzinfo
from functools import lru_cache
Because the libpq async function doesn't honour the timeout, we need to
reimplement the repeated attempts.
"""
- for attempt in _split_attempts(_inject_defaults(params)):
- yield attempt
+ if params.get("load_balance_hosts", "disable") == "random":
+ attempts = list(_split_attempts(_inject_defaults(params)))
+ shuffle(attempts)
+ for attempt in attempts:
+ yield attempt
+ else:
+ for attempt in _split_attempts(_inject_defaults(params)):
+ yield attempt
async def conninfo_attempts_async(params: ConnDict) -> AsyncIterator[ConnDict]:
list(conninfo_attempts(params))
+def test_conninfo_random(dsn, conn_cls):
+ hosts = [f"host{n:02d}" for n in range(50)]
+ args = {"host": ",".join(hosts)}
+ ahosts = [att["host"] for att in conninfo_attempts(args)]
+ assert ahosts == hosts
+
+ args["load_balance_hosts"] = "disable"
+ ahosts = [att["host"] for att in conninfo_attempts(args)]
+ assert ahosts == hosts
+
+ args["load_balance_hosts"] = "random"
+ ahosts = [att["host"] for att in conninfo_attempts(args)]
+ assert ahosts != hosts
+ ahosts.sort()
+ assert ahosts == hosts
+
+
@pytest.fixture
async def fake_resolve(monkeypatch):
fake_hosts = {