-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
feat(ACI): Use status column on Detector and Workflow #91994
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
Conversation
|
Tests completed | Failed | Passed | Skipped |
---|---|---|---|
25952 | 8 | 25944 | 206 |
View the top 3 failed test(s) by shortest run time
tests.sentry.workflow_engine.endpoints.test_organization_workflow_details.OrganizationDeleteWorkflowTest::test_delete_configured_workflow__action
Stack Traces | 2.28s run time
#x1B[1m#x1B[.../workflow_engine/endpoints/test_organization_workflow_details.py#x1B[0m:136: in test_delete_configured_workflow__action assert not Action.objects.filter(id=action.id).exists() #x1B[1m#x1B[31mE AssertionError: assert not True#x1B[0m #x1B[1m#x1B[31mE + where True = <bound method QuerySet.exists of <BaseQuerySet [<Action at 0x7f4600833770: id=16, type='slack'>]>>()#x1B[0m #x1B[1m#x1B[31mE + where <bound method QuerySet.exists of <BaseQuerySet [<Action at 0x7f4600833770: id=16, type='slack'>]>> = <BaseQuerySet [<Action at 0x7f4600833770: id=16, type='slack'>]>.exists#x1B[0m #x1B[1m#x1B[31mE + where <BaseQuerySet [<Action at 0x7f4600833770: id=16, type='slack'>]> = <bound method QuerySet.filter of <sentry.db.models.manager.base.BaseManager object at 0x7f4675332900>>(id=16)#x1B[0m #x1B[1m#x1B[31mE + where <bound method QuerySet.filter of <sentry.db.models.manager.base.BaseManager object at 0x7f4675332900>> = <sentry.db.models.manager.base.BaseManager object at 0x7f4675332900>.filter#x1B[0m #x1B[1m#x1B[31mE + where <sentry.db.models.manager.base.BaseManager object at 0x7f4675332900> = Action.objects#x1B[0m #x1B[1m#x1B[31mE + and 16 = <Action at 0x7f46008331d0: id=16, type=<Type.SLACK: 'slack'>>.id#x1B[0m
tests.sentry.workflow_engine.endpoints.test_organization_workflow_details.OrganizationDeleteWorkflowTest::test_delete_configured_workflow__action_condition
Stack Traces | 2.48s run time
#x1B[1m#x1B[.../workflow_engine/endpoints/test_organization_workflow_details.py#x1B[0m:154: in test_delete_configured_workflow__action_condition assert not DataConditionGroup.objects.filter(id=action_condition_group.id).exists() #x1B[1m#x1B[31mE AssertionError: assert not True#x1B[0m #x1B[1m#x1B[31mE + where True = <bound method QuerySet.exists of <BaseQuerySet [<DataConditionGroup at 0x7f4246ab50d0: id=20, logic_type='any-short'>]>>()#x1B[0m #x1B[1m#x1B[31mE + where <bound method QuerySet.exists of <BaseQuerySet [<DataConditionGroup at 0x7f4246ab50d0: id=20, logic_type='any-short'>]>> = <BaseQuerySet [<DataConditionGroup at 0x7f42446105d0: id=20, logic_type='any-short'>]>.exists#x1B[0m #x1B[1m#x1B[31mE + where <BaseQuerySet [<DataConditionGroup at 0x7f42446105d0: id=20, logic_type='any-short'>]> = <bound method QuerySet.filter of <sentry.db.models.manager.base.BaseManager object at 0x7f428ee97620>>(id=20)#x1B[0m #x1B[1m#x1B[31mE + where <bound method QuerySet.filter of <sentry.db.models.manager.base.BaseManager object at 0x7f428ee97620>> = <sentry.db.models.manager.base.BaseManager object at 0x7f428ee97620>.filter#x1B[0m #x1B[1m#x1B[31mE + where <sentry.db.models.manager.base.BaseManager object at 0x7f428ee97620> = DataConditionGroup.objects#x1B[0m #x1B[1m#x1B[31mE + and 20 = <DataConditionGroup at 0x7f4244829950: id=20, logic_type='any-short'>.id#x1B[0m
tests.sentry.workflow_engine.endpoints.test_organization_detector_details.OrganizationDetectorDetailsGetTest::test_pending_deletion
Stack Traces | 2.78s run time
#x1B[1m#x1B[.../workflow_engine/endpoints/test_organization_detector_details.py#x1B[0m:98: in test_pending_deletion self.get_error_response(self.organization.slug, self.detector.id, status_code=404) #x1B[1m#x1B[.../sentry/testutils/cases.py#x1B[0m:648: in get_error_response assert_status_code(response, status_code) #x1B[1m#x1B[.../sentry/testutils/asserts.py#x1B[0m:45: in assert_status_code assert minimum <= response.status_code < maximum, ( #x1B[1m#x1B[31mE AssertionError: (200, b'{"id":"21","projectId":"4556112054976514","name":"Test Detector","type":"metric_issue","workflowIds":[],"dateC...:"lt","comparison":50,"conditionResult":25}],"actions":[]},"config":{"detection_type":"static","threshold_period":1}}')#x1B[0m #x1B[1m#x1B[31mE assert 404 <= 200#x1B[0m #x1B[1m#x1B[31mE + where 200 = <Response status_code=200, "application/json">.status_code#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.
@@ -107,6 +108,7 @@ def delete(self, request: Request, organization: Organization, workflow: Workflo | |||
Delete a workflow | |||
""" | |||
RegionScheduledDeletion.schedule(workflow, days=0, actor=request.user) | |||
workflow.update(status=ObjectStatus.PENDING_DELETION) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting it to pending deletion in the delete endpoint after it's been scheduled for deletion
@@ -169,6 +172,7 @@ def delete(self, request: Request, organization: Organization, detector: Detecto | |||
return Response(status=403) | |||
|
|||
RegionScheduledDeletion.schedule(detector, days=0, actor=request.user) | |||
detector.update(status=ObjectStatus.PENDING_DELETION) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting it to pending deletion in the delete endpoint after it's been scheduled for deletion
for instance in instance_list: | ||
status = getattr(instance, "status", None) | ||
if status not in (ObjectStatus.DELETION_IN_PROGRESS, None): | ||
instance.update(status=ObjectStatus.DELETION_IN_PROGRESS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting it to deletion in progress
for instance in instance_list: | ||
status = getattr(instance, "status", None) | ||
if status not in (ObjectStatus.DELETION_IN_PROGRESS, None): | ||
instance.update(status=ObjectStatus.DELETION_IN_PROGRESS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting it to deletion in progress
I know it's a lot of files touched but it's the same change across most except those that I called out in the comments. |
@@ -87,7 +89,9 @@ def serialize( | |||
**kwargs: Any, | |||
) -> dict[str, Any]: | |||
# XXX: we are assuming that the obj/DataCondition is a detector trigger | |||
detector = Detector.objects.get(workflow_condition_group=obj.condition_group) | |||
detector = Detector.objects.get( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a way we can set status=ObjectStatus.ACTIVE
as a default value when fetching then have the ability to override it? that way we can ensure it only selects active detectors unless we otherwise query.
maybe something like:
class DetectorManager(models.Manager):
def filter(self, *args, **kwargs):
# Only add the default status if no status is explicitly provided
if 'status' not in kwargs:
kwargs['status'] = ObjectStatus.ACTIVE
return super().filter(*args, **kwargs)
def get(self, *args, **kwargs):
# Only add the default status if no status is explicitly provided
if 'status' not in kwargs:
kwargs['status'] = ObjectStatus.ACTIVE
return super().get(*args, **kwargs)
class Detector(models.Model):
# Your fields here
status = models.IntegerField(choices=ObjectStatus.choices, default=ObjectStatus.ACTIVE)
objects = DetectorManager()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nvm blonde moment
@@ -50,7 +50,8 @@ def create(self, validated_data): | |||
if not can_edit_detector(detector, self.context["request"]): | |||
raise PermissionDenied | |||
workflow = Workflow.objects.get( | |||
organization=self.context["organization"], id=validated_data["workflow_id"] | |||
organization=self.context["organization"], | |||
id=validated_data["workflow_id"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't put this back so just ignore 😢
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉 thanks for doing that refactor - if you don't mind adding tests for the managers as well that'd be awesome, otherwise lgtm!
from sentry.models.owner_base import OwnerModel | ||
from sentry.workflow_engine.models.data_condition import DataCondition, is_slow_condition | ||
from sentry.workflow_engine.types import WorkflowEventData | ||
|
||
from .json_config import JSONConfigBase | ||
|
||
|
||
class WorkflowManager(BaseManager["Workflow"]): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might be nice to have some individual tests for the managers to ensure it's working as expected.
9a4474d
to
a8a30ea
Compare
uh ... oops |
Now that the
Detector
andWorkflow
models have astatus
column we can make use of it. This PR sets the status toPENDING_DELETION
in the deletion endpoints, sets the status toDELETION_IN_PROGRESS
in the deletion tasks, and updates all gets and filters to filter toACTIVE
statuses.