def populate_redis_template_usage(service_id, day): """ Recalculate and replace the stats in redis for a day. To be used if redis data is lost for some reason. """ if not current_app.config['REDIS_ENABLED']: current_app.logger.error( 'Cannot populate redis template usage - redis not enabled') sys.exit(1) # the day variable is set by click to be midnight of that day start_time = get_sydney_midnight_in_utc(day) end_time = get_sydney_midnight_in_utc(day + timedelta(days=1)) usage = { str(row.template_id): row.count for row in db.session.query(Notification.template_id, func.count().label('count')). filter(Notification.service_id == service_id, Notification.created_at >= start_time, Notification.created_at < end_time).group_by( Notification.template_id) } current_app.logger.info( 'Populating usage dict for service {} day {}: {}'.format( service_id, day, usage.items())) if usage: key = cache_key_for_service_template_usage_per_day(service_id, day) redis_store.set_hash_and_expire( key, usage, current_app.config['EXPIRE_CACHE_EIGHT_DAYS'], raise_exception=True)
def increment_template_usage_cache(service_id, template_id, created_at): key = cache_key_for_service_template_usage_per_day(service_id, convert_utc_to_aet(created_at)) redis_store.increment_hash_value(key, template_id) # set key to expire in eight days - we don't know if we've just created the key or not, so must assume that we # have and reset the expiry. Eight days is longer than any notification is in the notifications table, so we'll # always capture the full week's numbers redis_store.expire(key, current_app.config['EXPIRE_CACHE_EIGHT_DAYS'])
def _get_template_statistics_for_last_n_days(service_id, whole_days): template_stats_by_id = Counter() # 0 whole_days = last 1 days (ie since midnight today) = today. # 7 whole days = last 8 days (ie since midnight this day last week) = a week and a bit for day in last_n_days(whole_days + 1): # "{SERVICE_ID}-template-usage-{YYYY-MM-DD}" key = cache_key_for_service_template_usage_per_day(service_id, day) stats = redis_store.get_all_from_hash(key) if stats: stats = {k.decode('utf-8'): int(v) for k, v in stats.items()} else: # key didn't exist (or redis was down) - lets populate from DB. stats = { str(row.id): row.count for row in dao_get_template_usage(service_id, day=day) } # if there is data in db, but not in redis - lets put it in redis so we don't have to do # this calc again next time. If there isn't any data, we can't put it in redis. # Zero length hashes aren't a thing in redis. (There'll only be no data if the service has no templates) # Nothing is stored if redis is down. if stats: redis_store.set_hash_and_expire( key, stats, current_app.config['EXPIRE_CACHE_EIGHT_DAYS']) template_stats_by_id += Counter(stats) # attach count from stats to name/type/etc from database template_details = dao_get_multiple_template_details( template_stats_by_id.keys()) return [ { 'count': template_stats_by_id[str(template.id)], 'template_id': str(template.id), 'template_name': template.name, 'template_type': template.template_type, 'is_precompiled_letter': template.is_precompiled_letter } for template in template_details # we don't want to return templates with no count to the front-end, # but they're returned from the DB and might be put in redis like that (if there was no data that day) if template_stats_by_id[str(template.id)] != 0 ]