| Index: dashboard/dashboard/models/alert.py
|
| diff --git a/dashboard/dashboard/models/alert.py b/dashboard/dashboard/models/alert.py
|
| index 91c11f282b4d283bd3e38dfe93164813361a2dc0..8e73f782fe035ebcbe15fa2b845a705fbe3fb9fb 100644
|
| --- a/dashboard/dashboard/models/alert.py
|
| +++ b/dashboard/dashboard/models/alert.py
|
| @@ -41,6 +41,88 @@
|
| # kind=alert_group.AlertGroup can be added.
|
| group = ndb.KeyProperty(indexed=True)
|
|
|
| + def _pre_put_hook(self):
|
| + """Updates the alert's group."""
|
| + # TODO(qyearsley): Extract sub-methods from this method in order
|
| + # to make it shorter.
|
| +
|
| + # The group should not be updated if this is the first time that the
|
| + # the Alert is being put. (If the key is auto-assigned, then key.id()
|
| + # will be None the first time.)
|
| + if not self.key.id():
|
| + return
|
| +
|
| + # The previous state of this alert. (If this is the first time the
|
| + # alert is being put, then this will be None.
|
| + original_alert = self.key.get(use_cache=False)
|
| + if original_alert is None:
|
| + return
|
| +
|
| + # If the alert does not have a group, don't do anything.
|
| + if not self.group:
|
| + return
|
| + # If the group key is "AnomalyGroup" (the previous incarnation of
|
| + # AlertGroup), we can just leave it as is. This will only apply to
|
| + # already-existing Anomaly entities, not new Anomaly entities.
|
| + if self.group.kind() != 'AlertGroup':
|
| + self.group = None
|
| + return
|
| + group = self.group.get()
|
| + if not group:
|
| + return
|
| +
|
| + # Each AlertGroup should only be associated with entities of one class;
|
| + # i.e. an Anomaly entity shouldn't be grouped with a StoppageAlert entity.
|
| + alert_class = self.__class__
|
| +
|
| + # When the bug ID changes, this alert may be updated to belong
|
| + # to the new group.
|
| + if self.bug_id != original_alert.bug_id:
|
| + grouped_alerts = alert_class.query(
|
| + alert_class.group == group.key).fetch()
|
| + grouped_alerts.append(self)
|
| +
|
| + # The alert has been assigned a real bug ID.
|
| + # Update the group bug ID if necessary.
|
| + if self.bug_id > 0 and group.bug_id != self.bug_id:
|
| + group.bug_id = self.bug_id
|
| + group.put()
|
| +
|
| + # The bug has been marked invalid/ignored. Kick it out of the group.
|
| + elif self.bug_id < 0 and self.bug_id is not None:
|
| + self._RemoveFromGroup(grouped_alerts)
|
| + grouped_alerts.remove(self)
|
| +
|
| + # The bug has been un-triaged. Update the group's bug ID if this is
|
| + # the only alert in the group.
|
| + elif self.bug_id is None and len(grouped_alerts) == 1:
|
| + group.bug_id = None
|
| + group.put()
|
| +
|
| + # Check and update the group's revision range if necessary.
|
| + group.UpdateRevisionRange(grouped_alerts)
|
| +
|
| + elif (self.end_revision != original_alert.end_revision or
|
| + self.start_revision != original_alert.start_revision):
|
| + grouped_alerts = alert_class.query(alert_class.group == group.key).fetch()
|
| + grouped_alerts.append(self)
|
| + group.UpdateRevisionRange(grouped_alerts)
|
| +
|
| + def _RemoveFromGroup(self, grouped_alerts):
|
| + """Removes an alert from its group and updates the group's properties.
|
| +
|
| + Args:
|
| + grouped_alerts: The list of alerts in |group| used to calculate
|
| + new revision range; none are modified.
|
| + """
|
| + group = self.group.get()
|
| + self.group = None
|
| + grouped_alerts.remove(self)
|
| + if not grouped_alerts:
|
| + group.key.delete()
|
| + return
|
| + # Update minimum revision range for group.
|
| + group.UpdateRevisionRange(grouped_alerts)
|
|
|
| def GetTestMetadataKey(self):
|
| """Get the key for the TestMetadata entity of this alert.
|
|
|