diff --git a/discovery-provider/src/queries/get_latest_play.py b/discovery-provider/src/queries/get_latest_play.py new file mode 100644 index 00000000000..43b9dd5fe55 --- /dev/null +++ b/discovery-provider/src/queries/get_latest_play.py @@ -0,0 +1,14 @@ +from src.models import Play +from src.utils import db_session + +def get_latest_play(): + """ + Gets the latest play in the database + """ + db = db_session.get_db_read_replica() + with db.scoped_session() as session: + play_query = session.query(Play.created_at).order_by( + Play.created_at.desc() + ).limit(1) + play = play_query.scalar() + return play diff --git a/discovery-provider/src/queries/get_latest_play_test.py b/discovery-provider/src/queries/get_latest_play_test.py new file mode 100644 index 00000000000..8a2f719cb18 --- /dev/null +++ b/discovery-provider/src/queries/get_latest_play_test.py @@ -0,0 +1,30 @@ +from datetime import datetime +from src.queries.get_latest_play import get_latest_play +from src.models import Play + +def test_get_latest_play(db_mock): + """Tests that the latest play is returned""" + date1 = datetime(2020, 10, 4, 10, 35, 0) + date2 = datetime(2020, 10, 1, 10, 10, 0) + date3 = datetime(2020, 9, 20, 8, 1, 0) + + with db_mock.scoped_session() as session: + Play.__table__.create(db_mock._engine) + session.add(Play( + user_id=1, + play_item_id=1, + created_at=date1 + )) + session.add(Play( + user_id=2, + play_item_id=1, + created_at=date2 + )) + session.add(Play( + user_id=3, + play_item_id=2, + created_at=date3 + )) + + latest_play = get_latest_play() + assert latest_play == date1 diff --git a/discovery-provider/src/queries/get_playlists.py b/discovery-provider/src/queries/get_playlists.py index b534dc853ce..ebaeb8a6d19 100644 --- a/discovery-provider/src/queries/get_playlists.py +++ b/discovery-provider/src/queries/get_playlists.py @@ -76,7 +76,10 @@ def get_unpopulated_playlists(): # if we passed in a current_user_id, filter out all privte playlists where # the owner_id doesn't match the current_user_id if current_user_id: - playlists = list(filter(lambda playlist: (not playlist["is_private"]) or playlist["playlist_owner_id"] == current_user_id, playlists)) + playlists = list(filter( + lambda playlist: (not playlist["is_private"]) or playlist["playlist_owner_id"] == current_user_id, + playlists) + ) # retrieve playlist ids list playlist_ids = list(map(lambda playlist: playlist["playlist_id"], playlists)) diff --git a/discovery-provider/src/queries/health_check.py b/discovery-provider/src/queries/health_check.py index f1880009530..13dba4dfc5f 100644 --- a/discovery-provider/src/queries/health_check.py +++ b/discovery-provider/src/queries/health_check.py @@ -1,7 +1,9 @@ +from datetime import datetime import logging from flask import Blueprint, request +from src.queries.get_latest_play import get_latest_play from src.queries.queries import parse_bool_param -from src.api_helpers import success_response_backwards_compat +from src.api_helpers import success_response, success_response_backwards_compat from src.queries.get_health import get_health from src.utils import helpers @@ -50,3 +52,20 @@ def block_check(): health_results, 500 if error else 200 ) + +# Health check for latest play stored in the db +@bp.route("/play_check", methods=["GET"]) +def play_check(): + """ + max_drift: maximum duration in seconds between `now` and the + latest recorded play record to be considered healthy + """ + max_drift = request.args.get("max_drift", type=int) + + latest_play = get_latest_play() + drift = (datetime.now() - latest_play).total_seconds() + + # Error if max drift was provided and the drift is greater than max_drift + error = max_drift and drift > max_drift + + return success_response(latest_play, 500 if error else 200) diff --git a/discovery-provider/src/utils/helpers.py b/discovery-provider/src/utils/helpers.py index 23635dc28f1..1dbcecaf898 100644 --- a/discovery-provider/src/utils/helpers.py +++ b/discovery-provider/src/utils/helpers.py @@ -1,8 +1,8 @@ import datetime -from json.encoder import JSONEncoder import logging import os import json +from json.encoder import JSONEncoder import re import time import contextlib