Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions docs/apidoc/modules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,8 @@ driving the protocol layer directly from the REPL.
- :mod:`~kafka.net.connection` - per-broker async
connection: state machine, request/response correlation, and SASL
handshake.
- :mod:`~kafka.net.transport` - Async socket I/O with write buffering,
- :mod:`~kafka.net.backend.transport` - Async socket I/O with write buffering,
pause/resume hooks, and the asyncio-shaped protocol callback surface.
- :mod:`~kafka.net.inet` - DNS lookup + non-blocking connect, plus a
URL-scheme registry that resolves ``proxy_url`` to socket factories.
- :mod:`~kafka.net.http_connect` - Tunnels broker connections through
an HTTP CONNECT proxy (RFC 7231).
- :mod:`~kafka.net.socks5` - SOCKS5 client with optional username/password
Expand All @@ -108,8 +106,7 @@ driving the protocol layer directly from the REPL.

manager <net/manager>
connection <net/connection>
transport <net/transport>
inet <net/inet>
transport <net/backend/transport>
http_connect <net/http_connect>
socks5 <net/socks5>

Expand Down
File renamed without changes.
10 changes: 0 additions & 10 deletions docs/apidoc/net/inet.rst

This file was deleted.

2 changes: 1 addition & 1 deletion kafka/future.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class Future:
``is_done`` / ``value`` / ``exception`` state) and is safe to resolve from
any thread. It is deliberately **not** awaitable: awaiting happens only on
the event loop, via the backend's loop-awaitable future from
``net.create_future()`` (``kafka.net.selector.SelectorFuture`` for the
``net.create_future()`` (``kafka.net.backend.selector.SelectorFuture`` for the
selector), which subclasses ``Future`` and adds ``__await__``. Keeping
``__await__`` off the base makes the invariant type-enforced -- awaiting a
plain handoff ``Future`` raises immediately rather than silently working on
Expand Down
9 changes: 3 additions & 6 deletions kafka/net/__init__.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
from .connection import KafkaConnection
from .inet import create_connection, KafkaNetSocket
from .manager import KafkaConnectionManager
from .metrics import KafkaConnectionMetrics, KafkaManagerMetrics
from .selector import NetworkSelector
from .http_connect import HttpConnectProxy
from .socks5 import Socks5Proxy
from .transport import KafkaTCPTransport, KafkaSSLTransport
from .wakeup_notifier import WakeupNotifier

from .compat import KafkaNetClient


__all__ = [
'KafkaConnection', 'create_connection', 'KafkaNetSocket',
'KafkaConnectionManager', 'KafkaConnectionMetrics', 'KafkaManagerMetrics',
'NetworkSelector', 'HttpConnectProxy', 'Socks5Proxy', 'KafkaTCPTransport', 'KafkaSSLTransport',
'KafkaConnection', 'KafkaConnectionManager',
'KafkaConnectionMetrics', 'KafkaManagerMetrics',
'HttpConnectProxy', 'Socks5Proxy',
'WakeupNotifier', 'KafkaNetClient',
]
7 changes: 7 additions & 0 deletions kafka/net/backend/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from .abstract import (
NetBackend, NetTransport, NetProtocol, NetBackendFuture,
resolve_backend, register_backend_lazy,
)

register_backend_lazy('selector', 'kafka.net.backend.selector', 'NetworkSelector')
register_backend_lazy('asyncio', 'kafka.net.backend.asyncio_backend', 'AsyncioBackend')
14 changes: 5 additions & 9 deletions kafka/net/backend.py → kafka/net/backend/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
``KafkaAdminClient`` (and the manager, cluster, connection, coordinator,
fetcher, sender) reach for through ``self._net`` / ``manager._net``.

``NetworkSelector`` (``kafka/net/selector.py``) is the reference
``NetworkSelector`` (``kafka/net/backend/selector.py``) is the reference
implementation; an asyncio backend (and eventually Twisted) implements the
same surface so it can be swapped in via ``net=`` without touching core code.

The :class:`NetBackendFuture` contract is the surface of the
loop-awaitable futures a backend hands out from ``net.create_future()``. The
selector's implementation is ``kafka.net.selector.SelectorFuture``; an asyncio
selector's implementation is ``kafka.net.backend.selector.SelectorFuture``; an asyncio
(and eventually Twisted) backend supplies its own.

Networking is a **connection seam**, not fd-readiness. asyncio and Twisted own
Expand All @@ -27,7 +27,7 @@

* ``wait_read`` / ``wait_write`` / ``unregister_event`` -- the low-level
fd-readiness primitives. They are the *selector's* private mechanism (used
only inside ``kafka/net/transport.py`` + ``inet.py``, zero core callers) and
only inside ``kafka/net/backend/transport.py`` + ``inet.py``, zero core callers) and
do not port to asyncio/Twisted. The connection seam replaces them.
* ``poll(timeout_ms, future=...)`` -- the legacy single-tick driver. Its only
remaining caller is the ``KafkaNetClient`` compat shim
Expand All @@ -54,7 +54,7 @@
class NetBackendFuture(Protocol):
"""Contract for the awaitable futures returned by ``net.create_future()``.

A pluggable async backend (the kafka.net selector, asyncio, Twisted, ...)
A pluggable async backend (the kafka.net.backend selector, asyncio, Twisted, ...)
returns its own future type from ``create_future()``. Core loop coroutines
touch it only through this surface, so the type is interchangeable across
backends. The selector's ``SelectorFuture`` is the reference implementation:
Expand Down Expand Up @@ -235,7 +235,7 @@ def wakeup(self) -> None:
# --- backend selection ----------------------------------------------------

# name -> factory(**config) -> NetBackend. Populated by register_backend();
# 'selector' is always available, 'asyncio' registers itself in Step 4.
# 'selector' and 'asyncio' are lazily registered in kafka/net/backend/__init__.py.
_BACKENDS = {}


Expand Down Expand Up @@ -307,7 +307,3 @@ def resolve_backend(net, config):
if name is None or name not in _BACKENDS:
name = 'selector'
return _BACKENDS[name](**config)


register_backend_lazy('selector', 'kafka.net.selector', 'NetworkSelector')
register_backend_lazy('asyncio', 'kafka.net.asyncio_backend', 'AsyncioBackend')
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions kafka/net/selector.py → kafka/net/backend/selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

import kafka.errors as Errors
from kafka.future import Future
from kafka.net.inet import create_connection as _inet_create_connection
from kafka.net.transport import KafkaSSLTransport, KafkaTCPTransport
from kafka.net.backend.inet import create_connection as _inet_create_connection
from kafka.net.backend.transport import KafkaSSLTransport, KafkaTCPTransport
from kafka.version import __version__


Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion kafka/net/http_connect.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from urllib.parse import urlparse

from kafka.errors import KafkaConnectionError
from kafka.net.inet import KafkaNetSocket
from kafka.net.backend.inet import KafkaNetSocket


log = logging.getLogger(__name__)
Expand Down
2 changes: 1 addition & 1 deletion kafka/net/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from kafka.net.backend import resolve_backend
from kafka.cluster import ClusterMetadata
import kafka.errors as Errors
from kafka.net.transport import KafkaSSLTransport
from kafka.net.backend.transport import KafkaSSLTransport
from kafka.net.wakeup_notifier import WakeupNotifier
from kafka.protocol.broker_version_data import BrokerVersionData
from kafka.version import __version__
Expand Down
2 changes: 1 addition & 1 deletion kafka/net/socks5.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from urllib.parse import urlparse

from kafka.errors import KafkaConnectionError
from kafka.net.inet import KafkaNetSocket
from kafka.net.backend.inet import KafkaNetSocket


log = logging.getLogger(__name__)
Expand Down
2 changes: 1 addition & 1 deletion test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from kafka.cluster import ClusterMetadata
from kafka.net.compat import KafkaNetClient
from kafka.net.manager import KafkaConnectionManager
from kafka.net.selector import NetworkSelector
from kafka.net.backend.selector import NetworkSelector
from kafka.protocol.metadata import MetadataResponse


Expand Down
14 changes: 7 additions & 7 deletions test/net/test_backend.py → test/net/backend/test_abstract.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Conformance tests for the NetBackend contract (kafka/net/backend.py).
"""Conformance tests for the NetBackend contract (kafka/net/backend/abstract.py).

