예제 #1
0
    def _on_request(self, message):
        log = logging.getLogger(__name__)
        try:
            task = task_pb2.Task()
            try:
                # `body` is of unicode type, but we need str type for
                # `ParseFromString()` to work.  It seems to work.
                # Maybe kombu estimate that, without any information,
                # the body should be something as json, and thus a
                # unicode string.  On the c++ side, I didn't manage to
                # find a way to give a content-type or something like
                # that.
                body = str(message.payload)
                task.ParseFromString(body)
            except DecodeError as e:
                log.warn('invalid protobuf: {}'.format(str(e)))
                return

            log.info('Getting a full feed publication request', extra={'task': task})
            if task.action != task_pb2.LOAD_REALTIME or not task.load_realtime:
                return
            start_datetime = datetime.utcnow()
            begin_date = None
            end_date = None
            if hasattr(task.load_realtime, "begin_date"):
                if task.load_realtime.begin_date:
                    begin_date = str_to_date(task.load_realtime.begin_date)

            if hasattr(task.load_realtime, "end_date"):
                if task.load_realtime.end_date:
                    end_date = str_to_date(task.load_realtime.end_date)
            feed = convert_to_gtfsrt(TripUpdate.find_by_contributor_period(task.load_realtime.contributors,
                                                                           begin_date,
                                                                           end_date),
                                     gtfs_realtime_pb2.FeedHeader.FULL_DATASET)

            feed_str = feed.SerializeToString()
            log.info('Starting of full feed publication {}, {}'.format(len(feed_str), task), extra={'size': len(feed_str), 'task': task})
            # http://docs.celeryproject.org/projects/kombu/en/latest/userguide/producers.html#bypassing-routing-by-using-the-anon-exchange
            self.producer.publish(feed_str,
                                  routing_key=task.load_realtime.queue_name,
                                  retry=True,
                                  retry_policy={
                                      'interval_start': 0,  # First retry immediately,
                                      'interval_step': 2,   # then increase by 2s for every retry.
                                      'interval_max': 10,   # but don't exceed 10s between retries.
                                      'max_retries':  self.max_retries,     # give up after 10 (by default) tries.
                                      })
            duration = (datetime.utcnow() - start_datetime).total_seconds()
            log.info('End of full feed publication', extra={'duration': duration, 'task': task})
            record_call('Full feed publication', size=len(feed_str), routing_key=task.load_realtime.queue_name,
                        duration=duration, trip_update_count=len(feed.entity),
                        contributor=task.load_realtime.contributors)
        finally:
            db.session.remove()
예제 #2
0
def test_realtime_loader_valid_protobuf(setup_database):
    task = task_pb2.Task()
    task.action = task_pb2.LOAD_REALTIME
    task.load_realtime.queue_name = "kirin_load_realtime"
    task.load_realtime.contributors.append(COTS_CONTRIBUTOR_ID)
    task.load_realtime.begin_date = "2015-11-04"
    task.load_realtime.end_date = "2015-11-04"
    message = Message()
    message.body = task.SerializeToString()
    rt_loader = RTReloader("hostname", "queue", "exchange", 10)
    with app.app_context():
        resp_rt = rt_loader._on_request(message)
        assert len(resp_rt) == 6
        assert [COTS_CONTRIBUTOR_ID] == resp_rt["contributors"]
        assert task.load_realtime.queue_name == resp_rt["routing_key"]
        assert 0 == resp_rt["output_trip_update_count"]
        assert 46 == resp_rt["output_feed_size"]
        # currently: error while trying to publish the message
        assert "'str' object has no attribute 'clone'" == resp_rt["reason"]
        assert resp_rt["duration"] > 0
