Skip to content

Commit

Permalink
RmqCommunicator: add the server_properties property (#107)
Browse files Browse the repository at this point in the history
This exposes the server properties as returned by the RMQ server when
connecting to clients of the async and threaded RMQ communicators. This
is useful for, amongst other things, checking the server version to
ensure compatibility.
  • Loading branch information
muhrin authored Jan 17, 2022
1 parent c35668d commit c51695f
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 4 deletions.
29 changes: 28 additions & 1 deletion kiwipy/rmq/communicator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import copy
import logging
import typing
from typing import Union, Optional
from typing import Union, Optional, Dict

import shortuuid
import aio_pika
Expand Down Expand Up @@ -345,6 +345,33 @@ async def __aexit__(self, exc_type, exc_val, exc_tb):
def __str__(self):
return f'RMQCommunicator({self._connection})'

@property
def server_properties(self) -> Dict:
"""
A dictionary containing server properties as returned by the RMQ server at connection time.
The details are defined by the RMQ standard and can be found here:
https://www.rabbitmq.com/amqp-0-9-1-reference.html#connection.start.server-properties
The protocol states that this dictionary SHOULD contain at least:
'host' - specifying the server host name or address
'product' - giving the name of the server product
'version' - giving the name of the server version
'platform' - giving the name of the operating system
'copyright' - if appropriate, and,
'information' - giving other general information
.. note:: In testing it seems like 'host' is not always returned. Host information may be found in
'cluster_name' but clients shouldn't rely on this.
:return: the server properties dictionary
"""
if self._connection is None:
return {}

return self._connection.connection.server_properties

@property
def loop(self):
"""Get the event loop instance driving this communicator connection."""
Expand Down
26 changes: 25 additions & 1 deletion kiwipy/rmq/threadcomms.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from concurrent.futures import Future as ThreadFuture
import functools
import logging
from typing import Union
from typing import Union, Dict

import aio_pika
import deprecation
Expand Down Expand Up @@ -148,6 +148,30 @@ def start(self):
def stop(self):
self.close()

@property
def server_properties(self) -> Dict:
"""
A dictionary containing server properties as returned by the RMQ server at connection time.
The details are defined by the RMQ standard and can be found here:
https://www.rabbitmq.com/amqp-0-9-1-reference.html#connection.start.server-properties
The protocol states that this dictionary SHOULD contain at least:
'host' - specifying the server host name or address
'product' - giving the name of the server product
'version' - giving the name of the server version
'platform' - giving the name of the operating system
'copyright' - if appropriate, and,
'information' - giving other general information
.. note:: In testing it seems like 'host' is not always returned. Host information may be found in
'cluster_name' but clients shouldn't rely on this.
:return: the server properties dictionary
"""
return self._communicator.server_properties

def __enter__(self):
return self

Expand Down
10 changes: 10 additions & 0 deletions test/rmq/test_coroutine_communicator.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,13 @@ def broadcast_subscriber(_comm, _body, _sender=None, _subject=None, _correlation


# endregion


@pytest.mark.asyncio
async def test_server_properties(communicator: kiwipy.rmq.RmqCommunicator):
props = communicator.server_properties
assert isinstance(props, dict)

assert props['product'] == b'RabbitMQ'
assert 'version' in props
assert props['platform'].startswith(b'Erlang')
11 changes: 9 additions & 2 deletions test/rmq/test_rmq_thread_communicator.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,15 @@ def test_jupyter_notebook():
fixture.diff_color_words = False
fixture.diff_ignore = ('/metadata/language_info/version',)

# Express the path in a way that will work no matter where the tests are being ran and convert
# to str as py35 doesn't support Paths being passed to open()
my_dir = pathlib.Path(__file__).parent
with open(my_dir / pathlib.Path('notebooks/communicator.ipynb')) as handle:
fixture.check(handle)


def test_server_properties(thread_communicator: kiwipy.rmq.RmqThreadCommunicator):
props = thread_communicator.server_properties
assert isinstance(props, dict)

assert props['product'] == b'RabbitMQ'
assert 'version' in props
assert props['platform'].startswith(b'Erlang')

0 comments on commit c51695f

Please sign in to comment.