Skip to content

Commit

Permalink
Change the datetimes
Browse files Browse the repository at this point in the history
- We want query the facts table for 6 days prev to the current day
- We want to query notifications for todays data. due to timezones/ and
  when the job runs to populate facts, we will take the max existing
  date in facts from the last 6 days and use that as a starting point to
  query notifications for
- We added a filter for notification_type as there is a part in the
  frontend that fetches this query only for a singular notification type
  • Loading branch information
jzbahrai committed Sep 25, 2024
1 parent 793e947 commit f06bc14
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 139 deletions.
75 changes: 55 additions & 20 deletions app/dao/fact_notification_status_dao.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from datetime import datetime, time, timedelta
from datetime import datetime, time, timedelta, timezone

from flask import current_app
from sqlalchemy import Date, case, func
Expand All @@ -7,7 +7,7 @@
from sqlalchemy.types import DateTime, Integer

from app import db
from app.dao.date_util import tz_aware_midnight_n_days_ago, utc_midnight_n_days_ago
from app.dao.date_util import get_query_date_based_on_retention_period
from app.models import (
EMAIL_TYPE,
KEY_TYPE_NORMAL,
Expand Down Expand Up @@ -241,32 +241,41 @@ def fetch_notification_status_for_service_for_day(bst_day, service_id):
)


def fetch_notification_status_for_service_for_today_and_7_previous_days(service_id, by_template=False, limit_days=7):
if limit_days == 1:
ft_start_date = utc_midnight_n_days_ago(limit_days - 1)
# For daily stats, service limits reset at 12:00am UTC each night, so we need to fetch the data from 12:00 UTC to now
start = utc_midnight_n_days_ago(0)
end = datetime.utcnow()
else:
ft_start_date = utc_midnight_n_days_ago(limit_days)

# The nightly task that populates ft_notification_status counts collects notifications from
# 5AM the day before to 5AM of the current day. So we need to match that timeframe when
# we fetch notifications for the current day.
start = (tz_aware_midnight_n_days_ago(1) + timedelta(hours=5)).replace(minute=0, second=0, microsecond=0)
end = (tz_aware_midnight_n_days_ago(0) + timedelta(hours=5)).replace(minute=0, second=0, microsecond=0)
def _stats_for_days_facts(service_id, start_time, by_template=False, notification_type=None):
"""
We want to take the data from the fact_notification_status table for bst_data>=start_date
Returns:
Aggregate data in a certain format for total notifications
"""
stats_for_7_days = db.session.query(
FactNotificationStatus.notification_type.label("notification_type"),
FactNotificationStatus.notification_status.label("status"),
*([FactNotificationStatus.template_id.label("template_id")] if by_template else []),
*([FactNotificationStatus.notification_count.label("count")]),
).filter(
FactNotificationStatus.service_id == service_id,
FactNotificationStatus.bst_date >= ft_start_date,
FactNotificationStatus.bst_date >= start_time,
FactNotificationStatus.key_type != KEY_TYPE_TEST,
)

if notification_type:
stats_for_7_days = stats_for_7_days.filter(FactNotificationStatus.notification_type == notification_type)

return stats_for_7_days


def _timing_notification_table(service_id):
max_date_from_facts = (
FactNotificationStatus.query.with_entities(func.max(FactNotificationStatus.bst_date))
.filter(FactNotificationStatus.service_id == service_id)
.scalar()
)
date_to_use = max_date_from_facts + timedelta(days=1) if max_date_from_facts else datetime.now(timezone.utc)
return datetime.combine(date_to_use, time.min)


def _stats_for_today(service_id, start_time, by_template=False, notification_type=None):
stats_for_today = (
db.session.query(
Notification.notification_type.cast(db.Text),
Expand All @@ -275,8 +284,7 @@ def fetch_notification_status_for_service_for_today_and_7_previous_days(service_
*([func.count().label("count")]),
)
.filter(
Notification.created_at >= start,
Notification.created_at <= end,
Notification.created_at >= start_time,
Notification.service_id == service_id,
Notification.key_type != KEY_TYPE_TEST,
)
Expand All @@ -286,8 +294,35 @@ def fetch_notification_status_for_service_for_today_and_7_previous_days(service_
Notification.status,
)
)
if notification_type:
stats_for_today = stats_for_today.filter(Notification.notification_type == notification_type)

return stats_for_today


def fetch_notification_status_for_service_for_today_and_7_previous_days(
service_id, by_template=False, limit_days=7, notification_type=None
):
"""
We want to take the data from the fact_notification_status table and the notifications table and combine them
We will take the data from notifications ONLY for today and the fact_notification_status for the last 6 days
In total we will have 7 days worth of data
Args:
service_id (uuid): _description_
by_template (bool, optional): _description_. Defaults to False.
limit_days (int, optional): _description_. Defaults to 7.
Returns:
Aggregate data in a certain format for total notifications
"""
facts_notification_start_time = get_query_date_based_on_retention_period(limit_days)
stats_from_facts = _stats_for_days_facts(service_id, facts_notification_start_time, by_template, notification_type)

start_time_notify_table = _timing_notification_table(service_id)
stats_for_today = _stats_for_today(service_id, start_time_notify_table, by_template, notification_type)

all_stats_table = stats_for_7_days.union_all(stats_for_today).subquery()
all_stats_table = stats_from_facts.union_all(stats_for_today).subquery()

query = db.session.query(
*(
Expand Down
Loading

0 comments on commit f06bc14

Please sign in to comment.