From 8dc90230d70fde1cb2adf390835980ec8b9b520e Mon Sep 17 00:00:00 2001 From: Matias Bordese Date: Mon, 21 Oct 2024 13:48:07 -0300 Subject: [PATCH] Update shift change notification to consider microsecond timestamps (#5196) Related to https://github.com/grafana/support-escalations/issues/12893 --- .../tasks/notify_ical_schedule_shift.py | 14 +++++-- .../tests/test_notify_ical_schedule_shift.py | 39 +++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/engine/apps/alerts/tasks/notify_ical_schedule_shift.py b/engine/apps/alerts/tasks/notify_ical_schedule_shift.py index e872623d6d..fb797cfb18 100644 --- a/engine/apps/alerts/tasks/notify_ical_schedule_shift.py +++ b/engine/apps/alerts/tasks/notify_ical_schedule_shift.py @@ -90,11 +90,17 @@ def notify_ical_schedule_shift(schedule_pk): prev_shifts = convert_prev_shifts_to_new_format(prev_shifts, schedule) prev_shifts_updated = True - # convert datetimes which was dumped to str back to datetime to calculate shift diff correct - str_format = "%Y-%m-%d %X%z" + def _parse_timestamp(timestamp: str) -> datetime.datetime: + # convert datetimes which was dumped to str back to datetime to calculate shift diff correct + try: + dt = datetime.datetime.strptime(timestamp, "%Y-%m-%d %X%z") + except ValueError: + dt = datetime.datetime.strptime(timestamp, "%Y-%m-%d %X.%f%z") + return dt + for prev_shift in prev_shifts: - prev_shift["start"] = datetime.datetime.strptime(prev_shift["start"], str_format) - prev_shift["end"] = datetime.datetime.strptime(prev_shift["end"], str_format) + prev_shift["start"] = _parse_timestamp(prev_shift["start"]) + prev_shift["end"] = _parse_timestamp(prev_shift["end"]) # get shifts in progress now now = datetime.datetime.now(datetime.timezone.utc) diff --git a/engine/apps/alerts/tests/test_notify_ical_schedule_shift.py b/engine/apps/alerts/tests/test_notify_ical_schedule_shift.py index 2833a826ff..deb5fc1e54 100644 --- a/engine/apps/alerts/tests/test_notify_ical_schedule_shift.py +++ b/engine/apps/alerts/tests/test_notify_ical_schedule_shift.py @@ -498,6 +498,45 @@ def test_next_shift_changes_no_triggering_notification( assert not mock_slack_api_call.called +@pytest.mark.django_db +def test_current_shifts_using_microseconds( + make_organization_and_user_with_slack_identities, + make_user, + make_schedule, +): + organization, _, _, _ = make_organization_and_user_with_slack_identities() + user1 = make_user(organization=organization, username="user1") + schedule = make_schedule( + organization, + schedule_class=OnCallScheduleCalendar, + name="test_schedule", + channel="channel", + prev_ical_file_overrides=None, + cached_ical_file_overrides=None, + ) + schedule.refresh_ical_file() + schedule.current_shifts = json.dumps( + { + "test_shift_uid": { + "users": [user1.pk], + "start": timezone.now().replace(microsecond=123456), + "end": timezone.now().replace(microsecond=654321) + timezone.timedelta(days=1), + "all_day": False, + "priority": 1, + "priority_increased_by": 0, + } + }, + default=str, + ) + schedule.empty_oncall = False + schedule.save() + + with patch("apps.slack.client.SlackClient.chat_postMessage") as mock_slack_api_call: + notify_ical_schedule_shift(schedule.pk) + + assert mock_slack_api_call.called + + @pytest.mark.django_db def test_lower_priority_changes_no_triggering_notification( make_organization_and_user_with_slack_identities,