Skip to content

Commit 62a9e5e

Browse files
feat(uptime): Backfill uptime_status to uptime_subscription (#90025)
Co-authored-by: getsantry[bot] <66042841+getsantry[bot]@users.noreply.github.com>
1 parent 3be52a9 commit 62a9e5e

File tree

3 files changed

+99
-1
lines changed

3 files changed

+99
-1
lines changed

migrations_lockfile.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ social_auth: 0002_default_auto_field
2727

2828
tempest: 0002_make_message_type_nullable
2929

30-
uptime: 0033_uptime_backfill_to_detectors
30+
uptime: 0034_uptime_backfill_uptime_status
3131

3232
workflow_engine: 0046_drop_metric_alert_fire_detectors
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Generated by Django 5.1.7 on 2025-04-17 21:24
2+
3+
from django.db import migrations
4+
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
5+
from django.db.migrations.state import StateApps
6+
7+
from sentry.new_migrations.migrations import CheckedMigration
8+
from sentry.utils.query import RangeQuerySetWrapperWithProgressBar
9+
10+
11+
def backfill_uptime_status(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
12+
ProjectUptimeSubscription = apps.get_model("uptime", "ProjectUptimeSubscription")
13+
14+
monitors = ProjectUptimeSubscription.objects.filter().select_related("uptime_subscription")
15+
for monitor in RangeQuerySetWrapperWithProgressBar(monitors):
16+
sub = monitor.uptime_subscription
17+
sub.uptime_status = monitor.uptime_status
18+
sub.uptime_status_update_date = monitor.uptime_status_update_date
19+
sub.save()
20+
21+
22+
class Migration(CheckedMigration):
23+
# This flag is used to mark that a migration shouldn't be automatically run in production.
24+
# This should only be used for operations where it's safe to run the migration after your
25+
# code has deployed. So this should not be used for most operations that alter the schema
26+
# of a table.
27+
# Here are some things that make sense to mark as post deployment:
28+
# - Large data migrations. Typically we want these to be run manually so that they can be
29+
# monitored and not block the deploy for a long period of time while they run.
30+
# - Adding indexes to large tables. Since this can take a long time, we'd generally prefer to
31+
# run this outside deployments so that we don't block them. Note that while adding an index
32+
# is a schema change, it's completely safe to run the operation after the code has deployed.
33+
# Once deployed, run these manually via: https://develop.sentry.dev/database-migrations/#migration-deployment
34+
35+
is_post_deployment = True
36+
37+
dependencies = [
38+
("uptime", "0033_uptime_backfill_to_detectors"),
39+
]
40+
41+
operations = []
42+
operations = [
43+
migrations.RunPython(
44+
code=backfill_uptime_status,
45+
reverse_code=migrations.RunPython.noop,
46+
hints={
47+
"tables": [
48+
"uptime_projectuptimesubscription",
49+
"uptime_uptimesubscription",
50+
]
51+
},
52+
),
53+
]
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from datetime import timedelta
2+
3+
from django.utils import timezone
4+
5+
from sentry.testutils.cases import TestMigrations
6+
from sentry.uptime.models import ProjectUptimeSubscription, UptimeStatus, UptimeSubscription
7+
8+
DATA_SOURCE_UPTIME_SUBSCRIPTION = "uptime_subscription"
9+
10+
11+
class UptimeBackfillUptimeStatusTest(TestMigrations):
12+
app = "uptime"
13+
migrate_from = "0033_uptime_backfill_to_detectors"
14+
migrate_to = "0034_uptime_backfill_uptime_status"
15+
16+
def setup_before_migration(self, apps):
17+
self.failing_subscription = UptimeSubscription.objects.create(
18+
url="https://sentry.io",
19+
interval_seconds=60,
20+
timeout_ms=5000,
21+
)
22+
23+
self.failing_monitor = ProjectUptimeSubscription.objects.create(
24+
project=self.project,
25+
uptime_status=UptimeStatus.FAILED,
26+
uptime_status_update_date=timezone.now() - timedelta(minutes=5),
27+
uptime_subscription=self.failing_subscription,
28+
name="failed monitor",
29+
)
30+
31+
assert self.failing_subscription.uptime_status != self.failing_monitor.uptime_status
32+
assert (
33+
self.failing_subscription.uptime_status_update_date
34+
!= self.failing_monitor.uptime_status_update_date
35+
)
36+
37+
def test(self):
38+
self.failing_monitor.refresh_from_db()
39+
self.failing_subscription.refresh_from_db()
40+
41+
assert self.failing_subscription.uptime_status == self.failing_monitor.uptime_status
42+
assert (
43+
self.failing_subscription.uptime_status_update_date
44+
== self.failing_monitor.uptime_status_update_date
45+
)

0 commit comments

Comments
 (0)