forked from GithubBackups/healthchecks
Profile.next_nag_date tracks when the next hourly/daily reminder should be sent. Normally, sendalerts sets this field when a check goes down, and sendreports clears it out whenever it is about to send a reminder but realizes all checks are up. The problem: sendalerts can set next_nag_date to a non-null value, but it does not clear it out when all checks are up. This can result in a hourly/daily reminder being sent out at the wrong time. Specific example, assuming hourly reminders: 13:00: Check A goes down. next_nag_date gets set to 14:00. 13:05: Check A goes up. next_nag_date remains set to 14:00. 13:55: Check B goes down. next_nag_date remains set to 14:00. 14:00: Healthchecks sends a hourly reminder, just 5 minutes after Check B going down. It should have sent the reminder at 13:55 + 1 hour = 14:55 The fix: sendalerts can now both set and clear the next_nag_date field. The main changes are in Project.update_next_nag_dates() and in Profile.update_next_nag_date(). With the fix: 13:00: Check A goes down. next_nag_date gets set to 14:00. 13:05: Check A goes up. next_nag_date gets set to null. 13:55: Check B goes down. next_nag_date gets set to 14:55. 14:55: Healthchecks sends a hourly reminder.
37 lines
1.2 KiB
Python
37 lines
1.2 KiB
Python
from datetime import timedelta as td
|
|
|
|
from django.utils.timezone import now
|
|
from hc.test import BaseTestCase
|
|
from hc.api.models import Check
|
|
|
|
|
|
class ProfileModelTestCase(BaseTestCase):
|
|
def test_it_sets_next_nag_date(self):
|
|
Check.objects.create(project=self.project, status="down")
|
|
|
|
self.profile.nag_period = td(hours=1)
|
|
self.profile.update_next_nag_date()
|
|
|
|
self.assertTrue(self.profile.next_nag_date)
|
|
|
|
def test_it_does_not_set_next_nag_date_if_no_nag_period(self):
|
|
Check.objects.create(project=self.project, status="down")
|
|
self.profile.update_next_nag_date()
|
|
self.assertIsNone(self.profile.next_nag_date)
|
|
|
|
def test_it_does_not_update_existing_next_nag_date(self):
|
|
Check.objects.create(project=self.project, status="down")
|
|
|
|
original_nag_date = now() - td(minutes=30)
|
|
|
|
self.profile.next_nag_date = original_nag_date
|
|
self.profile.nag_period = td(hours=1)
|
|
self.profile.update_next_nag_date()
|
|
|
|
self.assertEqual(self.profile.next_nag_date, original_nag_date)
|
|
|
|
def test_it_clears_next_nag_date(self):
|
|
self.profile.next_nag_date = now()
|
|
self.profile.update_next_nag_date()
|
|
self.assertIsNone(self.profile.next_nag_date)
|