Refine the logic for recording the nominal sent age of the mail

In the previous iteration, if we were ever down/frozen/disabled long enough
to miss sending two mails in a row, we would see unintended "catch-up"
behavior where each subsequent run of britney would send a mail until the
right total number of mails had been sent.  Don't do this; instead, catch us
up in one go to the most recent mail that should have been sent, avoiding
bunching of notifications.

This changes one of the tests also to match.
This commit is contained in:
Steve Langasek 2017-07-06 21:14:19 -07:00
parent d5040afb84
commit 132ffaf465
2 changed files with 12 additions and 12 deletions

View File

@ -190,25 +190,25 @@ class EmailPolicy(BasePolicy, Rest):
emails, last_sent = cached emails, last_sent = cached
# migration of older data # migration of older data
last_sent = int(last_sent) last_sent = int(last_sent)
if last_sent < max_age: last_due = int(math.pow(2, int(math.log(age + 2 - max_age, 2)))
next_due = max_age + max_age - 2)
else: if last_due - max_age >= MAX_INTERVAL:
next_due = int(math.pow(2, last_due = int((age - max_age - MAX_INTERVAL) / MAX_INTERVAL) \
int(math.log(last_sent - max_age + 1, * MAX_INTERVAL + max_age + MAX_INTERVAL
2))+1) + last_sent) if last_due < max_age:
if next_due - last_sent > MAX_INTERVAL: last_due = max_age
next_due = last_sent + MAX_INTERVAL
except TypeError: except TypeError:
# This exception happens when source_name, version never seen before # This exception happens when source_name, version never seen before
emails = [] emails = []
last_sent = 0 last_sent = 0
next_due = max_age last_due = max_age
if self.dry_run: if self.dry_run:
self.log("[email dry run] Age %d >= threshold %d: would email: %s" % self.log("[email dry run] Age %d >= threshold %d: would email: %s" %
(age, max_age, self.lp_get_emails(source_name, version))) (age, max_age, self.lp_get_emails(source_name, version)))
# don't update the cache file in dry run mode; we'll see all output each time # don't update the cache file in dry run mode; we'll see all output each time
return PolicyVerdict.PASS return PolicyVerdict.PASS
if age >= next_due: if last_sent < last_due:
if not emails: if not emails:
emails = self.lp_get_emails(source_name, version) emails = self.lp_get_emails(source_name, version)
if emails: if emails:
@ -221,7 +221,7 @@ class EmailPolicy(BasePolicy, Rest):
server.sendmail('noreply@canonical.com', emails, msg) server.sendmail('noreply@canonical.com', emails, msg)
server.quit() server.quit()
# record the age at which the mail should have been sent # record the age at which the mail should have been sent
last_sent = next_due last_sent = last_due
except socket.error as err: except socket.error as err:
self.log("Failed to send mail! Is SMTP server running?") self.log("Failed to send mail! Is SMTP server running?")
self.log(err) self.log(err)

View File

@ -266,7 +266,7 @@ class T(unittest.TestCase):
1, 3, 5, 7, 11, 19, 35, 65, 95, 125, 155, 185 1, 3, 5, 7, 11, 19, 35, 65, 95, 125, 155, 185
]) ])
self.smtp_repetition(valid=[False, False, True, False, True], expected=[ self.smtp_repetition(valid=[False, False, True, False, True], expected=[
1, 3, 5, 13, 29, 59, 89, 119, 149, 179 1, 3, 5, 7, 11, 19, 35, 65, 95, 125, 155, 185
]) ])