From 106187ba04418086650a2fa465dfcac7a0c85bfe Mon Sep 17 00:00:00 2001 From: David McDonald Date: Mon, 22 Nov 2021 11:11:52 +0000 Subject: [PATCH] Fix division by zero error on performance page For preview and staging environments, we often send no messages in a single day. This is currently causing a `DivisionByZero` error that is rendering the page with no results. This makes it impossible to look at preview/staging and see if the performance page is working correctly or not. (psycopg2.errors.DivisionByZero) division by zero [SQL: SELECT CAST(ft_processing_time.bst_date AS TEXT) AS date, ft_processing_time.messages_total AS ft_processing_time_messages_total, ft_processing_time.messages_within_10_secs AS ft_processing_time_messages_within_10_secs, (ft_processing_time.messages_within_10_secs / CAST(ft_processing_time.messages_total AS FLOAT)) * %(param_1)s AS percentage FROM ft_processing_time WHERE ft_processing_time.bst_date >= %(bst_date_1)s AND ft_processing_time.bst_date <= %(bst_date_2)s ORDER BY ft_processing_time.bst_date] [parameters: {'param_1': 100, 'bst_date_1': datetime.date(2021, 11, 12), 'bst_date_2': datetime.date(2021, 11, 19)}] (Background on this error at: http://sqlalche.me/e/14/9h9h) I've fixed this by falling back to 100.0% for days we send no messages. Maybe some argument that it should be N/A rather than 100% but I think it doesn't really matter as this is only going to affect preview and staging as we will never have a day sending no messages in production. --- app/dao/fact_processing_time_dao.py | 10 +++++-- .../app/dao/test_fact_processing_time_dao.py | 26 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/app/dao/fact_processing_time_dao.py b/app/dao/fact_processing_time_dao.py index c2559ac9b..ddb4c4bf8 100644 --- a/app/dao/fact_processing_time_dao.py +++ b/app/dao/fact_processing_time_dao.py @@ -1,6 +1,7 @@ from datetime import datetime from sqlalchemy.dialects.postgresql import insert +from sqlalchemy.sql.expression import case from app import db from app.dao.dao_utils import autocommit @@ -37,8 +38,13 @@ def get_processing_time_percentage_for_date_range(start_date, end_date): FactProcessingTime.bst_date.cast(db.Text).label("date"), FactProcessingTime.messages_total, FactProcessingTime.messages_within_10_secs, - ((FactProcessingTime.messages_within_10_secs / FactProcessingTime.messages_total.cast( - db.Float)) * 100).label("percentage") + case([ + ( + FactProcessingTime.messages_total > 0, + ((FactProcessingTime.messages_within_10_secs / FactProcessingTime.messages_total.cast(db.Float)) * 100) + ), + (FactProcessingTime.messages_total == 0, 100.0) + ]).label("percentage") ).filter( FactProcessingTime.bst_date >= start_date, FactProcessingTime.bst_date <= end_date diff --git a/tests/app/dao/test_fact_processing_time_dao.py b/tests/app/dao/test_fact_processing_time_dao.py index e731fac8f..206245153 100644 --- a/tests/app/dao/test_fact_processing_time_dao.py +++ b/tests/app/dao/test_fact_processing_time_dao.py @@ -70,3 +70,29 @@ def test_get_processing_time_percentage_for_date_range(notify_db_session): assert results[0].messages_total == 3 assert results[0].messages_within_10_secs == 2 assert round(results[0].percentage, 1) == 66.7 + + +def test_get_processing_time_percentage_for_date_range_handles_zero_cases(notify_db_session): + create_process_time( + bst_date='2021-02-21', + messages_total=0, + messages_within_10_secs=0 + ) + create_process_time( + bst_date='2021-02-22', + messages_total=10, + messages_within_10_secs=0 + ) + + results = get_processing_time_percentage_for_date_range('2021-02-21', '2021-02-22') + + assert len(results) == 2 + assert results[0].date == '2021-02-21' + assert results[0].messages_total == 0 + assert results[0].messages_within_10_secs == 0 + assert results[0].percentage == 100.0 + + assert results[1].date == '2021-02-22' + assert results[1].messages_total == 10 + assert results[1].messages_within_10_secs == 0 + assert results[1].percentage == 0.0