def execute(self): """ Get message from channel API and post it to message API. Retry in case of failure """ job = self.channel_notification_repo.get_job() if not job: return super().execute() queue_message_id, job_payload = job attempt = job_payload[self.ATTEMPT] try: self.process(job_payload) except ChannelApiFailure as e: increase_counter( "usecase.ProcessChannelNotificationUseCase.failure") logger.info("%s: processing channel notification failure", queue_message_id) logger.exception(e) if attempt < self.MAX_ATTEMPTS: attempt += 1 EnqueueChannelNotificationUseCase( self.channel_notification_repo).retry( job_payload, attempt) self.channel_notification_repo.delete(queue_message_id) return raise else: self.channel_notification_repo.delete(queue_message_id)
def process(self, job_payload): logger.debug("Processing job: %r", job_payload) channel_id = job_payload[self.CHANNEL_ID] channel = get_channel_by_id(channel_id, self.routing_table) if not channel: raise ChannelNotFound("Channel not found, id: %s" % channel_id) notification_payload = job_payload[self.NOTIFICATION_PAYLOAD] message = self._get_message(channel, notification_payload['id']) self.enqueue_message_use_case.execute(message) increase_counter("usecase.ProcessChannelNotificationUseCase.processed")
def channel_message_receive(channel_id): """ Handles the pings """ body = request.get_json(silent=True) increase_counter("message_rx.message.received") repo = ChannelNotificationRepo(Config.CHANNEL_NOTIFICATION_REPO_CONF) use_case = EnqueueChannelNotificationUseCase( channel_notification_repo=repo) channel = get_channel_by_id(channel_id, Config.ROUTING_TABLE) use_case.execute(channel, body) return Response()
def run(self): for channel in get_channels_to_subscribe_as(env.ROUTING_TABLE, env.JURISDICTION): if self.should_update_subscription(): increase_counter("subscription.attempt") logger.info("Subscribing to channel %s", channel["Name"]) try: self.subscribe(channel) except Exception as e: increase_counter("subscription.error") logger.error("Unable to subscribe to channel %s - %s", channel, str(e))
def subscribe(self, channel): channel_url = self.get_channel_subscribe_endpoint_url(channel) now = datetime.datetime.utcnow() try: callback_url = self.get_callback_url(channel) logger.info('Sending subscription request to %s', channel_url) RequestChannelAPIUseCase(channel).subscribe_by_jurisdiction( callback_url, env.JURISDICTION) except (SubscriptionFailure, InvalidSubscriptionParameters) as e: logger.error(e) else: self.last_subscribed_at = now increase_counter("subscription.success") logger.info('Successfully subscribed at %s' % self.last_subscribed_at)
def channel_message_confirm(channel_id): """ Handles subscription verification requests https://www.w3.org/TR/websub/#hub-verifies-intent hub.mode=subscribe&hub.topic=jurisdiction.AU& hub.challenge=e35ad43c-7149-45cb-a8eb-3a5a76a368de& hub.lease_seconds=432000 """ # TODO: validate topic and mode # TODO: validate signature header channel = get_channel_by_id(channel_id, Config.ROUTING_TABLE) if not channel: logger.warning( "Trying to confirm subscription for a wrong channel %s (%s)", channel_id, Config.ROUTING_TABLE) return Response("Bad channel_id", status=400) increase_counter("message_rx.channel.confirmed") return Response(request.args.get('hub.challenge'))
def execute(self, *args, **kwargs): increase_counter(f"usecase.{self.__class__.__name__}.execute_called", 1)
try: callback_url = self.get_callback_url(channel) logger.info('Sending subscription request to %s', channel_url) RequestChannelAPIUseCase(channel).subscribe_by_jurisdiction( callback_url, env.JURISDICTION) except (SubscriptionFailure, InvalidSubscriptionParameters) as e: logger.error(e) else: self.last_subscribed_at = now increase_counter("subscription.success") logger.info('Successfully subscribed at %s' % self.last_subscribed_at) @staticmethod def get_callback_url(channel): return urljoin(env.MESSAGE_RX_API_URL, 'channel-message/{Id}'.format(**channel)) def get_channel_subscribe_endpoint_url(self, channel): return urljoin(channel['ChannelUrl'], self.CHANNEL_API_SUBSCRIBE_ENDPOINT) if __name__ == '__main__': processor = SubscriptionHandler() sleep_period = 30 increase_counter("subscription.start-process") while True: processor.run() sleep(sleep_period)