-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update get play metrics query to use hourly_play_counts (#2195)
* Update get play metrics query to use hourly_play_counts * Add typed arg * add typed session arg
- Loading branch information
Showing
3 changed files
with
155 additions
and
58 deletions.
There are no files selected for viewing
161 changes: 123 additions & 38 deletions
161
discovery-provider/integration_tests/queries/test_get_plays_metrics.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,73 +1,158 @@ | ||
import time | ||
from datetime import datetime, timedelta | ||
|
||
from src.models import Play | ||
from src.queries.get_plays_metrics import _get_plays_metrics | ||
from integration_tests.utils import populate_mock_db | ||
from src.queries.get_plays_metrics import GetPlayMetricsArgs, _get_plays_metrics | ||
from src.tasks.index_hourly_play_counts import _index_hourly_play_counts | ||
from src.utils.db_session import get_db | ||
|
||
DAYS_IN_A_YEAR = 365 | ||
|
||
def populate_mock_db(db, date1, date2): | ||
"""Helper function to populate thee mock DB with plays""" | ||
test_plays = [ | ||
{"item_id": 1, "created_at": date1}, | ||
{"item_id": 1, "created_at": date1}, | ||
{"item_id": 1, "created_at": date2}, | ||
{"item_id": 2, "created_at": date1}, | ||
{"item_id": 2, "created_at": date2}, | ||
{"item_id": 3, "created_at": date2}, | ||
{"item_id": 3, "created_at": date2}, | ||
{"item_id": 3, "created_at": date2}, | ||
] | ||
|
||
with db.scoped_session() as session: | ||
for i, play_meta in enumerate(test_plays): | ||
play = Play( | ||
id=i, | ||
play_item_id=play_meta.get("item_id"), | ||
created_at=play_meta.get("created_at", datetime.now()), | ||
) | ||
session.add(play) | ||
def format_date(date): | ||
return int(time.mktime(date.timetuple())) | ||
|
||
|
||
def test_get_plays_metrics(app): | ||
"""Tests that plays metrics can be queried""" | ||
|
||
date = datetime(2020, 10, 4).replace(minute=0, second=0, microsecond=0) | ||
date1 = date + timedelta(hours=-1) | ||
date2 = date + timedelta(days=-2) | ||
before_date = date + timedelta(days=-3) | ||
|
||
with app.app_context(): | ||
db = get_db() | ||
|
||
populate_mock_db(db, date1, date2) | ||
|
||
args = {"limit": 10, "start_time": before_date, "bucket_size": "hour"} | ||
date = datetime(2020, 10, 4).replace(minute=0, second=0, microsecond=0) | ||
test_entities = { | ||
"tracks": [ | ||
{"track_id": 1, "title": "track 1"}, | ||
{"track_id": 2, "title": "track 2"}, | ||
{"track_id": 3, "title": "track 3"}, | ||
], | ||
"plays": [ | ||
{"item_id": 1, "created_at": date + timedelta(hours=-1)}, | ||
{"item_id": 1, "created_at": date + timedelta(hours=-1)}, | ||
{"item_id": 1, "created_at": date + timedelta(days=-2)}, | ||
{"item_id": 2, "created_at": date + timedelta(hours=-1)}, | ||
{"item_id": 2, "created_at": date + timedelta(days=-2)}, | ||
{"item_id": 3, "created_at": date + timedelta(days=-2)}, | ||
{"item_id": 3, "created_at": date + timedelta(days=-2)}, | ||
{"item_id": 3, "created_at": date + timedelta(days=-2)}, | ||
], | ||
} | ||
|
||
populate_mock_db(db, test_entities) | ||
|
||
args = GetPlayMetricsArgs( | ||
limit=10, | ||
start_time=date + timedelta(days=-3), | ||
bucket_size="hour", | ||
) | ||
|
||
with db.scoped_session() as session: | ||
_index_hourly_play_counts(session) | ||
metrics = _get_plays_metrics(session, args) | ||
|
||
assert len(metrics) == 2 | ||
assert metrics[0]["timestamp"] == format_date(date + timedelta(hours=-1)) | ||
assert metrics[0]["count"] == 3 | ||
assert metrics[1]["timestamp"] == format_date(date + timedelta(days=-2)) | ||
assert metrics[1]["count"] == 5 | ||
|
||
|
||
def test_get_plays_metrics_with_weekly_buckets(app): | ||
"""Tests that plays metrics can be queried with weekly buckets""" | ||
# A Thursday | ||
date = datetime(2020, 10, 1).replace(minute=0, second=0, microsecond=0) | ||
date1 = date + timedelta(hours=-1) | ||
date2 = date + timedelta(days=-2) | ||
before_date = date + timedelta(days=-3) | ||
|
||
with app.app_context(): | ||
db = get_db() | ||
|
||
populate_mock_db(db, date1, date2) | ||
|
||
args = {"limit": 10, "start_time": before_date, "bucket_size": "week"} | ||
# A Thursday | ||
date = datetime(2020, 10, 1).replace(minute=0, second=0, microsecond=0) | ||
test_entities = { | ||
"tracks": [ | ||
{"track_id": 1, "title": "track 1"}, | ||
{"track_id": 2, "title": "track 2"}, | ||
{"track_id": 3, "title": "track 3"}, | ||
], | ||
"plays": [ | ||
{"item_id": 1, "created_at": date + timedelta(hours=-1)}, | ||
{"item_id": 1, "created_at": date + timedelta(hours=-1)}, | ||
{"item_id": 1, "created_at": date + timedelta(days=-2)}, | ||
{"item_id": 2, "created_at": date + timedelta(hours=-1)}, | ||
{"item_id": 2, "created_at": date + timedelta(days=-2)}, | ||
{"item_id": 3, "created_at": date + timedelta(days=-2)}, | ||
{"item_id": 3, "created_at": date + timedelta(days=-2)}, | ||
{"item_id": 3, "created_at": date + timedelta(days=-2)}, | ||
], | ||
} | ||
|
||
populate_mock_db(db, test_entities) | ||
|
||
start_time = date + timedelta(days=-3) | ||
args = GetPlayMetricsArgs( | ||
limit=10, | ||
start_time=date + timedelta(days=-3), | ||
bucket_size="week", | ||
) | ||
|
||
with db.scoped_session() as session: | ||
_index_hourly_play_counts(session) | ||
metrics = _get_plays_metrics(session, args) | ||
|
||
assert len(metrics) == 1 | ||
assert metrics[0]["count"] == 8 | ||
assert metrics[0]["timestamp"] == format_date(start_time) | ||
|
||
|
||
def test_get_plays_metrics_with_yearly_buckets(app): | ||
"""Tests that plays metrics can be queried""" | ||
|
||
with app.app_context(): | ||
db = get_db() | ||
|
||
date = datetime(2020, 10, 4).replace(minute=0, second=0, microsecond=0) | ||
test_entities = { | ||
"tracks": [ | ||
{"track_id": 1, "title": "track 1"}, | ||
{"track_id": 2, "title": "track 2"}, | ||
{"track_id": 3, "title": "track 3"}, | ||
], | ||
"plays": [ | ||
{"item_id": 1, "created_at": date + timedelta(days=-3 * DAYS_IN_A_YEAR)}, | ||
{"item_id": 1, "created_at": date + timedelta(days=-3 * DAYS_IN_A_YEAR)}, | ||
{"item_id": 3, "created_at": date + timedelta(days=-3 * DAYS_IN_A_YEAR)}, | ||
{"item_id": 1, "created_at": date + timedelta(days=-2 * DAYS_IN_A_YEAR)}, | ||
{"item_id": 2, "created_at": date + timedelta(days=-2 * DAYS_IN_A_YEAR)}, | ||
{"item_id": 3, "created_at": date + timedelta(days=-1 * DAYS_IN_A_YEAR)}, | ||
{"item_id": 3, "created_at": date + timedelta(days=-1)}, | ||
{"item_id": 3, "created_at": date + timedelta(weeks=-1)}, | ||
], | ||
} | ||
|
||
populate_mock_db(db, test_entities) | ||
|
||
start_time = date + timedelta( | ||
days=-3 * DAYS_IN_A_YEAR - 1 | ||
) # -1 extra day to be inclusive | ||
args = GetPlayMetricsArgs( | ||
limit=10, | ||
start_time=start_time, | ||
bucket_size="year", | ||
) | ||
|
||
with db.scoped_session() as session: | ||
_index_hourly_play_counts(session) | ||
metrics = _get_plays_metrics(session, args) | ||
|
||
assert len(metrics) == 4 | ||
assert metrics[0]["count"] == 2 | ||
assert metrics[0]["timestamp"] == format_date(date.replace(day=1, month=1)) | ||
assert metrics[1]["count"] == 1 | ||
assert metrics[1]["timestamp"] == format_date( | ||
(date + timedelta(days=-1 * DAYS_IN_A_YEAR)).replace(day=1, month=1) | ||
) | ||
assert metrics[2]["count"] == 2 | ||
assert metrics[2]["timestamp"] == format_date( | ||
(date + timedelta(days=-2 * DAYS_IN_A_YEAR)).replace(day=1, month=1) | ||
) | ||
assert metrics[3]["count"] == 3 | ||
assert metrics[3]["timestamp"] == format_date( | ||
(date + timedelta(days=-3 * DAYS_IN_A_YEAR)).replace(day=1, month=1) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters