Files
notifications-api/app/template_statistics/rest.py

103 lines
4.0 KiB
Python
Raw Normal View History

from flask import (
Blueprint,
jsonify,
request,
current_app
)
from app import redis_store
from app.dao.notifications_dao import (
dao_get_template_usage,
dao_get_last_template_usage
)
from app.dao.templates_dao import (
dao_get_multiple_template_details,
dao_get_template_by_id_and_service_id
)
from app.schemas import notification_with_template_schema
from app.utils import cache_key_for_service_template_usage_per_day, last_n_days
from app.errors import register_errors, InvalidRequest
from collections import Counter
template_statistics = Blueprint('template_statistics',
__name__,
url_prefix='/service/<service_id>/template-statistics')
register_errors(template_statistics)
@template_statistics.route('')
def get_template_statistics_for_service_by_day(service_id):
whole_days = request.args.get('whole_days', request.args.get('limit_days', ''))
try:
whole_days = int(whole_days)
except ValueError:
error = '{} is not an integer'.format(whole_days)
message = {'whole_days': [error]}
raise InvalidRequest(message, status_code=400)
if whole_days < 0 or whole_days > 7:
raise InvalidRequest({'whole_days': ['whole_days must be between 0 and 7']}, status_code=400)
return jsonify(data=_get_template_statistics_for_last_n_days(service_id, whole_days))
@template_statistics.route('/<template_id>')
def get_template_statistics_for_template_id(service_id, template_id):
template = dao_get_template_by_id_and_service_id(template_id, service_id)
data = None
notification = dao_get_last_template_usage(template_id, template.template_type, template.service_id)
if notification:
data = notification_with_template_schema.dump(notification).data
return jsonify(data=data)
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 = {
2018-04-12 14:47:56 +01:00
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 [
{
2018-04-12 14:47:56 +01:00
'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
]