summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kafka/client_async.py38
-rw-r--r--test/test_client_async.py34
2 files changed, 43 insertions, 29 deletions
diff --git a/kafka/client_async.py b/kafka/client_async.py
index 64233f8..3dee2e1 100644
--- a/kafka/client_async.py
+++ b/kafka/client_async.py
@@ -1,6 +1,7 @@
from __future__ import absolute_import
import copy
+import functools
import heapq
import itertools
import logging
@@ -152,6 +153,22 @@ class KafkaClient(object):
conn = self._conns[node_id]
return conn.state is ConnectionStates.DISCONNECTED and not conn.blacked_out()
+ def _conn_state_change(self, node_id, conn):
+ if conn.connecting():
+ self._connecting.add(node_id)
+
+ elif conn.connected():
+ log.debug("Node %s connected", node_id)
+ if node_id in self._connecting:
+ self._connecting.remove(node_id)
+
+ # Connection failures imply that our metadata is stale, so let's refresh
+ elif conn.state is ConnectionStates.DISCONNECTING:
+ log.warning("Node %s connect failed -- refreshing metadata", node_id)
+ if node_id in self._connecting:
+ self._connecting.remove(node_id)
+ self.cluster.request_update()
+
def _maybe_connect(self, node_id):
"""Idempotent non-blocking connection attempt to the given node id."""
if node_id not in self._conns:
@@ -160,32 +177,15 @@ class KafkaClient(object):
log.debug("Initiating connection to node %s at %s:%s",
node_id, broker.host, broker.port)
-
host, port, afi = get_ip_port_afi(broker.host)
+ cb = functools.partial(self._conn_state_change, node_id)
self._conns[node_id] = BrokerConnection(host, broker.port, afi,
+ state_change_callback=cb,
**self.config)
conn = self._conns[node_id]
if conn.connected():
return True
-
conn.connect()
-
- if conn.connecting():
- if node_id not in self._connecting:
- self._connecting.add(node_id)
-
- # Whether CONNECTED or DISCONNECTED, we need to remove from connecting
- elif node_id in self._connecting:
- self._connecting.remove(node_id)
-
- if conn.connected():
- log.debug("Node %s connected", node_id)
-
- # Connection failures imply that our metadata is stale, so let's refresh
- elif conn.disconnected():
- log.warning("Node %s connect failed -- refreshing metadata", node_id)
- self.cluster.request_update()
-
return conn.connected()
def ready(self, node_id):
diff --git a/test/test_client_async.py b/test/test_client_async.py
index 6da5394..ae8549d 100644
--- a/test/test_client_async.py
+++ b/test/test_client_async.py
@@ -1,5 +1,5 @@
-import time
import socket
+import time
import pytest
@@ -83,26 +83,40 @@ def test_maybe_connect(conn):
else:
assert False, 'Exception not raised'
+ # New node_id creates a conn object
assert 0 not in cli._conns
conn.state = ConnectionStates.DISCONNECTED
conn.connect.side_effect = lambda: conn._set_conn_state(ConnectionStates.CONNECTING)
assert cli._maybe_connect(0) is False
assert cli._conns[0] is conn
- assert 0 in cli._connecting
- conn.connect.side_effect = lambda: conn._set_conn_state(ConnectionStates.CONNECTED)
- assert cli._maybe_connect(0) is True
- assert 0 not in cli._connecting
+
+def test_conn_state_change(mocker, conn):
+ cli = KafkaClient()
+
+ node_id = 0
+ conn.state = ConnectionStates.CONNECTING
+ cli._conn_state_change(node_id, conn)
+ assert node_id in cli._connecting
+
+ conn.state = ConnectionStates.CONNECTED
+ cli._conn_state_change(node_id, conn)
+ assert node_id not in cli._connecting
# Failure to connect should trigger metadata update
assert cli.cluster._need_update is False
- conn.state = ConnectionStates.CONNECTING
- cli._connecting.add(0)
- conn.connect.side_effect = lambda: conn._set_conn_state(ConnectionStates.DISCONNECTED)
- assert cli._maybe_connect(0) is False
- assert 0 not in cli._connecting
+ conn.state = ConnectionStates.DISCONNECTING
+ cli._conn_state_change(node_id, conn)
+ assert node_id not in cli._connecting
assert cli.cluster._need_update is True
+ conn.state = ConnectionStates.CONNECTING
+ cli._conn_state_change(node_id, conn)
+ assert node_id in cli._connecting
+ conn.state = ConnectionStates.DISCONNECTING
+ cli._conn_state_change(node_id, conn)
+ assert node_id not in cli._connecting
+
def test_ready(mocker, conn):
cli = KafkaClient()