Skip to content

Commit 328b74c

Browse files
kconsgeorge-sentry
authored andcommitted
feat(alerts): Set up prune_old_open_period_activity (#112243)
Our backlog is only 17m or so rows, but by reusing a task pattern we've already used before we should be able to safely get that quickly cleaned up in all regions. A job or post-deploy migration would also be an option, but this is no harder and more or less guarantees that next time we look it'll be dealt with.
1 parent bf1cac0 commit 328b74c

4 files changed

Lines changed: 56 additions & 50 deletions

File tree

src/sentry/options/defaults.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3575,18 +3575,18 @@
35753575
default=10000,
35763576
flags=FLAG_AUTOMATOR_MODIFIABLE,
35773577
)
3578-
# Tuning knobs for the periodic fire-history cleanup task.
3578+
# Tuning knobs for the periodic open-period-activity cleanup task.
35793579
# time_limit is a wall-clock budget checked *between* batches, so a single
35803580
# batch that exceeds it will still run to completion. Setting it to 0
35813581
# prevents any batches from running.
35823582
register(
3583-
"workflow_engine.fire_history_cleanup.time_limit_seconds",
3583+
"workflow_engine.open_period_activity_cleanup.time_limit_seconds",
35843584
type=Float,
35853585
default=5.0,
35863586
flags=FLAG_AUTOMATOR_MODIFIABLE,
35873587
)
35883588
register(
3589-
"workflow_engine.fire_history_cleanup.batch_size",
3589+
"workflow_engine.open_period_activity_cleanup.batch_size",
35903590
type=Int,
35913591
default=10000,
35923592
flags=FLAG_AUTOMATOR_MODIFIABLE,

src/sentry/workflow_engine/tasks/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
"process_delayed_workflows",
33
"process_workflow_activity",
44
"process_workflows_event",
5-
"prune_old_fire_history",
5+
"prune_old_open_period_activity",
66
]
77

8-
from .cleanup import prune_old_fire_history
8+
from .cleanup import prune_old_open_period_activity
99
from .delayed_workflows import process_delayed_workflows
1010
from .workflows import process_workflow_activity, process_workflows_event

src/sentry/workflow_engine/tasks/cleanup.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,30 @@
1515

1616
logger = logging.getLogger(__name__)
1717

18-
FIRE_HISTORY_RETENTION_DAYS = 90
18+
OPEN_PERIOD_ACTIVITY_RETENTION_DAYS = 90
1919

2020

2121
@instrumented_task(
22-
name="sentry.workflow_engine.tasks.cleanup.prune_old_fire_history",
22+
name="sentry.workflow_engine.tasks.cleanup.prune_old_open_period_activity",
2323
namespace=workflow_engine_tasks,
2424
processing_deadline_duration=15,
2525
silo_mode=SiloMode.CELL,
2626
)
27-
def prune_old_fire_history() -> None:
28-
from sentry.workflow_engine.models import WorkflowFireHistory
27+
def prune_old_open_period_activity() -> None:
28+
from sentry.models.groupopenperiodactivity import GroupOpenPeriodActivity
2929

30-
time_limit: float = options.get("workflow_engine.fire_history_cleanup.time_limit_seconds")
31-
batch_size: int = options.get("workflow_engine.fire_history_cleanup.batch_size")
30+
time_limit: float = options.get(
31+
"workflow_engine.open_period_activity_cleanup.time_limit_seconds"
32+
)
33+
batch_size: int = options.get("workflow_engine.open_period_activity_cleanup.batch_size")
3234

33-
cutoff = timezone.now() - timedelta(days=FIRE_HISTORY_RETENTION_DAYS)
35+
cutoff = timezone.now() - timedelta(days=OPEN_PERIOD_ACTIVITY_RETENTION_DAYS)
3436
start = time.time()
3537
batches_deleted = 0
3638