NetworkSelector is the reference implementation; these pin that it satisfies
the NetBackend Protocol structurally and that the shared lifecycle helper
Expand All @@ -10,11 +10,11 @@

import pytest

from kafka.net.backend import (
from kafka.net.backend.abstract import (
NetBackend, NetTransport, resolve_backend, register_backend, _BACKENDS,
)
from kafka.net.selector import NetworkSelector
from kafka.net.transport import KafkaTCPTransport
from kafka.net.backend.selector import NetworkSelector
from kafka.net.backend.transport import KafkaTCPTransport


# The full contract surface, kept here so a missing/renamed method fails loudly.
Expand Down Expand Up @@ -120,7 +120,7 @@ def test_unknown_name_raises(self):

def test_asyncio_name_resolves(self):
# net='asyncio' lazily imports + registers the asyncio backend.
from kafka.net.asyncio_backend import AsyncioBackend
from kafka.net.backend.asyncio_backend import AsyncioBackend
b = resolve_backend('asyncio', {'client_id': 'x'})
assert isinstance(b, AsyncioBackend)
b.close()
Expand Down Expand Up @@ -156,7 +156,7 @@ async def main():
def test_autodetect_asyncio_in_loop_returns_asyncio_backend(self):
# In a running asyncio loop with no explicit net, auto-detect lazily
# registers + selects the asyncio backend (Phase-1: still own thread).
from kafka.net.asyncio_backend import AsyncioBackend
from kafka.net.backend.asyncio_backend import AsyncioBackend

async def main():
return resolve_backend(None, {'client_id': 'auto'})
Expand All @@ -168,7 +168,7 @@ async def main():
def test_autodetect_falls_back_for_unknown_framework(self, monkeypatch):
# A detected-but-unregistered framework (e.g. trio, no backend) falls
# back to the default selector rather than erroring.
import kafka.net.backend as backend_mod
import kafka.net.backend.abstract as backend_mod
monkeypatch.setattr(backend_mod, '_detect_async_library', lambda: 'trio')
assert isinstance(resolve_backend(None, {}), NetworkSelector)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"""Tests for the asyncio NetBackend (kafka/net/asyncio_backend.py).
"""Tests for the asyncio NetBackend (kafka/net/backend/asyncio_backend.py).

Covers backend-specific behavior (lifecycle, timers, cross-thread run), reuses
the shared NetBackendFuture conformance suite against the asyncio-backed future,
and drives a real protocol round-trip through a MockBroker on a started
AsyncioBackend -- the both-backends coverage for the async paths.
AsyncioBackend -- the both-backend coverage for the async paths.
"""
import asyncio
import socket
Expand All @@ -13,12 +13,12 @@
import pytest

import kafka.errors as Errors
from kafka.net.asyncio_backend import AsyncioBackend, AsyncioFuture
from kafka.net.backend import NetBackend
from kafka.net.backend.asyncio_backend import AsyncioBackend, AsyncioFuture
from kafka.net.manager import KafkaConnectionManager
from kafka.protocol.metadata import MetadataRequest
from test.mock_broker import MockBroker
from test.net.test_net_backend_future import NetBackendFutureContract
from test.net.backend.test_net_backend_future import NetBackendFutureContract


@pytest.fixture
Expand Down
Loading