def test_should_publish_consume_and_retry_from_store_queue_from_rabbitmq( max_retries_allowed, expected_number_event_consumed, simulated_results ): spy = SpyEvents() def assert_consumer_event_store(event: Event) -> Result[bool, Error]: spy.append(event) result = simulated_results.pop(0) return result event = EventUserCreatedMother.random() configurer = RabbitMqEventConfigurerMother.with_retry_ttl_10ms() configurer.configure_event(event) bus = RabbitMqEventBusMother.default() bus.publish(event) consumer = RabbitMqEventConsumerMother.with_max_retries(max_retries_allowed) consumer.add_handler_on_store(assert_consumer_event_store) consumer.start() sleep(1.0) consumer.stop() configurer.clear() spy.assert_number_unique_events(1) spy.assert_first_event(event) spy.assert_count_by_event_id(event.event_id, expected_number_event_consumed)
def test_should_consumer_react_to_chaos_inputs( max_retries_allowed, expected_number_event_consumed, chaos ): spy = SpyEvents() def assert_consumer(event: Event) -> Result[bool, Error]: spy.append(event) return isSuccess event = EventUserCreatedMother.random() subscribers = [ EventSubscriber( event_name=event.event_name, event_version=event.event_version, handlers=[assert_consumer], ) ] configurer = RabbitMqEventConfigurerMother.with_retry_ttl_10ms() configurer.configure_subscribers(subscribers) bus = RabbitMqEventBusMother.default() bus.publish(event) consumer = RabbitMqEventConsumerMother.with_chaos(chaos, max_retries_allowed) consumer.add_subscribers(subscribers) consumer.start() sleep(1.0) consumer.stop() configurer.clear() spy.assert_count_by_event_id(event.event_id, expected_number_event_consumed)
def test_should_publish_consume_and_retry_event_with_two_handlers_from_rabbitmq_when_fail_consumer( max_retries_allowed, expected_number_event_consumed, simulated_results): spy_consumer_1 = SpyEvents() spy_consumer_2 = SpyEvents() simulated_results_1 = copy.deepcopy(simulated_results) simulated_results_2 = copy.deepcopy(simulated_results) def assert_consumer_1(event: Event) -> Result[bool, Error]: spy_consumer_1.append(event) result = simulated_results_1.pop(0) return result def assert_consumer_2(event: Event) -> Result[bool, Error]: spy_consumer_2.append(event) result = simulated_results_2.pop(0) return result event = EventUserCreatedMother.random() subscribers = [ EventSubscriber( event_name=event.event_name, event_version=event.event_version, handlers=[assert_consumer_1, assert_consumer_2], ) ] configurer = RabbitMqEventConfigurerMother.with_retry_ttl_10ms() configurer.configure_subscribers(subscribers) bus = RabbitMqEventBusMother.default() bus.publish(event) consumer = RabbitMqEventConsumerMother.with_max_retries( max_retries_allowed) consumer.add_subscribers(subscribers) consumer.start() sleep(1.5) consumer.stop() configurer.clear() print(f"num events: {len(spy_consumer_1.events)} - {spy_consumer_1}") print(f"num events: {len(spy_consumer_2.events)} - {spy_consumer_2}") spy_consumer_1.assert_number_unique_events(1) spy_consumer_1.assert_first_event(event) spy_consumer_1.assert_count_by_event_id(event.event_id, expected_number_event_consumed) spy_consumer_2.assert_number_unique_events(1) spy_consumer_2.assert_first_event(event) spy_consumer_2.assert_count_by_event_id(event.event_id, expected_number_event_consumed)
def test_should_publish_consume_retry_and_send_to_dead_letter_event_from_rabbitmq_when_fail_consumer( ): max_retries_allowed = 2 expected_number_event_consumed = 3 spy = SpyEvents() spy_dead_letter = SpyEvents() def assert_consumer(event: Event) -> Result[bool, Error]: spy.append(event) return isFailure event = EventUserCreatedMother.random() subscriber = EventSubscriber( event_name=event.event_name, event_version=event.event_version, handlers=[assert_consumer], ) subscribers = [subscriber] configurer = RabbitMqEventConfigurerMother.with_retry_ttl_10ms() configurer.configure_subscribers(subscribers) bus = RabbitMqEventBusMother.default() bus.publish(event) consumer = RabbitMqEventConsumerMother.with_max_retries( max_retries_allowed) consumer.add_subscribers(subscribers) def dead_letter_consumer(event: Event) -> Result[bool, Error]: spy_dead_letter.append(event) return isSuccess consumer.add_subscriber_on_dead_letter(subscriber, dead_letter_consumer) consumer.start() sleep(1.5) consumer.stop() configurer.clear() spy.assert_number_unique_events(1) spy.assert_first_event(event) spy.assert_count_by_event_id(event.event_id, expected_number_event_consumed) spy_dead_letter.assert_number_unique_events(1) spy_dead_letter.assert_first_event(event) spy_dead_letter.assert_count_by_event_id(event.event_id, 1)
def test_should_publish_consume_and_retry_event_not_affecting_store_queue_from_rabbitmq_when_fail_handler_consumer( max_retries_allowed, expected_number_event_consumed, simulated_results): spy_consumer_event_store = SpyEvents() spy_consumer_handler = SpyEvents() def assert_consumer_event_store(event: Event) -> Result[bool, Error]: spy_consumer_event_store.append(event) return isSuccess def assert_consumer_handler(event: Event) -> Result[bool, Error]: spy_consumer_handler.append(event) result = simulated_results.pop(0) return result event = EventUserCreatedMother.random() subscribers = [ EventSubscriber( event_name=event.event_name, event_version=event.event_version, handlers=[assert_consumer_handler], ) ] configurer = RabbitMqEventConfigurerMother.with_retry_ttl_10ms() configurer.configure_subscribers(subscribers) bus = RabbitMqEventBusMother.default() bus.publish(event) consumer = RabbitMqEventConsumerMother.with_max_retries( max_retries_allowed) consumer.add_subscribers(subscribers) consumer.add_handler_on_queue("store", assert_consumer_event_store) consumer.start() sleep(1.0) consumer.stop() configurer.clear() spy_consumer_event_store.assert_number_unique_events(1) spy_consumer_event_store.assert_first_event(event) spy_consumer_event_store.assert_count_by_event_id(event.event_id, 1) spy_consumer_handler.assert_number_unique_events(1) spy_consumer_handler.assert_first_event(event) spy_consumer_handler.assert_count_by_event_id( event.event_id, expected_number_event_consumed)
def test_should_consumer_react_to_chaos_with_nck_simulation_and_check_logger(): spy = SpyEvents() logger = FakeLogger() def assert_consumer(event: Event) -> Result[bool, Error]: spy.append(event) return isSuccess event = EventUserCreatedMother.random() subscribers = [ EventSubscriber( event_name=event.event_name, event_version=event.event_version, handlers=[assert_consumer], ) ] configurer = RabbitMqEventConfigurerMother.with_retry_ttl_10ms() configurer.configure_subscribers(subscribers) bus = RabbitMqEventBusMother.default() bus.publish(event) max_retries_allowed = 5 chaos = RabbitMqEventChaos(percentage_simulate_nack=1.0) consumer = RabbitMqEventConsumerMother.with_chaos( chaos, max_retries_allowed, logger ) consumer.add_subscribers(subscribers) consumer.start() sleep(1.0) consumer.stop() configurer.clear() assert len(logger.get_logging_messages()) >= 200 first_logging_message = logger.get_logging_messages()[0] assert first_logging_message[0] == DEBUG assert first_logging_message[1]["meta"] == { "layer": "rabbitmq_event_consumer", "operation": "assert_consumer", } assert ( first_logging_message[1]["data"]["message"]["chaos_action"] == "nack simulated" )
def test_should_consumer_react_to_chaos_with_zero_probability(): spy = SpyEvents() logger = FakeLogger() def assert_consumer(event: Event) -> Result[bool, Error]: spy.append(event) return isSuccess event = EventUserCreatedMother.random() subscribers = [ EventSubscriber( event_name=event.event_name, event_version=event.event_version, handlers=[assert_consumer], ) ] configurer = RabbitMqEventConfigurerMother.with_retry_ttl_10ms() configurer.configure_subscribers(subscribers) bus = RabbitMqEventBusMother.default() bus.publish(event) max_retries_allowed = 5 chaos = RabbitMqEventChaos( percentage_simulate_nack=0.0, percentage_simulate_failures=0.0 ) consumer = RabbitMqEventConsumerMother.with_chaos( chaos, max_retries_allowed, logger ) consumer.add_subscribers(subscribers) consumer.start() sleep(1.0) consumer.stop() configurer.clear() spy.assert_number_unique_events(1) spy.assert_first_event(event) spy.assert_count_by_event_id(event.event_id, 1) assert len(logger.get_logging_messages()) == 2 logging_message = logger.get_logging_messages()[1] assert logging_message[0] == DEBUG assert logging_message[1]["data"]["message"]["derived_action"] == {}
def test_should_unsubscribe_and_resume_handler_on_store_queue(): spy = SpyEvents() spy_dead_letter = SpyEvents() def assert_consumer_event_store(event: Event) -> BoolResult: spy.append(event) return isSuccess def assert_consumer_event_dead_letter(event: Event) -> BoolResult: spy_dead_letter.append(event) return isSuccess bus = RabbitMqEventBusMother.default() first_event = EventUserCreatedMother.random() configurer = RabbitMqEventConfigurerMother.with_retry_ttl_10ms() configurer.configure_event(first_event) # Consumer configuration consumer = RabbitMqEventConsumerMother.default() consumer.add_handler_on_store(assert_consumer_event_store) consumer.add_handler_on_queue( "dead_letter.store", assert_consumer_event_dead_letter ) consumer.start() bus.publish(first_event) sleep(1.0) consumer.unsubscribe_handler_on_queue("store") for i in range(10): bus.publish(EventUserCreatedMother.random()) sleep(5.0) consumer.resume_handler_on_queue("store") second_event = EventUserCreatedMother.random() bus.publish(second_event) sleep(3.0) consumer.stop() configurer.clear() spy.assert_number_unique_events(2) spy.assert_count_by_event_id(first_event.event_id, 1) spy.assert_count_by_event_id(second_event.event_id, 1) spy_dead_letter.assert_number_unique_events(10)
def test_should_publish_consume_with_event_handler_return_nothing(): spy = SpyEvents() logger = FakeLogger() @event_handler(logger=logger) def assert_consumer(event: Event) -> Result[bool, Error]: spy.append(event) event = EventUserCreatedMother.random() subscribers = [ EventSubscriber( event_name=event.event_name, event_version=event.event_version, handlers=[assert_consumer], ) ] configurer = RabbitMqEventConfigurerMother.with_retry_ttl_10ms() configurer.configure_subscribers(subscribers) bus = RabbitMqEventBusMother.default() bus.publish(event) consumer = RabbitMqEventConsumerMother.with_max_retries(5) consumer.add_subscribers(subscribers) consumer.start() sleep(1.0) consumer.stop() configurer.clear() spy.assert_number_unique_events(1) # If returns isFailure it would retry spy.assert_first_event(event) spy.assert_count_by_event_id(event.event_id, 1) first_logging_message = logger.get_logging_messages()[0] assert first_logging_message == ( DEBUG, LogMessageMother.get_event_handler( operation="assert_consumer", message={"event": event.event_name, "body": event.to_json()}, ).to_dict(), )
def test_should_raise_an_error_when_resume_an_nonexistent_queue(): def assert_consumer_event_store(event: Event) -> BoolResult: return isSuccess event = EventUserCreatedMother.random() configurer = RabbitMqEventConfigurerMother.with_retry_ttl_10ms() configurer.configure_event(event) # Consumer configuration consumer = RabbitMqEventConsumerMother.default() consumer.add_handler_on_store(assert_consumer_event_store) consumer.start() with pytest.raises(IndexError) as excinfo: consumer.resume_handler_on_queue("nonexistent_queue") assert ( "Cannot resume an nonexistent queue (nonexistent_queue). Please, check configured consumers" in str(excinfo.value) ) consumer.stop() configurer.clear()
def test_should_publish_event_on_consumer_with_event_handler(): spy = SpyEvents() @event_handler(logger=FakeLogger()) def assert_consumer(event: Event, event_bus: IEventBus) -> BoolResult: spy.append(event) event = EventUserUpdatedMother.random() event_bus.publish(event) return isSuccess event = EventUserCreatedMother.random() subscribers = [ EventSubscriber( event_name=event.event_name, event_version=event.event_version, handlers=[assert_consumer], ) ] configurer = RabbitMqEventConfigurerMother.with_retry_ttl_10ms() configurer.configure_subscribers(subscribers) consumer = RabbitMqEventConsumerMother.with_max_retries(1) consumer.add_subscribers(subscribers) consumer.start() bus = RabbitMqEventBusMother.default() for _ in range(1): event = EventUserCreatedMother.random() bus.publish(event) sleep(1.0) consumer.stop() configurer.clear() spy.assert_number_unique_events(1)