3739
while (time.time() - start) < time_limit:
3840
has_more = bulk_delete_objects(
39-
WorkflowFireHistory,
41+
GroupOpenPeriodActivity,
4042
limit=batch_size,
4143
logger=logger,
4244
date_added__lte=cutoff,
@@ -46,7 +48,7 @@ def prune_old_fire_history() -> None:
4648
batches_deleted += 1
4749

4850
metrics.incr(
49-
"workflow_engine.tasks.prune_old_fire_history.batches_deleted",
51+
"workflow_engine.tasks.prune_old_open_period_activity.batches_deleted",
5052
amount=batches_deleted,
5153
sample_rate=1.0,
5254
)

tests/sentry/workflow_engine/tasks/test_cleanup.py

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,76 +3,80 @@
33

44
from django.utils import timezone
55

6+
from sentry.models.groupopenperiod import GroupOpenPeriod
7+
from sentry.models.groupopenperiodactivity import GroupOpenPeriodActivity, OpenPeriodActivityType
68
from sentry.testutils.cases import TestCase
79
from sentry.testutils.helpers.options import override_options
810
from sentry.utils.query import bulk_delete_objects
9-
from sentry.workflow_engine.models import WorkflowFireHistory
1011
from sentry.workflow_engine.tasks.cleanup import (
11-
FIRE_HISTORY_RETENTION_DAYS,
12-
prune_old_fire_history,
12+
OPEN_PERIOD_ACTIVITY_RETENTION_DAYS,
13+
prune_old_open_period_activity,
1314
)
1415

1516

16-
class TestPruneOldFireHistory(TestCase):
17-
def _create_fire_history(self, days_ago: int) -> WorkflowFireHistory:
18-
workflow = self.create_workflow(organization=self.organization)
17+
class TestPruneOldOpenPeriodActivity(TestCase):
18+
def _create_activity(self, days_ago: int) -> GroupOpenPeriodActivity:
1919
group = self.create_group(project=self.project)
20-
obj = WorkflowFireHistory.objects.create(workflow=workflow, group=group, event_id="abc123")
20+
open_period = GroupOpenPeriod.objects.get(group=group)
21+
obj = GroupOpenPeriodActivity.objects.create(
22+
group_open_period=open_period,
23+
type=OpenPeriodActivityType.OPENED,
24+
)
2125
if days_ago > 0:
2226
backdated = timezone.now() - timedelta(days=days_ago)
23-
WorkflowFireHistory.objects.filter(id=obj.id).update(date_added=backdated)
27+
GroupOpenPeriodActivity.objects.filter(id=obj.id).update(date_added=backdated)
2428
obj.refresh_from_db()
2529
return obj
2630

2731
def test_noop_when_nothing_to_delete(self) -> None:
2832
with patch("sentry.workflow_engine.tasks.cleanup.metrics") as mock_metrics:
29-
prune_old_fire_history()
33+
prune_old_open_period_activity()
3034

3135
mock_metrics.incr.assert_called_once_with(
32-
"workflow_engine.tasks.prune_old_fire_history.batches_deleted",
36+
"workflow_engine.tasks.prune_old_open_period_activity.batches_deleted",
3337
amount=0,
3438
sample_rate=1.0,
3539
)
3640

3741
def test_deletes_rows_older_than_retention(self) -> None:
38-
old = self._create_fire_history(days_ago=FIRE_HISTORY_RETENTION_DAYS + 1)
39-
recent = self._create_fire_history(days_ago=FIRE_HISTORY_RETENTION_DAYS - 1)
42+
old = self._create_activity(days_ago=OPEN_PERIOD_ACTIVITY_RETENTION_DAYS + 1)
43+
recent = self._create_activity(days_ago=OPEN_PERIOD_ACTIVITY_RETENTION_DAYS - 1)
4044

41-
prune_old_fire_history()
45+
prune_old_open_period_activity()
4246

43-
assert not WorkflowFireHistory.objects.filter(id=old.id).exists()
44-
assert WorkflowFireHistory.objects.filter(id=recent.id).exists()
47+
assert not GroupOpenPeriodActivity.objects.filter(id=old.id).exists()
48+
assert GroupOpenPeriodActivity.objects.filter(id=recent.id).exists()
4549

4650
def test_preserves_recent_rows(self) -> None:
4751
rows = [
48-
self._create_fire_history(days_ago=1),
49-
self._create_fire_history(days_ago=30),
50-
self._create_fire_history(days_ago=FIRE_HISTORY_RETENTION_DAYS - 1),
52+
self._create_activity(days_ago=1),
53+
self._create_activity(days_ago=30),
54+
self._create_activity(days_ago=OPEN_PERIOD_ACTIVITY_RETENTION_DAYS - 1),
5155
]
5256

53-
prune_old_fire_history()
57+
prune_old_open_period_activity()
5458

5559
for row in rows:
56-
assert WorkflowFireHistory.objects.filter(id=row.id).exists()
60+
assert GroupOpenPeriodActivity.objects.filter(id=row.id).exists()
5761

58-
@override_options({"workflow_engine.fire_history_cleanup.batch_size": 10})
62+
@override_options({"workflow_engine.open_period_activity_cleanup.batch_size": 10})
5963
def test_multiple_batches(self) -> None:
6064
old_ids = []
6165
for _ in range(25):
62-
obj = self._create_fire_history(days_ago=FIRE_HISTORY_RETENTION_DAYS + 1)
66+
obj = self._create_activity(days_ago=OPEN_PERIOD_ACTIVITY_RETENTION_DAYS + 1)
6367
old_ids.append(obj.id)
6468

6569
with patch("sentry.workflow_engine.tasks.cleanup.metrics") as mock_metrics:
66-
prune_old_fire_history()
70+
prune_old_open_period_activity()
6771

68-
assert WorkflowFireHistory.objects.filter(id__in=old_ids).count() == 0
72+
assert GroupOpenPeriodActivity.objects.filter(id__in=old_ids).count() == 0
6973
mock_metrics.incr.assert_called_once()
7074
assert mock_metrics.incr.call_args.kwargs["amount"] >= 2
7175

7276
@override_options(
7377
{
74-
"workflow_engine.fire_history_cleanup.batch_size": 10,
75-
"workflow_engine.fire_history_cleanup.time_limit_seconds": 5.0,
78+
"workflow_engine.open_period_activity_cleanup.batch_size": 10,
79+
"workflow_engine.open_period_activity_cleanup.time_limit_seconds": 5.0,
7680
}
7781
)
7882
@patch("sentry.workflow_engine.tasks.cleanup.time")
@@ -82,41 +86,41 @@ def test_time_bounded_leaves_remaining_rows(self, mock_time: MagicMock) -> None:
8286

8387
old_ids = []
8488
for _ in range(25):
85-
obj = self._create_fire_history(days_ago=FIRE_HISTORY_RETENTION_DAYS + 1)
89+
obj = self._create_activity(days_ago=OPEN_PERIOD_ACTIVITY_RETENTION_DAYS + 1)
8690
old_ids.append(obj.id)
8791

8892
with patch("sentry.workflow_engine.tasks.cleanup.metrics"):
89-
prune_old_fire_history()
93+
prune_old_open_period_activity()
9094

91-
remaining = WorkflowFireHistory.objects.filter(id__in=old_ids).count()
95+
remaining = GroupOpenPeriodActivity.objects.filter(id__in=old_ids).count()
9296
assert remaining == 15 # only one batch of 10 was deleted
9397

94-
@override_options({"workflow_engine.fire_history_cleanup.batch_size": 5})
98+
@override_options({"workflow_engine.open_period_activity_cleanup.batch_size": 5})
9599
def test_options_honored(self) -> None:
96100
old_ids = []
97101
for _ in range(12):
98-
obj = self._create_fire_history(days_ago=FIRE_HISTORY_RETENTION_DAYS + 1)
102+
obj = self._create_activity(days_ago=OPEN_PERIOD_ACTIVITY_RETENTION_DAYS + 1)
99103
old_ids.append(obj.id)
100104

101105
with patch(
102106
"sentry.workflow_engine.tasks.cleanup.bulk_delete_objects",
103107
wraps=bulk_delete_objects,
104108
) as spy:
105-
prune_old_fire_history()
109+
prune_old_open_period_activity()
106110

107111
for call in spy.call_args_list:
108112
assert call.kwargs["limit"] == 5
109113

110-
assert WorkflowFireHistory.objects.filter(id__in=old_ids).count() == 0
114+
assert GroupOpenPeriodActivity.objects.filter(id__in=old_ids).count() == 0
111115

112116
def test_metrics_emitted(self) -> None:
113-
self._create_fire_history(days_ago=FIRE_HISTORY_RETENTION_DAYS + 1)
117+
self._create_activity(days_ago=OPEN_PERIOD_ACTIVITY_RETENTION_DAYS + 1)
114118

115119
with patch("sentry.workflow_engine.tasks.cleanup.metrics") as mock_metrics:
116-
prune_old_fire_history()
120+
prune_old_open_period_activity()
117121

118122
mock_metrics.incr.assert_called_once_with(
119-
"workflow_engine.tasks.prune_old_fire_history.batches_deleted",
123+
"workflow_engine.tasks.prune_old_open_period_activity.batches_deleted",
120124
amount=1, # 1 row fits in a single batch
121125
sample_rate=1.0,
122126
)

0 commit comments

Comments
 (0)