def test_multiple_descriptions(valid_message_dicts): message_dict = valid_message_dicts[0] notifications = mock.Mock() notifications.get_job.return_value = (123, message_dict) delivery_outbox = mock.Mock() delivery_outbox.post_job.return_value = False # post failed subscriptions = mock.Mock() subscriptions.get_subscriptions_by_pattern.side_effect = random_urls use_case = DispatchMessageToSubscribersUseCase( notifications, delivery_outbox, subscriptions) use_case.execute() assert not notifications.delete.called
def test_delivery_outbox_post_fail_no_delete(valid_message_dicts): message_dict = valid_message_dicts[0] notifications = mock.Mock() notifications.get_job.return_value = (123, message_dict) delivery_outbox = mock.Mock() delivery_outbox.post_job.return_value = False # post failed subscriptions = mock.Mock() subscriptions.get_subscriptions_by_pattern.return_value = {mock.Mock(callback_url='https://foo.com/bar'), } use_case = DispatchMessageToSubscribersUseCase( notifications, delivery_outbox, subscriptions) use_case.execute() assert not notifications.delete.called
def test_notifications_empty_no_send(valid_message_dicts): message_dict = valid_message_dicts[0] m = protocol.Message.from_dict(message_dict) print(m) notifications = mock.Mock() notifications.get_job.return_value = () delivery_outbox = mock.Mock() subscriptions = mock.Mock() subscriptions.get_subscriptions_by_pattern.return_value = {mock.Mock(callback_url='https://foo.com/bar'), } use_case = DispatchMessageToSubscribersUseCase( notifications, delivery_outbox, subscriptions) use_case.execute() assert not delivery_outbox.post_job.called
def test_delivery_enqueued(valid_message_dicts): message_dict = valid_message_dicts[0] notifications = mock.Mock() notifications.get_job.return_value = (1234, message_dict) delivery_outbox = mock.Mock() delivery_outbox.post_job.return_value = True subscriptions = mock.Mock() subscriptions.search.return_value = ['https://foo.com/bar', ] use_case = DispatchMessageToSubscribersUseCase( notifications, delivery_outbox, subscriptions) use_case.execute() assert delivery_outbox.post_job.called assert notifications.delete.called
class CallbacksSpreaderProcessor(object): """ Convert each incoming message to set of messages containing (websub_url, message) so they may be sent and fail separately """ def _prepare_notifications_repo(self, conf): notifications_repo_conf = env_queue_config('PROC_OBJ_OUTBOX_REPO') if conf: notifications_repo_conf.update(conf) self.notifications_repo = NotificationsRepo(notifications_repo_conf) def _prepare_outbox_repo(self, conf): outbox_repo_conf = env_queue_config('PROC_DELIVERY_OUTBOX_REPO') if conf: outbox_repo_conf.update(conf) self.delivery_outbox_repo = DeliveryOutboxRepo(outbox_repo_conf) def _prepare_subscriptions_repo(self, conf): subscriptions_repo_conf = env_s3_config('PROC_SUB_REPO') if conf: subscriptions_repo_conf.update(conf) self.subscriptions_repo = SubscriptionsRepo(subscriptions_repo_conf) def _prepare_use_cases(self): self.uc = DispatchMessageToSubscribersUseCase( notifications_repo=self.notifications_repo, delivery_outbox_repo=self.delivery_outbox_repo, subscriptions_repo=self.subscriptions_repo, ) def __init__(self, notifications_repo_conf=None, delivery_outbox_repo_conf=None, subscriptions_repo_conf=None): self._prepare_notifications_repo(notifications_repo_conf) self._prepare_outbox_repo(delivery_outbox_repo_conf) self._prepare_subscriptions_repo(subscriptions_repo_conf) self._prepare_use_cases() def __iter__(self): logger.info("Starting the outbound callbacks processor") return self def __next__(self): try: result = self.uc.execute() except Exception as e: logger.exception(e) result = None return result
def _prepare_use_cases(self): self.uc = DispatchMessageToSubscribersUseCase( notifications_repo=self.notifications_repo, delivery_outbox_repo=self.delivery_outbox_repo, subscriptions_repo=self.subscriptions_repo, )
def test(): # testing predicate in url search delivery_outbox_repo = repos.DeliveryOutboxRepo(DELIVERY_OUTBOX_REPO_CONF) notifications_repo = repos.NotificationsRepo(NOTIFICATIONS_REPO_CONF) subscriptions_repo = repos.SubscriptionsRepo(SUBSCRIPTIONS_REPO_CONF) delivery_outbox_repo._unsafe_method__clear() notifications_repo._unsafe_method__clear() subscriptions_repo._unsafe_method__clear() assert notifications_repo.is_empty() assert delivery_outbox_repo.is_empty() assert subscriptions_repo.is_empty() use_case = DispatchMessageToSubscribersUseCase(notifications_repo, delivery_outbox_repo, subscriptions_repo) processor = Processor(use_case=use_case) # testing that iter returns processor assert iter(processor) is processor # assert processor has nothing to do assert next(processor) is None _fill_subscriptions_repo(subscriptions_repo, SUBSCRIPTIONS) for prefix, subscriptions in SUBSCRIPTIONS_WITH_COMMON_PREFIXES.items(): _fill_subscriptions_repo(subscriptions_repo, subscriptions) for s in subscriptions_repo.get_subscriptions_by_pattern(Pattern('aaa.bbb.ccc.ddd')): print(s.__hash__()) print(s.payload, s.key, s.now, s.data) # testing that subscriptions repod doesn't have side effect on processor assert next(processor) is None # testing callbacks spreading for predicates without common prefixes for predicate, number_of_subscribers in SUBSCRIPTIONS.items(): # pushing notification message = _generate_msg_object(predicate=predicate) notifications_repo.post_job(message) # test proccessor received notification assert next(processor) is True # test processor created correct number of delivery jobs # each subscriptions group has unique topic/predicate for i in range(number_of_subscribers): job = delivery_outbox_repo.get_job() assert job, f"Call:{i+1}. Predicate:{predicate}" message_queue_id, payload = job # test that only direct subscribers received this message assert payload.get('payload', {}).get('predicate') == predicate # testing that only correct subscribers will receive notification url = payload.get('s', '') assert _is_predicate_in_url(url, predicate), {'url': url, 'predicate': predicate} assert delivery_outbox_repo.delete(message_queue_id) # test queue is empty print(delivery_outbox_repo.get_job()) assert not delivery_outbox_repo.get_job() # processor completed the job assert next(processor) is None for prefix, subscriptions in SUBSCRIPTIONS_WITH_COMMON_PREFIXES.items(): # finding longest predicate in the group + total number of expected # delivery jobs expect_jobs = 0 longest_predicate = "" for predicate, number_of_subscribers in subscriptions.items(): if len(longest_predicate) < len(predicate): longest_predicate = predicate expect_jobs += number_of_subscribers # posting notification message = _generate_msg_object(predicate=longest_predicate) assert notifications_repo.post_job(message) assert next(processor) is True # testing processor created the correct number of delivery jobs for i in range(expect_jobs): job = delivery_outbox_repo.get_job() assert job message_queue_id, payload = job # test that only direct subscribers received this message assert payload.get('payload', {}).get('predicate') == longest_predicate # testing that only correct subscribers will receive notification url = payload.get('s', '') assert _is_predicate_in_url(url, prefix), {'url': url, 'prefix': prefix} assert delivery_outbox_repo.delete(message_queue_id) assert next(processor) is None