Skip to content

Commit 92c4ee9

Browse files
committed
Added optional support for HTTP connections using thriftpy2-httpx-client
Signed-off-by: Roger Aiudi <[email protected]>
1 parent 9ee29c1 commit 92c4ee9

File tree

6 files changed

+52
-4
lines changed

6 files changed

+52
-4
lines changed

aiohappybase/connection.py

+28-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@
2626
run_coro,
2727
)
2828

29+
try:
30+
from thriftpy2_httpx_client import make_aio_client as make_http_client
31+
except ImportError:
32+
async def make_http_client(*_, **__):
33+
raise RuntimeError("thriftpy2_httpx_client is required to"
34+
" use the HTTP client protocol.")
35+
2936
logger = logging.getLogger(__name__)
3037

3138
COMPAT_MODES = ('0.90', '0.92', '0.94', '0.96', '0.98')
@@ -35,6 +42,7 @@
3542
DEFAULT_COMPAT = os.environ.get('AIOHAPPYBASE_COMPAT', '0.98')
3643
DEFAULT_TRANSPORT = os.environ.get('AIOHAPPYBASE_TRANSPORT', 'buffered')
3744
DEFAULT_PROTOCOL = os.environ.get('AIOHAPPYBASE_PROTOCOL', 'binary')
45+
DEFAULT_CLIENT = os.environ.get('AIOHAPPYBASE_CLIENT', 'socket')
3846

3947

4048
class Connection:
@@ -88,6 +96,17 @@ class Connection:
8896
process as well. ``TBinaryProtocol`` is the default protocol that
8997
AIOHappyBase uses.
9098
99+
The optional `client` argument specifies the type of Thrift client
100+
to use. Supported values for this argument are ``socket``
101+
(the default) and ``http``. Make sure to choose the right one,
102+
since otherwise you might see non-obvious connection errors or
103+
program hangs when making a connection. To check which client
104+
you should use, refer to the ``hbase.regionserver.thrift.http``
105+
setting. If it is ``true`` use ``http``, otherwise use ``socket``.
106+
107+
.. versionadded:: v1.4.0
108+
`client` argument
109+
91110
.. versionadded:: 0.9
92111
`protocol` argument
93112
@@ -109,7 +128,10 @@ class Connection:
109128
binary=TAsyncBinaryProtocolFactory(decode_response=False),
110129
compact=TAsyncCompactProtocolFactory(decode_response=False),
111130
)
112-
THRIFT_CLIENT_FACTORY = staticmethod(make_client)
131+
THRIFT_CLIENTS = dict(
132+
socket=make_client,
133+
http=make_http_client,
134+
)
113135

114136
def __init__(self,
115137
host: str = DEFAULT_HOST,
@@ -121,6 +143,7 @@ def __init__(self,
121143
compat: str = DEFAULT_COMPAT,
122144
transport: str = DEFAULT_TRANSPORT,
123145
protocol: str = DEFAULT_PROTOCOL,
146+
client: str = DEFAULT_CLIENT,
124147
**client_kwargs: Any):
125148
"""
126149
:param host: The host to connect to
@@ -132,6 +155,7 @@ def __init__(self,
132155
:param compat: Compatibility mode (optional)
133156
:param transport: Thrift transport mode (optional)
134157
:param protocol: Thrift protocol mode (optional)
158+
:param client: Thrift client mode (optional)
135159
:param client_kwargs:
136160
Extra keyword arguments for `make_client()`. See the ThriftPy2
137161
documentation for more information.
@@ -149,6 +173,7 @@ def __init__(self,
149173
compat=(compat, COMPAT_MODES),
150174
transport=(transport, self.THRIFT_TRANSPORTS),
151175
protocol=(protocol, self.THRIFT_PROTOCOLS),
176+
client=(client, self.THRIFT_CLIENTS),
152177
)
153178

154179
# Allow host and port to be None, which may be easier for
@@ -162,6 +187,7 @@ def __init__(self,
162187

163188
self._transport_factory = self.THRIFT_TRANSPORTS[transport]
164189
self._protocol_factory = self.THRIFT_PROTOCOLS[protocol]
190+
self._client_factory = self.THRIFT_CLIENTS[client]
165191

166192
self.client_kwargs = {
167193
'service': Hbase,
@@ -196,7 +222,7 @@ async def open(self) -> None:
196222
return # _refresh_thrift_client opened the transport
197223

198224
logger.debug(f"Opening Thrift transport to {self.host}:{self.port}")
199-
self.client = await self.THRIFT_CLIENT_FACTORY(**self.client_kwargs)
225+
self.client = await self._client_factory(**self.client_kwargs)
200226

201227
def close(self) -> None:
202228
"""

aiohappybase/sync/connection.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@
1818

1919
logger = logging.getLogger(__name__)
2020

21+
try:
22+
from thriftpy2_httpx_client import make_sync_client as make_http_client
23+
except ImportError:
24+
async def make_http_client(*_, **__):
25+
raise RuntimeError("thriftpy2_httpx_client is required to"
26+
" use the HTTP client protocol.")
27+
2128

2229
@synchronize
2330
class Connection:
@@ -30,7 +37,10 @@ class Connection:
3037
binary=TBinaryProtocolFactory(decode_response=False),
3138
compact=TCompactProtocolFactory(decode_response=False),
3239
)
33-
THRIFT_CLIENT_FACTORY = staticmethod(make_client)
40+
THRIFT_CLIENTS = dict(
41+
socket=make_client,
42+
http=make_http_client,
43+
)
3444

3545
def _autoconnect(self):
3646
self.open()

doc/installation.rst

+8
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ fetch the package from the `Python Package Index <http://pypi.python.org/>`_
3737
--gen py`` on the ``.thrift`` file) is not necessary, since AIOHappyBase
3838
bundles pregenerated versions of those modules.
3939

40+
If you are going to be using AIOHappyBase to communicate with an HBase server
41+
that uses Thrift over HTTP, you will need to install the ``http`` extra as
42+
well:
43+
44+
::
45+
46+
(venv_name) $ pip install aiohappybase[http]
47+
4048

4149
Testing the installation
4250
========================

setup.cfg

+3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ py_modules =
3333
exclude =
3434
tests
3535

36+
[options.extras_require]
37+
http = thriftpy2-httpx-client
38+
3639
[coverage:run]
3740
source = .
3841
include = aiohappybase/*,tests/*

test-requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
-r requirements.txt
2+
thriftpy2-httpx-client
23
coverage
34
pytest
45
pytest-asyncio

tests/test_api.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ async def test_scan_reverse(self, table: Table):
552552

553553
if table.connection.compat < '0.98':
554554
with pytest.raises(NotImplementedError):
555-
await self._scan_list(reverse=True)
555+
await self._scan_list(table, reverse=True)
556556
return
557557

558558
async with table.batch() as b:

0 commit comments

Comments
 (0)