Browse Source

Create Detector State Model (#78244)

# Description
Add the detector state model.

This model is used to track the state of the detector for [Alerts Create
Issues](https://www.notion.so/sentry/Alerts-Create-Issues-9114a498098143178839d584c293fe75#a688242905694b3ba68aa1e981c73c3c)
Josh Callender 5 months ago
parent
commit
6c6024b9d8

+ 18 - 0
fixtures/backup/model_dependencies/detailed.json

@@ -6404,6 +6404,24 @@
       ]
     ]
   },
+  "workflow_engine.detectorstate": {
+    "dangling": false,
+    "foreign_keys": {
+      "detector": {
+        "kind": "FlexibleForeignKey",
+        "model": "workflow_engine.detector",
+        "nullable": false
+      }
+    },
+    "model": "workflow_engine.detectorstate",
+    "relocation_dependencies": [],
+    "relocation_scope": "Organization",
+    "silos": [
+      "Region"
+    ],
+    "table_name": "workflow_engine_detectorstate",
+    "uniques": []
+  },
   "workflow_engine.detectorworkflow": {
     "dangling": false,
     "foreign_keys": {

+ 3 - 0
fixtures/backup/model_dependencies/flat.json

@@ -884,6 +884,9 @@
     "sentry.user",
     "workflow_engine.dataconditiongroup"
   ],
+  "workflow_engine.detectorstate": [
+    "workflow_engine.detector"
+  ],
   "workflow_engine.detectorworkflow": [
     "workflow_engine.detector",
     "workflow_engine.workflow"

+ 1 - 0
fixtures/backup/model_dependencies/sorted.json

@@ -53,6 +53,7 @@
   "workflow_engine.dataconditiongroupaction",
   "workflow_engine.datasource",
   "workflow_engine.detector",
+  "workflow_engine.detectorstate",
   "workflow_engine.workflow",
   "workflow_engine.workflowdataconditiongroup",
   "workflow_engine.detectorworkflow",

+ 1 - 0
fixtures/backup/model_dependencies/truncate.json

@@ -53,6 +53,7 @@
   "workflow_engine_dataconditiongroupaction",
   "workflow_engine_datasource",
   "workflow_engine_detector",
+  "workflow_engine_detectorstate",
   "workflow_engine_workflow",
   "workflow_engine_workflowdataconditiongroup",
   "workflow_engine_detectorworkflow",

+ 1 - 1
migrations_lockfile.txt

@@ -13,4 +13,4 @@ replays: 0004_index_together
 sentry: 0770_increase_project_slug_max_length
 social_auth: 0002_default_auto_field
 uptime: 0014_add_uptime_enviromnet
-workflow_engine: 0007_loosen_workflow_action_relationship
+workflow_engine: 0008_detector_state

+ 1 - 0
src/sentry/backup/comparators.py

@@ -878,6 +878,7 @@ def get_default_comparators() -> dict[str, list[JSONScrubbingComparator]]:
                 DateUpdatedComparator("date_updated", "date_added")
             ],
             "workflow_engine.detector": [DateUpdatedComparator("date_updated", "date_added")],
+            "workflow_engine.detectorstate": [DateUpdatedComparator("date_updated", "date_added")],
             "workflow_engine.detectorworkflow": [
                 DateUpdatedComparator("date_updated", "date_added")
             ],

+ 12 - 0
src/sentry/testutils/factories.py

@@ -178,6 +178,7 @@ from sentry.workflow_engine.models import (
     DataSource,
     DataSourceDetector,
     Detector,
+    DetectorState,
     DetectorWorkflow,
     Workflow,
     WorkflowDataConditionGroup,
@@ -2140,6 +2141,17 @@ class Factories:
             organization=organization, name=name, owner_user_id=owner_user_id, owner_team=owner_team
         )
 
+    @staticmethod
+    @assume_test_silo_mode(SiloMode.REGION)
+    def create_detector_state(
+        detector: Detector | None = None,
+        **kwargs,
+    ) -> DetectorState:
+        if detector is None:
+            detector = Factories.create_detector()
+
+        return DetectorState.objects.create(detector=detector, **kwargs)
+
     @staticmethod
     @assume_test_silo_mode(SiloMode.REGION)
     def create_data_source_detector(

+ 3 - 0
src/sentry/testutils/fixtures.py

@@ -650,6 +650,9 @@ class Fixtures:
     def create_detector(self, *args, **kwargs) -> Detector:
         return Factories.create_detector(*args, **kwargs)
 
+    def create_detector_state(self, *args, **kwargs) -> Detector:
+        return Factories.create_detector_state(*args, **kwargs)
+
     def create_data_source_detector(self, *args, **kwargs):
         return Factories.create_data_source_detector(*args, **kwargs)
 

+ 1 - 0
src/sentry/testutils/helpers/backups.py

@@ -613,6 +613,7 @@ class ExhaustiveFixtures(Fixtures):
         workflow = self.create_workflow(organization=org)
         detector = self.create_detector(organization=org)
         self.create_detector_workflow(detector=detector, workflow=workflow)
+        self.create_detector_state(detector=detector)
 
         notification_condition_group = self.create_data_condition_group(
             logic_type=DataConditionGroup.Type.ANY,

+ 63 - 0
src/sentry/workflow_engine/migrations/0008_detector_state.py

@@ -0,0 +1,63 @@
+# Generated by Django 5.1.1 on 2024-09-28 00:10
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+import sentry.db.models.fields.bounded
+import sentry.db.models.fields.foreignkey
+import sentry.workflow_engine.models.detector_state
+from sentry.new_migrations.migrations import CheckedMigration
+
+
+class Migration(CheckedMigration):
+    # This flag is used to mark that a migration shouldn't be automatically run in production.
+    # This should only be used for operations where it's safe to run the migration after your
+    # code has deployed. So this should not be used for most operations that alter the schema
+    # of a table.
+    # Here are some things that make sense to mark as post deployment:
+    # - Large data migrations. Typically we want these to be run manually so that they can be
+    #   monitored and not block the deploy for a long period of time while they run.
+    # - Adding indexes to large tables. Since this can take a long time, we'd generally prefer to
+    #   run this outside deployments so that we don't block them. Note that while adding an index
+    #   is a schema change, it's completely safe to run the operation after the code has deployed.
+    # Once deployed, run these manually via: https://develop.sentry.dev/database-migrations/#migration-deployment
+
+    is_post_deployment = False
+
+    dependencies = [
+        ("workflow_engine", "0007_loosen_workflow_action_relationship"),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name="DetectorState",
+            fields=[
+                (
+                    "id",
+                    sentry.db.models.fields.bounded.BoundedBigAutoField(
+                        primary_key=True, serialize=False
+                    ),
+                ),
+                ("date_updated", models.DateTimeField(auto_now=True)),
+                ("date_added", models.DateTimeField(auto_now_add=True)),
+                ("detector_group_key", models.CharField(blank=True, max_length=200, null=True)),
+                ("active", models.BooleanField(default=False)),
+                (
+                    "state",
+                    models.CharField(
+                        default=sentry.workflow_engine.models.detector_state.DetectorStatus["OK"],
+                        max_length=200,
+                    ),
+                ),
+                (
+                    "detector",
+                    sentry.db.models.fields.foreignkey.FlexibleForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE, to="workflow_engine.detector"
+                    ),
+                ),
+            ],
+            options={
+                "abstract": False,
+            },
+        ),
+    ]

Some files were not shown because too many files changed in this diff