Пример #1
0
 def __init__(self, *args, **kwargs):
     super().__init__(*args, **kwargs)
     self.compare_and_update_script = CompareAndUpdateScript(self.redis)
Пример #2
0
class SiteStatsDaoRedis(SiteStatsDaoBase, RedisDaoBase):
    """Persists and queries SiteStats in Redis."""
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.compare_and_update_script = CompareAndUpdateScript(self.redis)

    def find_by_id(self,
                   site_id: int,
                   day: datetime.datetime = None,
                   **kwargs) -> SiteStats:
        if day is None:
            day = datetime.datetime.now()

        key = self.key_schema.site_stats_key(site_id, day)
        fields = self.redis.hgetall(key)

        if not fields:
            raise SiteStatsNotFound()

        return SiteStatsSchema().load(fields)

    def _update_basic(self, key: str, reading: MeterReading) -> None:
        reporting_time = datetime.datetime.utcnow().isoformat()
        self.redis.hset(key, SiteStats.LAST_REPORTING_TIME, reporting_time)
        self.redis.hincrby(key, SiteStats.COUNT, 1)
        self.redis.expire(key, WEEK_SECONDS)

        max_wh = self.redis.hget(key, SiteStats.MAX_WH)
        if not max_wh or reading.wh_generated > float(max_wh):
            self.redis.hset(key, SiteStats.MAX_WH, reading.wh_generated)

        min_wh = self.redis.hget(key, SiteStats.MIN_WH)
        if not min_wh or reading.wh_generated < float(min_wh):
            self.redis.hset(key, SiteStats.MIN_WH, reading.wh_generated)

        max_capacity = self.redis.hget(key, SiteStats.MAX_CAPACITY)
        if not max_capacity or reading.current_capacity > float(max_capacity):
            self.redis.hset(key, SiteStats.MAX_CAPACITY, reading.wh_generated)

    def _update_optimized(self,
                          key: str,
                          meter_reading: MeterReading,
                          pipeline: redis.client.Pipeline = None) -> None:
        execute = False
        if pipeline is None:
            pipeline = self.redis.pipeline()
            execute = True

        # START Challenge #3
        reporting_time = datetime.datetime.utcnow().isoformat()

        pipeline.hset(key, SiteStats.LAST_REPORTING_TIME, reporting_time)
        pipeline.hincrby(key, SiteStats.COUNT, 1)
        pipeline.expire(key, WEEK_SECONDS)

        self.compare_and_update_script.update_if_greater(
            pipeline, key, SiteStats.MAX_WH, meter_reading.wh_generated)
        self.compare_and_update_script.update_if_less(
            pipeline, key, SiteStats.MIN_WH, meter_reading.wh_generated)
        self.compare_and_update_script.update_if_greater(
            pipeline, key, SiteStats.MAX_CAPACITY,
            meter_reading.current_capacity)

        # END Challenge #3

        if execute:
            pipeline.execute()

    def update(self, meter_reading: MeterReading, **kwargs) -> None:
        key = self.key_schema.site_stats_key(meter_reading.site_id,
                                             meter_reading.timestamp)

        pipeline = kwargs.get('pipeline')
        self._update_optimized(key, meter_reading, pipeline)