Skip to content

fix(core): Adjust connection timeout and retry logic - #12

Closed
ceache wants to merge 8 commits into
masterfrom
feature/connection-retry
Closed

ceache wants to merge 8 commits into
masterfrom
feature/connection-retry

Conversation

@ceache

@ceache ceache commented Sep 10, 2026

Copy link
Copy Markdown
Owner

Fixes python-zk#685

Why is this needed?

Previously, ConnectionHandler._connect() set the TCP socket connect timeout to client._session_timeout / 1000.0 (which defaults to 10 seconds, but can be up to 40 seconds).

If any member of the ZooKeeper ensemble was unresponsive or dropped packets without sending a TCP RST (e.g. host crash, blackholed IP, firewall drop, network partition), the client would block for the entire session timeout on that single host. In a multi-node ensemble, cycling through unreachable hosts could take 10+ seconds, causing active ZooKeeper sessions on the remaining healthy ensemble members to prematurely expire before reconnection could succeed.

Proposed Changes

  • Decouple TCP Connect Timeout from Session Timeout:
    In kazoo.protocol.connection.ConnectionHandler._connect_attempt(), pass timeout=retry.cur_delay to self._connect() instead of client._session_timeout / 1000.0.
  • Expose cur_delay Property in KazooRetry:
    Added typed @property def cur_delay(self) -> float returning self._cur_delay.
  • Fast Failover with Exponential Backoff:
    Initial connection attempts cycle through all ensemble members quickly using the initial retry delay (default 0.1s), escalating with exponential backoff on subsequent passes (0.2s, 0.4s, 0.8s... up to max_delay).
  • Preserve Full Quorum Negotiation Timeout:
    Once the TCP socket is connected, self._invoke(client._session_timeout / 1000.0 / len(client.hosts), connect) remains unchanged, ensuring the ZooKeeper server has adequate quorum negotiation time to process and commit session registration.
  • Reset on Connection Success:
    retry.reset() on successful connection resets _cur_delay to initial delay (0.1s), ensuring subsequent reconnections begin with fast failover cycles.
  • Unit Testing:
    Added kazoo/tests/unit/test_cnx_retry.py to verify that create_connection is called with the initial timeout across all hosts on the first pass, and escalates to max_delay across subsequent retry passes.
  • Rebase & Modernization:
    Rebased cleanly on top of feature/docker-compose-tests (8cb597a), adding modern typing (timeout: float) and SNI parameters (hostname, check_hostname).

Does this PR introduce any breaking change?

No breaking API changes. The connection retry logic is internal and more responsive to unreachable ensemble members.

…ure kazoo.testing package

- Replace legacy ZookeeperCluster process driver with testcontainers 4.x using base+overlay compose layouts (docker-compose.base.yml).
- Add auth matrix overlays for digest, sasl-digest, tls, and sasl-gssapi with certgen and alpine KDC sidecars.
- Scaffold docker-compose.capture.yml feature overlay and tshark sidecar for pcapng network packet capture, splitting ensemble into netns-holder + service pairs.
- Emit TLS keylog files and context certificates from tls-secrets-agent for Wireshark/pcapng TLS decryption.
- Restructure kazoo.testing package into kazoo.testing.common (core logic, helpers) and kazoo.testing.fixtures (pytest plugins), retiring harness.py.
- Move compose overlays, JAAS configs, and Dockerfile resources into kazoo.testing package using importlib.resources.
- Migrate integration tests off KazooTestCase to zkclient/zkensemble pytest fixtures and retire legacy root compose files.
- Add registered pytest markers (zk_version, zk_auth, zk_features) with collection-time evaluation and skip reasons.
- Introduce ZK axis enums (backports.strenum / enum.StrEnum) and bump default ZK version to 3.9.5.
- Add contract & unit tests reaching 93%+ coverage on kazoo.testing pure helpers and subprocess functions.
- Optimize GitHub Actions workflows with test matrices, docker layer caching, and Windows WSL2 runner support.
Do not use the session timeout as connection timeout.
This value is too large and results in a bad non-responsive server
holding up the client long enough for the session to timeout.

Use the KazooRetry object to use an increasing backoff timeout and cycle
over all servers quickly, working around bad servers with minimal
impact.
@ceache
ceache force-pushed the feature/connection-retry branch from d24a2bd to 26311a9 Compare September 19, 2026 02:28
@ceache ceache closed this Sep 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant