Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ACI): Delete endpoint for a detector #84279

Open
wants to merge 25 commits into
base: master
Choose a base branch
from

Conversation

ceorourke
Copy link
Member

@ceorourke ceorourke commented Jan 29, 2025

Create a DELETE endpoint for a given detector. This deletes the related DataSource, QuerySubscription, and SnubaQuery.

It assumes that a data source is only connected to a single detector. The db model supports multiple detectors but the UI does not.

@ceorourke ceorourke requested a review from a team as a code owner January 29, 2025 23:38
@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Jan 29, 2025
@ceorourke ceorourke force-pushed the ceorourke/delete-detector-endpoint branch from 8920d82 to 57af780 Compare January 30, 2025 00:06
Copy link

codecov bot commented Jan 30, 2025

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
23513 1 23512 289
View the top 1 failed test(s) by shortest run time
tests.sentry.sentry_metrics.test_snuba.SnubaMetricsInterfaceTest::test_count_query
Stack Traces | 3.44s run time
#x1B[1m#x1B[.../sentry/sentry_metrics/test_snuba.py#x1B[0m:53: in test_count_query
    data = get_series(
#x1B[1m#x1B[.../snuba/metrics/datasource.py#x1B[0m:847: in get_series
    ).get_snuba_queries()
#x1B[1m#x1B[.../snuba/metrics/query_builder.py#x1B[0m:1153: in get_snuba_queries
    component_entities = metric_field_obj.get_entity(
#x1B[1m#x1B[.../metrics/fields/base.py#x1B[0m:783: in get_entity
    return _get_entity_of_metric_mri(projects, self.metric_object.metric_mri, use_case_id)
#x1B[1m#x1B[.../metrics/fields/base.py#x1B[0m:283: in _get_entity_of_metric_mri
    raise InvalidParams(f"Raw metric {get_public_name_from_mri(metric_mri)} does not exist")
#x1B[1m#x1B[31mE   sentry.exceptions.InvalidParams: Raw metric measurements.speed does not exist#x1B[0m

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@@ -69,3 +77,51 @@ def get(self, request: Request, project, detector):
DetectorSerializer(),
)
return Response(serialized_detector)

@extend_schema(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥔 for adding documentation to the endpoint from the beginning. People make experimental endpoints left and right and the endpoint sits there for long before publishing so everyone forgets the context 😅



class DetectorDeletionTask(ModelDeletionTask[Detector]):
def get_child_relations(self, instance: Detector) -> list[BaseRelation]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just note that with cascade delete if there are a large number of related rows the delete can fail. That's probably unlikely here, but jfyi

src/sentry/deletions/defaults/detector.py Outdated Show resolved Hide resolved
def setUp(self):
self.data_condition_group = self.create_data_condition_group()
self.data_condition = self.create_data_condition(condition_group=self.data_condition_group)
self.snuba_query = self.create_snuba_query()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we could do that. In the past we didn't because potentially one snuba query could be shared, but in practice we haven't really used that.

Could make sense to just check that there aren't other links to the snuba query and then delete it if orphaned.

Comment on lines 9 to 11
model_relations: list[BaseRelation] = [
ModelRelation(QuerySubscription, {"id": instance.query_id})
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to check the type here? query_id will point to different datasources in the future.

Looks like you can do instance.type_handler.bulk_get_query_object([instance]) to get all related objects.

I think that probably, you should build the SnubaQuery deletion stuff into a delete module for subscriptions rather than here. That way, you can just add the QuerySubscription as the model relation, and then it will automatically clean itself up.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Today we only appear to have a single type for a QuerySubscription (incident). Since I moved deleting the snuba query to the query subscription deletion task do I still need to filter?

I moved deleting it into querysubscription.py but ended up having to check for an AlertRule first - after everything is migrated that won't be a problem and I'm not sure if in practice it'll ever happen that we're deleting a QuerySubscription that still has an active AlertRule.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you still need to use bulk_get_query_object here or the QuerySubscription rows won't be deleted when the DataSource is deleted. Probably you'd need to schedule deletions for them, since we don't have an explicit relationship that we can follow here...

Comment on lines 17 to 18
if not AlertRule.objects.filter(snuba_query_id=instance.snuba_query_id).exists():
return [ModelRelation(SnubaQuery, {"id": instance.snuba_query_id})]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also check that the SnubaQuery only has this one subscription?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Scope: Backend Automatically applied to PRs that change backend components
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants