From c7707873e4877093a10964338aa5a9a4b35bcdf1 Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Mon, 12 Jun 2017 14:25:17 +0100 Subject: [PATCH] Queries to get job statistics by job_id or by service_id. --- app/dao/jobs_dao.py | 35 +++++++++- tests/app/dao/test_jobs_dao.py | 117 ++++++++++++++++++++++++++++++++- 2 files changed, 150 insertions(+), 2 deletions(-) diff --git a/app/dao/jobs_dao.py b/app/dao/jobs_dao.py index 86e565619..d6770943f 100644 --- a/app/dao/jobs_dao.py +++ b/app/dao/jobs_dao.py @@ -8,7 +8,7 @@ from app.dao import days_ago from app.models import ( Job, JobStatistics, Notification, NotificationHistory, Template, JOB_STATUS_SCHEDULED, JOB_STATUS_PENDING, - EMAIL_TYPE, SMS_TYPE, LETTER_TYPE + LETTER_TYPE ) from app.statsd_decorators import statsd @@ -142,3 +142,36 @@ def dao_get_all_letter_jobs(): return db.session.query(Job).join(Job.template).filter( Template.template_type == LETTER_TYPE ).order_by(desc(Job.created_at)).all() + + +@statsd(namespace="dao") +def dao_get_job_statistics_for_job(job_id): + query = db.session.query( + JobStatistics.job_id, + Job.original_file_name, + Job.created_at, + JobStatistics.sent, + JobStatistics.delivered, + JobStatistics.failed + ).filter(JobStatistics.job_id == job_id).filter(Job.id == JobStatistics.job_id) + return query.one() + + +@statsd(namespace="dao") +def dao_get_job_stats_for_service(service_id, page=1, page_size=50, limit_days=None): + query = Job.query.join( + JobStatistics, Job.id == JobStatistics.job_id + ).filter( + Job.service_id == service_id + ).add_columns( + JobStatistics.job_id, + Job.original_file_name, + Job.created_at, + JobStatistics.sent, + JobStatistics.delivered, + JobStatistics.failed + ) + if limit_days: + query = query.filter(Job.created_at >= days_ago(limit_days)) + query = query.order_by(Job.created_at.desc()) + return query.paginate(page=page, per_page=page_size).items diff --git a/tests/app/dao/test_jobs_dao.py b/tests/app/dao/test_jobs_dao.py index 42f93d230..476e6b1de 100644 --- a/tests/app/dao/test_jobs_dao.py +++ b/tests/app/dao/test_jobs_dao.py @@ -16,7 +16,10 @@ from app.dao.jobs_dao import ( all_notifications_are_created_for_job, dao_update_job_status, dao_get_all_notifications_for_job, - dao_get_jobs_older_than_limited_by) + dao_get_jobs_older_than_limited_by, + dao_get_job_statistics_for_job, + dao_get_job_stats_for_service) +from app.dao.statistics_dao import create_or_update_job_sending_statistics, update_job_stats_outcome_count from app.models import ( Job, JobStatistics, EMAIL_TYPE, SMS_TYPE, LETTER_TYPE @@ -411,3 +414,115 @@ def test_should_get_jobs_seven_days_old_filters_type(notify_db, notify_db_sessio assert len(jobs) == 2 assert job_to_remain.id not in [job.id for job in jobs] + + +def test_dao_get_job_statistics_for_job(notify_db, notify_db_session, sample_job): + notification = create_notification(notify_db=notify_db, notify_db_session=notify_db_session, job=sample_job) + notification_delivered = create_notification(notify_db=notify_db, notify_db_session=notify_db_session, + job=sample_job, status='delivered') + notification_failed = create_notification(notify_db=notify_db, notify_db_session=notify_db_session, job=sample_job, + status='permanent-failure') + + create_or_update_job_sending_statistics(notification) + create_or_update_job_sending_statistics(notification_delivered) + create_or_update_job_sending_statistics(notification_failed) + update_job_stats_outcome_count(notification_delivered) + update_job_stats_outcome_count(notification_failed) + results = dao_get_job_statistics_for_job(sample_job.id) + assert results.job_id == sample_job.id + assert results.sent == 3 + assert results.delivered == 1 + assert results.failed == 1 + + +def test_dao_get_job_statistics_for_job(notify_db, notify_db_session, sample_service): + job_1, job_2 = stats_set_up(notify_db, notify_db_session, sample_service) + results = dao_get_job_statistics_for_job(job_1.id) + assert_job_stat(job_1, results, 2, 1, 0) + + results_2 = dao_get_job_statistics_for_job(job_2.id) + assert_job_stat(job_2, results_2, 1, 0, 1) + + +def test_dao_get_job_stats_for_service(notify_db, notify_db_session, sample_service): + job_1, job_2 = stats_set_up(notify_db, notify_db_session, sample_service) + + results = dao_get_job_stats_for_service(sample_service.id) + assert len(results) == 2 + assert_job_stat(job_2, results[0], 1, 0, 1) + assert_job_stat(job_1, results[1], 2, 1, 0) + + +def test_dao_get_job_stats_for_service_only_returns_stats_for_service(notify_db, notify_db_session, sample_service): + job_1, job_2 = stats_set_up(notify_db, notify_db_session, sample_service) + another_service = create_service(notify_db=notify_db, notify_db_session=notify_db_session, + service_name='Another Service') + job_3, job_4 = stats_set_up(notify_db, notify_db_session, service=another_service) + + results = dao_get_job_stats_for_service(sample_service.id) + assert len(results) == 2 + assert_job_stat(job_2, results[0], 1, 0, 1) + assert_job_stat(job_1, results[1], 2, 1, 0) + + results = dao_get_job_stats_for_service(another_service.id) + assert len(results) == 2 + assert_job_stat(job_4, results[0], 1, 0, 1) + assert_job_stat(job_3, results[1], 2, 1, 0) + + +def test_dao_get_job_stats_for_service_only_returns_jobs_created_within_limited_days( + notify_db, notify_db_session, sample_service): + job_1, job_2 = stats_set_up(notify_db, notify_db_session, sample_service) + + results = dao_get_job_stats_for_service(sample_service.id, limit_days=1) + assert len(results) == 1 + assert_job_stat(job_2, results[0], 1, 0, 1) + + +def test_dao_get_job_stats_for_service_only_returns_jobs_created_within_limited_days_inclusive( + notify_db, notify_db_session, sample_service): + job_1, job_2 = stats_set_up(notify_db, notify_db_session, sample_service) + + results = dao_get_job_stats_for_service(sample_service.id, limit_days=2) + assert len(results) == 2 + assert_job_stat(job_2, results[0], 1, 0, 1) + assert_job_stat(job_1, results[1], 2, 1, 0) + + +def test_dao_get_job_stats_paginates_results( + notify_db, notify_db_session, sample_service): + job_1, job_2 = stats_set_up(notify_db, notify_db_session, sample_service) + + results = dao_get_job_stats_for_service(sample_service.id, page=1, page_size=1) + assert len(results) == 1 + assert_job_stat(job_2, results[0], 1, 0, 1) + results_2 = dao_get_job_stats_for_service(sample_service.id, page=2, page_size=1) + assert len(results_2) == 1 + assert_job_stat(job_1, results_2[0], 2, 1, 0) + + +def assert_job_stat(job, result, sent, delivered, failed): + assert result.job_id == job.id + assert result.original_file_name == job.original_file_name + assert result.created_at == job.created_at + assert result.sent == sent + assert result.delivered == delivered + assert result.failed == failed + + +def stats_set_up(notify_db, notify_db_session, service): + job_1 = create_job(notify_db=notify_db, notify_db_session=notify_db_session, + service=service, created_at=datetime.utcnow() - timedelta(days=2)) + job_2 = create_job(notify_db=notify_db, notify_db_session=notify_db_session, + service=service, original_file_name='Another job') + notification = create_notification(notify_db=notify_db, notify_db_session=notify_db_session, job=job_1) + notification_delivered = create_notification(notify_db=notify_db, notify_db_session=notify_db_session, + job=job_1, status='delivered') + notification_failed = create_notification(notify_db=notify_db, notify_db_session=notify_db_session, job=job_2, + status='permanent-failure') + create_or_update_job_sending_statistics(notification) + create_or_update_job_sending_statistics(notification_delivered) + create_or_update_job_sending_statistics(notification_failed) + update_job_stats_outcome_count(notification_delivered) + update_job_stats_outcome_count(notification_failed) + return job_1, job_2