def _find_and_respond_to_twitter_events(self) -> None: """Looks for TwitterEvent objects that have not yet been responded to and begins the process of creating a response. Additionally, failed events are rerun to provide a correct response, particularly useful in cases where external apis are down for maintenance. """ interval = ( self.PRODUCTION_APP_RATE_LIMITING_INTERVAL_IN_SECONDS if self._is_production() else self.DEVELOPMENT_CLIENT_RATE_LIMITING_INTERVAL_IN_SECONDS) self._events_iteration += 1 LOG.debug( f'Looking up twitter events on iteration {self._events_iteration}') # set up timer twitter_events_thread = threading.Timer( interval, self._find_and_respond_to_twitter_events) self._lookup_threads.append(twitter_events_thread) # start timer twitter_events_thread.start() try: new_events: list[TwitterEvent] = TwitterEvent.get_all_by( is_duplicate=False, responded_to=False, response_in_progress=False) LOG.debug(f'new events: {new_events}') failed_events: list[TwitterEvent] = TwitterEvent.get_all_by( is_duplicate=False, error_on_lookup=True, responded_to=True, response_in_progress=False) failed_events_that_need_response: list[TwitterEvent] = self._filter_failed_twitter_events(failed_events) events_to_respond_to: [list[TwitterEvent]] = new_events + failed_events_that_need_response LOG.debug(f'events to respond to: {events_to_respond_to}') for event in events_to_respond_to: self._process_twitter_event(event=event) except Exception as e: LOG.error(e) LOG.error(str(e)) LOG.error(e.args) logging.exception("stack trace") finally: TwitterEvent.query.session.close()
def _find_and_respond_to_twitter_events(self): """Looks for TwitterEvent objects that have not yet been responded to and begins the process of creating a response. Additionally, failed events are rerun to provide a correct response, particularly useful in cases where external apis are down for maintenance. """ interval = 3.0 if self._is_production() else self.DEVELOPMENT_TIME_INTERVAL self.events_iteration += 1 LOG.debug( f'Looking up twitter events on iteration {self.events_iteration}') # start timer threading.Timer( interval, self._find_and_respond_to_twitter_events).start() try: new_events: [List[TwitterEvent]] = TwitterEvent.get_all_by( is_duplicate=False, responded_to=False, response_in_progress=False) LOG.debug(f'new events: {new_events}') failed_events: [List[TwitterEvent]] = TwitterEvent.get_all_by( is_duplicate=False, error_on_lookup=True, responded_to=True, response_in_progress=False) LOG.debug(f'failed events: {failed_events}') events_to_respond_to: [List[TwitterEvent]] = new_events + failed_events LOG.debug(f'events to respond to: {events_to_respond_to}') for event in events_to_respond_to: LOG.debug(f'Beginning response for event: {event.id}') # search for duplicates is_event_duplicate: bool = TwitterEvent.query.filter_by( event_type=event.event_type, event_id=event.event_id, user_handle=event.user_handle, responded_to=True ).filter( TwitterEvent.id != event.id).count() > 0 if is_event_duplicate: event.is_duplicate = True TwitterEvent.query.session.commit() LOG.info(f'Event {event.id} is a duplicate, skipping.') else: event.response_in_progress = True TwitterEvent.query.session.commit() try: message_source = LookupSource(event.event_type) # build request lookup_request: Type[BaseLookupRequest] = self.reply_argument_builder.build_reply_data( message=event, message_source=message_source) # Reply to the event. reply_event = self.aggregator.initiate_reply( lookup_request=lookup_request) success = reply_event.get('success', False) if success: # Need username for statuses reply_event['username'] = event.user_handle # There's need to tell people that there was an error more than once if not (reply_event.get( 'error_on_lookup') and event.error_on_lookup): try: self._process_response(reply_event) except tweepy.error.TweepError as e: reply_event['error_on_lookup'] = True # We've responded! event.response_in_progress = False event.responded_to = True # Update error status if reply_event.get('error_on_lookup'): event.error_on_lookup = True else: event.error_on_lookup = False TwitterEvent.query.session.commit() except ValueError as e: LOG.error( f'Encountered unknown event type. ' f'Response is not possible.') except Exception as e: LOG.error(e) LOG.error(str(e)) LOG.error(e.args) logging.exception("stack trace") finally: TwitterEvent.query.session.close()