... and pass it to Transport.notify_flip().
This allows us to pass flip-specific information (the flip timestamp,
the new status) to transport classes.
I'm planning to change Channel.notify() signature to take a Flip
object as an argument instead of a Check object. This change is
in preparation for these changes.
If the recipient has set up an username, the responses
from Signal will return "number": null.
Example scenario:
* Alice sets up a Signal integration
* Alice sets up an username for their Signal account
* Alice deletes their Signal account
* Healthchecks sends a message to Alice's Signal account
* Signal responds with UNREGISTERED_FAILURE, but the
number field in the response is null
The fix is to:
* Allow null in the "number" field as a valid value
* Ignore the value of the "number" field when reading Signal responses
In some rare cases the last ping can be None (i.e., there was no
last ping). In these cases we would need to omit the
"Last ping was <time interval> ago." part from the message.
To avoid creating a *third* WhatsApp content template, remove
the "Last ping was <time interval> ago." part from the message
altogether.
What are the cases when last ping could be None? Here's one:
* User creates a check
* User sends a "/start" signal
* The grace time passes, the check goes down. There's no
previous "success" or "fail" signal, so the check's
"last_ping" field will be None.
When preparing WhatsApp payload we call naturaltime() and
serialize its output as JSON. naturaltime can return a lazy object
which causes an exception during JSON serialization. The fix
is to wrap naturaltime in str() to force its output to be a string.
The purpose of @nolog was to disable logging in certain
test cases to avoid console spam during tests. But with the
current logging configuration console is clean even without it.
In prune(), we need to look up the earliest ping in the database
for a given check. The old version did:
ping = self.ping_set.earliest("id")
The new version does:
ping = self.ping_set.earliest("created")
Both yield the same result, but in the first case Postgres may
decide to use the index for the api_ping.id column and scan
almost the entire table.
In the second case it uses the index for the api_ping.owner_id column,
and scans just the rows associated with the check.