def tombstone_events(project_id, group_id, event_ids): """ Delete associated per-event data: nodestore, event attachments, user reports. Mark the event as "tombstoned" in Snuba. This is not full event deletion. Snuba can still only delete entire groups, however we must only run this task for event IDs that we don't intend to reuse for reprocessed events. An event ID that is once tombstoned cannot be inserted over in eventstream. See doccomment in sentry.reprocessing2. """ from sentry.reprocessing2 import delete_unprocessed_events models.EventAttachment.objects.filter(project_id=project_id, event_id__in=event_ids).delete() models.UserReport.objects.filter(project_id=project_id, event_id__in=event_ids).delete() # Remove from nodestore node_ids = [ Event.generate_node_id(project_id, event_id) for event_id in event_ids ] nodestore.delete_multi(node_ids) delete_unprocessed_events(project_id, event_ids) # Tell Snuba to delete the event data. eventstream.tombstone_events(project_id, event_ids)
def chunk(self): conditions = [] if self.last_event is not None: conditions.extend( [ ["timestamp", "<=", self.last_event.timestamp], [ ["timestamp", "<", self.last_event.timestamp], ["event_id", "<", self.last_event.event_id], ], ] ) events = eventstore.get_unfetched_events( filter=eventstore.Filter( conditions=conditions, project_ids=[self.project_id], group_ids=[self.group_id] ), limit=self.DEFAULT_CHUNK_SIZE, referrer="deletions.group", orderby=["-timestamp", "-event_id"], ) if not events: return False self.last_event = events[-1] # Remove from nodestore node_ids = [Event.generate_node_id(self.project_id, event.event_id) for event in events] nodestore.delete_multi(node_ids) from sentry.reprocessing2 import delete_unprocessed_events delete_unprocessed_events(events) # Remove EventAttachment and UserReport *again* as those may not have a # group ID, therefore there may be dangling ones after "regular" model # deletion. event_ids = [event.event_id for event in events] models.EventAttachment.objects.filter( event_id__in=event_ids, project_id=self.project_id ).delete() models.UserReport.objects.filter( event_id__in=event_ids, project_id=self.project_id ).delete() return True
def handle_remaining_events(project_id, new_group_id, event_ids, remaining_events): """ Delete or merge/move associated per-event data: nodestore, event attachments, user reports. Mark the event as "tombstoned" in Snuba. This is not full event deletion. Snuba can still only delete entire groups, however we must only run this task for event IDs that we don't intend to reuse for reprocessed events. An event ID that is once tombstoned cannot be inserted over in eventstream. See doccomment in sentry.reprocessing2. """ from sentry.reprocessing2 import delete_unprocessed_events assert remaining_events in ("delete", "keep") if remaining_events == "delete": models.EventAttachment.objects.filter(project_id=project_id, event_id__in=event_ids).delete() models.UserReport.objects.filter(project_id=project_id, event_id__in=event_ids).delete() # Remove from nodestore node_ids = [ Event.generate_node_id(project_id, event_id) for event_id in event_ids ] nodestore.delete_multi(node_ids) delete_unprocessed_events(project_id, event_ids) # Tell Snuba to delete the event data. eventstream.tombstone_events_unsafe(project_id, event_ids) elif remaining_events == "keep": eventstream.replace_group_unsafe(project_id, event_ids, new_group_id=new_group_id) else: raise ValueError( "Invalid value for remaining_events: {}".format(remaining_events))
def chunk(self): conditions = [] if self.last_event is not None: conditions.extend([ ["timestamp", "<=", self.last_event.timestamp], [ ["timestamp", "<", self.last_event.timestamp], ["event_id", "<", self.last_event.event_id], ], ]) events = eventstore.get_unfetched_events( filter=eventstore.Filter(conditions=conditions, project_ids=[self.project_id], group_ids=[self.group_id]), limit=self.DEFAULT_CHUNK_SIZE, referrer="deletions.group", orderby=["-timestamp", "-event_id"], ) if not events: return False self.last_event = events[-1] # Remove from nodestore node_ids = [ Event.generate_node_id(self.project_id, event.event_id) for event in events ] nodestore.delete_multi(node_ids) delete_unprocessed_events(events) # Remove EventAttachment and UserReport event_ids = [event.event_id for event in events] EventAttachment.objects.filter(event_id__in=event_ids, project_id=self.project_id).delete() UserReport.objects.filter(event_id__in=event_ids, project_id=self.project_id).delete() return True