'Main logic of the push loop without the wrapper function that sets
up logging, measures and guards against multiple instances of it
being run.'

@defer.inlineCallbacks
def _unsafe_process(self):

    start = (0 if INCLUDE_ALL_UNREAD_NOTIFS else self.last_stream_ordering)
    fn = self.store.get_unread_push_actions_for_user_in_range_for_email
    unprocessed = (yield fn(self.user_id, start, self.max_stream_ordering))
    soonest_due_at = None
    if (not unprocessed):
        (yield self.save_last_stream_ordering_and_success(self.max_stream_ordering))
        return
    for push_action in unprocessed:
        received_at = push_action['received_ts']
        if (received_at is None):
            received_at = 0
        notif_ready_at = (received_at + DELAY_BEFORE_MAIL_MS)
        room_ready_at = self.room_ready_to_notify_at(push_action['room_id'])
        should_notify_at = max(notif_ready_at, room_ready_at)
        if (should_notify_at < self.clock.time_msec()):
            reason = {'room_id': push_action['room_id'], 'now': self.clock.time_msec(), 'received_at': received_at, 'delay_before_mail_ms': DELAY_BEFORE_MAIL_MS, 'last_sent_ts': self.get_room_last_sent_ts(push_action['room_id']), 'throttle_ms': self.get_room_throttle_ms(push_action['room_id'])}
            (yield self.send_notification(unprocessed, reason))
            (yield self.save_last_stream_ordering_and_success(max([ea['stream_ordering'] for ea in unprocessed])))
            for ea in unprocessed:
                (yield self.sent_notif_update_throttle(ea['room_id'], ea))
            break
        else:
            if ((soonest_due_at is None) or (should_notify_at < soonest_due_at)):
                soonest_due_at = should_notify_at
            if (self.timed_call is not None):
                try:
                    self.timed_call.cancel()
                except (AlreadyCalled, AlreadyCancelled):
                    pass
                self.timed_call = None
    if (soonest_due_at is not None):
        self.timed_call = reactor.callLater(self.seconds_until(soonest_due_at), self.on_timer)
