Esempio n. 1
0
def test_simplest_handler():
    sut = MessageBus()
    sut.add_handler(EmptyMessage, get_one)

    message = EmptyMessage()
    handling_result = sut.handle(message)
    assert handling_result == [1]
Esempio n. 2
0
def test_handlers_get_message():
    sut = MessageBus()
    sut.add_handler(EmptyMessage, identity_handler)

    message = EmptyMessage()
    handling_result = sut.handle(message)
    assert handling_result == [message]
Esempio n. 3
0
def test_multiple_handlers_for_single_message():
    sut = MessageBus()
    sut.add_handler(EmptyMessage, get_one)
    sut.add_handler(EmptyMessage, get_one)

    message = EmptyMessage()
    handling_result = sut.handle(message)
    assert handling_result == [1, 1]
Esempio n. 4
0
 def __init__(
     self,
     *,
     middlewares: t.List[api.Middleware] = None,
     allow_result: bool = True,
     locking: bool = True,
 ) -> None:
     self._messagebus = MessageBus(middlewares=middlewares)
     self._allow_result = bool(allow_result)
     self._locking = bool(locking)
     self._is_processing_a_message = False
Esempio n. 5
0
def test_multiple_handlers_for_single_message_triggered_in_correct_order():
    sut = MessageBus()
    sut.add_handler(EmptyMessage, get_one)
    sut.add_handler(EmptyMessage, get_two)
    sut.add_handler(EmptyMessage, get_three)

    message = EmptyMessage()
    handling_result = sut.handle(message)
    assert handling_result == [1, 2, 3]
Esempio n. 6
0
def test_multiple_handlers_correctly_triggered():
    sut = MessageBus()
    sut.add_handler(MessageClassOne, get_one)
    sut.add_handler(MessageClassOne, get_two)
    sut.add_handler(MessageClassTwo, get_three)

    message_one = MessageClassOne()
    handling_result_one = sut.handle(message_one)
    assert handling_result_one == [1, 2]

    message_two = MessageClassTwo()
    handling_result_two = sut.handle(message_two)
    assert handling_result_two == [3]
Esempio n. 7
0
def test_handler_is_triggered_each_time():
    counter = 0

    def handler(msg):
        nonlocal counter
        counter += 1
        return counter

    sut = MessageBus()
    sut.add_handler(EmptyMessage, handler)

    message = EmptyMessage()
    handling_result = sut.handle(message)
    assert handling_result == [1]
    handling_result = sut.handle(message)
    assert handling_result == [2]
Esempio n. 8
0
class CommandBus(api.CommandBus):
    def __init__(
        self,
        *,
        middlewares: t.List[api.Middleware] = None,
        allow_result: bool = True,
        locking: bool = True,
    ) -> None:
        self._messagebus = MessageBus(middlewares=middlewares)
        self._allow_result = bool(allow_result)
        self._locking = bool(locking)
        self._is_processing_a_message = False

    def add_handler(self, message_class: type,
                    message_handler: t.Callable) -> None:
        if self._messagebus.has_handler_for(message_class):
            raise api.CommandHandlerAlreadyRegisteredForAType(
                f"A command handler is already registed for message class '{message_class}'."
            )
        self._messagebus.add_handler(message_class, message_handler)

    def handle(self, message: object) -> t.Any:
        if not self._messagebus.has_handler_for(message.__class__):
            raise api.CommandHandlerNotFound(
                f"No command handler is registered for message class '{message.__class__}'."
            )
        if self._locking and self._is_processing_a_message:
            raise api.CommandBusAlreadyProcessingAMessage(
                f"CommandBus already processing a message when received a '{message.__class__}' one."  # pylint: disable=line-too-long
            )
        self._is_processing_a_message = True
        result = self._messagebus.handle(message)
        self._is_processing_a_message = False
        return result[0] if self._allow_result else None

    def has_handler_for(self, message_class: type) -> bool:
        return self._messagebus.has_handler_for(message_class)
