Skip to content

Commit

Permalink
[staged-updates] v2, removes that database query entirely, we just we…
Browse files Browse the repository at this point in the history
…re not using the cached value.
  • Loading branch information
biblicabeebli committed Aug 29, 2024
1 parent a5ffd86 commit 2fb75f9
Show file tree
Hide file tree
Showing 5 changed files with 6 additions and 44 deletions.
40 changes: 2 additions & 38 deletions database/user_models_participant.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,43 +255,6 @@ def log(self, action: str):
################################################################################################
################################## PARTICIPANT STATE ###########################################
################################################################################################
# FIXME: make this a cached value

@property
def last_app_heartbeat(self) -> Optional[datetime]:
""" Returns the last time the app sent a heartbeat.
`self.heartbeats.latest("timestamp")` emits the following SQL:
SELECT "database_appheartbeats"."id",
"database_appheartbeats"."participant_id",
"database_appheartbeats"."timestamp",
"database_appheartbeats"."message"
FROM "database_appheartbeats"
WHERE "database_appheartbeats"."participant_id" = 8051
ORDER BY "database_appheartbeats"."timestamp" DESC
LIMIT 1
This is slow because it is... slow.
`self.heartbeats.aggregate(min=Min("timestamp"))` emits
SELECT MIN("database_appheartbeats"."timestamp") AS "min"
FROM "database_appheartbeats"
WHERE "database_appheartbeats"."participant_id" = 8051
is like 10x faster but still too slow, the where clause is probably not using the index?
Current implementation:
`.values_list("heartbeats__timestamp").aggregate(min=Min("heartbeats__timestamp"))` emits
SELECT MIN("database_appheartbeats"."timestamp") AS "min"
FROM "database_participant"
LEFT OUTER JOIN "database_appheartbeats"
ON ("database_participant"."id" = "database_appheartbeats"."participant_id")
WHERE "database_participant"."id" = 8051
This can take 10ms, it seems to get cached.
"""
return (
Participant.objects.filter(id=self.id)
.values_list("heartbeats__timestamp")
.aggregate(min=Min("heartbeats__timestamp"))['min']
)

@property
def is_active_one_week(self) -> bool:
Expand Down Expand Up @@ -551,7 +514,7 @@ def summary(cls):
class AppHeartbeats(UtilityModel):
""" Storing heartbeats is intended as a debugging tool for monitoring app uptime, the idea is
that the app checks in every 5 minutes so we can see when it doesn't. (And then send it a push
notification) """
notification) """
participant = models.ForeignKey(Participant, null=False, on_delete=models.PROTECT, related_name="heartbeats")
timestamp = models.DateTimeField(null=False, blank=False, db_index=True)
# TODO: message is not intended to be surfaced to anyone other than developers, at time of comment
Expand All @@ -560,6 +523,7 @@ class AppHeartbeats(UtilityModel):

@classmethod
def create(cls, participant: Participant, timestamp: datetime, message: str = None):
participant.update_only(last_heartbeat_checkin=timestamp)
return cls.objects.create(participant=participant, timestamp=timestamp, message=message)


Expand Down
2 changes: 1 addition & 1 deletion endpoints/mobile_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,8 @@ def mobile_heartbeat(request: ParticipantRequest, OS_API=""):
This endpoint is hit every 5 minutes by the app, at time of writing it is ios-only. """
# a field on the participant model is WAY easier to deal with when querying data for push notifications
now = timezone.now()
request.session_participant.update_only(last_heartbeat_checkin=now)
# AppHeartbeats is the historical record of app checkins.
# .create updates the field on the participant.
AppHeartbeats.create(participant=request.session_participant, timestamp=now,
message = request.POST.get("message", None))
return HttpResponse(status=200)
Expand Down
2 changes: 1 addition & 1 deletion frontend/templates/participant.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ <h3 class="text-center"> <b>Activity Information </b></h3>
</tr>
<tr>
<td><b>Last Heartbeat</b></td>
<td>{{ really_nice_time_format_with_tz(participant_last_app_heartbeat, study_timezone) }}</td>
<td>{{ really_nice_time_format_with_tz(participant.last_heartbeat_checkin, study_timezone) }}</td>
</tr>
<tr>
<td><b>Last check-in for updated surveys</b></td>
Expand Down
2 changes: 0 additions & 2 deletions libs/endpoint_helpers/participant_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ def render_participant_page(request: ResearcherRequest, participant: Participant
)

conditionally_display_locked_message(request, participant)
last_app_heartbeat = participant.last_app_heartbeat
study_interventions_exists = study.interventions.exists()
study_fields_exists = study.fields.exists()
relation = request.session_researcher.get_study_relation(study.id)
Expand All @@ -76,7 +75,6 @@ def render_participant_page(request: ResearcherRequest, participant: Participant
locked=participant.is_dead,
can_delete=can_delete,
study_timezone=participant.study.timezone,
participant_last_app_heartbeat=last_app_heartbeat,
study_interventions_exists=study_interventions_exists,
study_fields_exists=study_fields_exists,
)
Expand Down
4 changes: 2 additions & 2 deletions libs/utils/http_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import functools
from datetime import datetime, tzinfo
from typing import Callable, Dict, List, Union
from typing import Callable, Dict, List, Optional, Union

from dateutil import tz
from django.http.request import HttpRequest
Expand Down Expand Up @@ -39,7 +39,7 @@ def nice_iso_time_format(dt: datetime, timezone: Union[tzinfo, str]) -> str:
return final_dt.strftime('%A %Y-%m-%d, %-I:%M %p')


def really_nice_time_format_with_tz(dt: datetime, timezone: Union[tzinfo, str]) -> str:
def really_nice_time_format_with_tz(dt: Optional[datetime], timezone: Union[tzinfo, str]) -> str:
""" output looks like Tuesday Aug 25, 2020, 4:31 PM (EST) """
if dt is None:
return ""
Expand Down

0 comments on commit 2fb75f9

Please sign in to comment.