예제 #3
0
        def callback(body, message):
            try:
                task = task_pb2.Task()
                try:
                    # `body` is of unicode type, but we need str type for
                    # `ParseFromString()` to work.  It seems to work.
                    # Maybe kombu estimate that, without any information,
                    # the body should be something as json, and thus a
                    # unicode string.  On the c++ side, I didn't manage to
                    # find a way to give a content-type or something like
                    # that.
                    body = str(body)
                    task.ParseFromString(body)
                except DecodeError as e:
                    log.warn('invalid protobuf: {}'.format(str(e)))
                    return

                log.info('getting a request: {}'.format(task))
                if task.action != task_pb2.LOAD_REALTIME or not task.load_realtime:
                    return
                begin_date = None
                end_date = None
                if hasattr(task.load_realtime, "begin_date"):
                    if task.load_realtime.begin_date:
                        begin_date = str_to_date(task.load_realtime.begin_date)

                if hasattr(task.load_realtime, "end_date"):
                    if task.load_realtime.end_date:
                        end_date = str_to_date(task.load_realtime.end_date)
                feed = convert_to_gtfsrt(TripUpdate.find_by_contributor_period(task.load_realtime.contributors,
                                                                               begin_date,
                                                                               end_date),
                                         gtfs_realtime_pb2.FeedHeader.FULL_DATASET)

                with self._get_producer() as producer:
                    log.info('Publishing full feed...')
                    producer.publish(feed.SerializeToString(), routing_key=task.load_realtime.queue_name)
                    log.info('Full feed published.')
            finally:
                db.session.remove()
예제 #4
0
    def _on_request(self, message):
        log = logging.getLogger(__name__)
        status = "OK"
        log_dict = {}
        start_datetime = datetime.utcnow()
        try:
            task = task_pb2.Task()
            try:
                # `body` is a string, but we need binary type for
                # `ParseFromString()` to work.  It seems to work.
                body = bytes(message.payload, encoding="utf-8")
                task.ParseFromString(body)
            except DecodeError as e:
                log.warning("invalid protobuf: {}".format(str(e)))
                return

            log.info("Getting a full feed publication request",
                     extra={"task": task})
            if task.action != task_pb2.LOAD_REALTIME or not task.load_realtime:
                return
            begin_date = None
            end_date = None
            if hasattr(task.load_realtime,
                       "begin_date") and task.load_realtime.begin_date:
                begin_date = str_to_date(task.load_realtime.begin_date)

            if hasattr(task.load_realtime,
                       "end_date") and task.load_realtime.end_date:
                end_date = str_to_date(task.load_realtime.end_date)
            feed = convert_to_gtfsrt(
                TripUpdate.find_by_contributor_period(
                    task.load_realtime.contributors, begin_date, end_date),
                gtfs_realtime_pb2.FeedHeader.FULL_DATASET,
            )

            feed_str = feed.SerializeToString()
            log_dict.update({
                "contributors": task.load_realtime.contributors,
                "routing_key": task.load_realtime.queue_name,
                "output_trip_update_count": len(feed.entity),
                "output_feed_size": sys.getsizeof(feed_str),
            })
            log.info(
                "Starting of full feed publication {}, {}".format(
                    len(feed_str), task),
                extra={
                    "size": len(feed_str),
                    "task": task
                },
            )
            record_custom_parameter("contributors",
                                    task.load_realtime.contributors)
            # http://docs.celeryproject.org/projects/kombu/en/latest/userguide/producers.html#bypassing-routing-by-using-the-anon-exchange
            self.producer.publish(
                feed_str,
                routing_key=task.load_realtime.queue_name,
                retry=True,
                retry_policy={
                    "interval_start": 0,  # First retry immediately,
                    "interval_step": 2,  # then increase by 2s for every retry.
                    "interval_max":
                    10,  # but don't exceed 10s between retries.
                    "max_retries":
                    self.max_retries,  # give up after 10 (by default) tries.
                },
            )
        except Exception as e:
            status = "failure"
            log_dict.update({"reason": str(e)})
            record_custom_parameter("reason", str(e))
        finally:
            duration = (datetime.utcnow() - start_datetime).total_seconds()
            log_dict.update({"duration": duration})
            record_call("kirin_reload_info", status, **log_dict)
            log.info("End of full feed publication",
                     extra={
                         "duration": duration,
                         "task": task
                     })
            db.session.remove()
        return log_dict