Esempio n. 9
0
def test_simplest_handler_can_have_no_handlers_for_a_message():
    sut = MessageBus()

    message = EmptyMessage()
    handling_result = sut.handle(message)
    assert handling_result == []
Esempio n. 10
0
def test_handler_handler_must_be_a_callable():
    sut = MessageBus()

    not_a_callable = 2
    with pytest.raises(api.MessageHandlerMappingRequiresACallable):
        sut.add_handler(EmptyMessage, not_a_callable)
Esempio n. 11
0
def test_handler_message_must_be_a_type():
    sut = MessageBus()

    not_a_type = EmptyMessage()
    with pytest.raises(api.MessageHandlerMappingRequiresAType):
        sut.add_handler(not_a_type, get_one)
Esempio n. 12
0
def test_has_handler_for():
    sut = MessageBus()
    sut.add_handler(MessageClassOne, get_one)

    assert sut.has_handler_for(MessageClassOne) is True
    assert sut.has_handler_for(MessageClassTwo) is False
Esempio n. 13
0
def test_middlewares():
    class MessageWithList(t.NamedTuple):
        payload: t.List[str]

    def middleware_one(message: MessageWithList, next: api.CallNextMiddleware):
        message.payload.append(
            "middleware one: does something before the handler")
        result = next(message)
        message.payload.append(
            "middleware one: does something after the handler")
        return result

    def middleware_two(message: MessageWithList, next: api.CallNextMiddleware):
        message.payload.append(
            "middleware two: does something before the handler")
        result = next(message)
        message.payload.append(
            "middleware two: does something after the handler")
        return result

    def handler_one(message: MessageWithList):
        message.payload.append("handler one does something")
        return "handler one result"

    def handler_two(message: MessageWithList):
        message.payload.append("handler two does something")
        return "handler two result"

    # 1. Simplest test: one handler, one middleware
    sut1 = MessageBus(middlewares=[middleware_one])
    sut1.add_handler(MessageWithList, handler_one)

    message1 = MessageWithList(payload=[])
    result1 = sut1.handle(message1)
    assert result1 == ["handler one result"]
    assert message1.payload == [
        "middleware one: does something before the handler",
        "handler one does something",
        "middleware one: does something after the handler",
    ]

    # 2. Next step: one handler, multiple middlewares
    sut2 = MessageBus(middlewares=[middleware_one, middleware_two])
    sut2.add_handler(MessageWithList, handler_one)

    message2 = MessageWithList(payload=[])
    result2 = sut2.handle(message2)
    assert result2 == ["handler one result"]
    assert message2.payload == [
        "middleware one: does something before the handler",
        "middleware two: does something before the handler",
        "handler one does something",
        "middleware two: does something after the handler",
        "middleware one: does something after the handler",
    ]

    # 3. Ultimate step: multiple handlers, multiple middlewares
    sut3 = MessageBus(middlewares=[middleware_one, middleware_two])
    sut3.add_handler(MessageWithList, handler_one)
    sut3.add_handler(MessageWithList, handler_two)

    message3 = MessageWithList(payload=["initial message payload"])
    result3 = sut3.handle(message3)
    assert result3 == ["handler one result", "handler two result"]
    assert message3.payload == [
        "initial message payload",
        "middleware one: does something before the handler",
        "middleware two: does something before the handler",
        "handler one does something",
        "handler two does something",
        "middleware two: does something after the handler",
        "middleware one: does something after the handler",
    ]
Esempio n. 14
0
import typing as t

from pymessagebus._messagebus import MessageBus

_DEFAULT_MESSAGE_BUS = MessageBus()


# Public API:
# This is our handy decorator:
def register_handler(message_class: type):
    def decorator(handler: t.Callable):
        _DEFAULT_MESSAGE_BUS.add_handler(message_class, handler)
        return handler

    return decorator


# And those are aliases to our "default" singleton instance:
# pylint: disable=invalid-name
add_handler = _DEFAULT_MESSAGE_BUS.add_handler
handle = _DEFAULT_MESSAGE_BUS.handle
has_handler_for = _DEFAULT_MESSAGE_BUS.has_handler_for