Skip to content

Commit be2fa50

Browse files
authored
feat(cells) Add silo annotations to email, debug, and plugin views (#104034)
Add silo annotations to the debug views, and plugin views. While debug email views are never run in production, having silo annotations on these will allow silo completeness tests to have fewer exceptions. Refs INFRENG-201
1 parent c871df2 commit be2fa50

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+182
-10
lines changed

src/sentry/charts/endpoints.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
from django.views import static
66

77
import sentry
8+
from sentry.web.frontend.base import all_silo_view
89

910
CONFIG_DIR = os.path.abspath(
1011
os.path.join(os.path.dirname(sentry.__file__), "..", "..", "config", "chartcuterie")
1112
)
1213

1314

15+
@all_silo_view
1416
def serve_chartcuterie_config(
1517
request: HttpRequest,
1618
) -> HttpResponseBase:

src/sentry/silo/base.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import abc
44
import contextlib
55
import functools
6-
import itertools
76
import threading
87
import typing
98
from collections.abc import Callable, Generator, Iterable
@@ -158,10 +157,11 @@ def override(*args: P.args, **kwargs: P.kwargs) -> R:
158157
if is_available:
159158
return original_method(*args, **kwargs)
160159
else:
160+
modes = list(self.modes)
161+
if SiloMode.MONOLITH not in self.modes:
162+
modes = modes + [SiloMode.MONOLITH]
161163
handler = self.handle_when_unavailable(
162-
original_method,
163-
SiloMode.get_current_mode(),
164-
itertools.chain([SiloMode.MONOLITH], self.modes),
164+
original_method, SiloMode.get_current_mode(), modes
165165
)
166166
return handler(*args, **kwargs)
167167

src/sentry/web/frontend/base.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@
5757

5858

5959
class ViewSiloLimit(SiloLimit):
60+
def __init__(self, modes: SiloMode | Iterable[SiloMode], internal: bool = False) -> None:
61+
if isinstance(modes, SiloMode):
62+
modes = [modes]
63+
self.modes = frozenset(modes)
64+
self.internal = internal
65+
6066
def modify_endpoint_class(self, decorated_class: type[View]) -> type:
6167
dispatch_override = self.create_override(decorated_class.dispatch)
6268
new_class = type(
@@ -71,7 +77,10 @@ def modify_endpoint_class(self, decorated_class: type[View]) -> type:
7177
return new_class
7278

7379
def modify_endpoint_method(self, decorated_method: Callable[..., Any]) -> Callable[..., Any]:
74-
return self.create_override(decorated_method)
80+
decorated = self.create_override(decorated_method)
81+
setattr(decorated, "silo_limit", self)
82+
83+
return decorated
7584

7685
def handle_when_unavailable(
7786
self,
@@ -115,25 +124,32 @@ def __call__(self, decorated_obj: Any) -> Any:
115124
raise TypeError("`@ViewSiloLimit` must decorate a class or method")
116125

117126

118-
control_silo_view = ViewSiloLimit(SiloMode.CONTROL)
127+
control_silo_view = ViewSiloLimit([SiloMode.CONTROL])
119128
"""
120129
Apply to frontend views that exist in CONTROL Silo
121130
If a request is received and the application is not in CONTROL/MONOLITH
122131
mode a 404 will be returned.
123132
"""
124133

125-
region_silo_view = ViewSiloLimit(SiloMode.REGION)
134+
region_silo_view = ViewSiloLimit([SiloMode.REGION])
126135
"""
127136
Apply to frontend views that exist in REGION Silo
128137
If a request is received and the application is not in REGION/MONOLITH
129138
mode a 404 will be returned.
130139
"""
131140

132-
all_silo_view = ViewSiloLimit(SiloMode.REGION, SiloMode.CONTROL, SiloMode.MONOLITH)
141+
all_silo_view = ViewSiloLimit([SiloMode.REGION, SiloMode.CONTROL, SiloMode.MONOLITH])
133142
"""
134143
Apply to frontend views that respond in both CONTROL and REGION mode.
135144
"""
136145

146+
internal_region_silo_view = ViewSiloLimit([SiloMode.REGION], internal=True)
147+
"""
148+
Apply to frontend views that exist in REGION Silo
149+
and are not accessible via cell routing.
150+
This is generally for debug/development views.
151+
"""
152+
137153

138154
class _HasRespond(Protocol):
139155
active_organization: RpcUserOrganizationContext | None

src/sentry/web/frontend/debug/charts/debug_chart_renderer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from sentry.charts import backend as charts
55
from sentry.charts.types import ChartType
6+
from sentry.web.frontend.base import internal_region_silo_view
67
from sentry.web.frontend.debug.mail import MailPreview
78

89
discover_total_period = {
@@ -279,6 +280,7 @@
279280
}
280281

281282

283+
@internal_region_silo_view
282284
class DebugChartRendererView(View):
283285
def get(self, request: HttpRequest) -> HttpResponse:
284286
ret = []

src/sentry/web/frontend/debug/charts/metric_alert_charts.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from sentry.charts import backend as charts
55
from sentry.charts.types import ChartType
66
from sentry.seer.anomaly_detection.types import AnomalyType
7+
from sentry.web.frontend.base import internal_region_silo_view
78
from sentry.web.frontend.debug.mail import MailPreview
89

910
incident = {
@@ -510,6 +511,7 @@
510511
}
511512

512513

514+
@internal_region_silo_view
513515
class DebugMetricAlertChartRendererView(View):
514516
def get(self, request: HttpRequest) -> HttpResponse:
515517
ret = []

src/sentry/web/frontend/debug/debug_auth_views.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
from django.views.generic import View
33

44
from sentry.users.models.user import User
5+
from sentry.web.frontend.base import internal_region_silo_view
56
from sentry.web.helpers import render_to_response
67

78

9+
@internal_region_silo_view
810
class DebugAuthConfirmIdentity(View):
911
def get(self, request: HttpRequest) -> HttpResponse:
1012
auth_identity = {"id": "[email protected]", "email": "[email protected]"}
@@ -21,6 +23,7 @@ def get(self, request: HttpRequest) -> HttpResponse:
2123
)
2224

2325

26+
@internal_region_silo_view
2427
class DebugAuthConfirmLink(View):
2528
def get(self, request: HttpRequest) -> HttpResponse:
2629
auth_identity = {"id": "[email protected]", "email": "[email protected]"}

src/sentry/web/frontend/debug/debug_codeowners_auto_sync_failure_email.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
from sentry.models.project import Project
77
from sentry.notifications.notifications.codeowners_auto_sync import AutoSyncNotification
88
from sentry.users.models.user import User
9+
from sentry.web.frontend.base import internal_region_silo_view
910

1011
from .mail import render_preview_email_for_notification
1112

1213

14+
@internal_region_silo_view
1315
class DebugCodeOwnersAutoSyncFailureView(View):
1416
def get(self, request: HttpRequest) -> HttpResponse:
1517
org = Organization(id=1, slug="petal", name="Petal")

src/sentry/web/frontend/debug/debug_cron_broken_monitor_email.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from django.http import HttpRequest, HttpResponse
44
from django.views.generic import View
55

6+
from sentry.web.frontend.base import internal_region_silo_view
7+
68
from .mail import MailPreview
79

810

@@ -17,6 +19,7 @@ def get_context():
1719
}
1820

1921

22+
@internal_region_silo_view
2023
class DebugCronBrokenMonitorEmailView(View):
2124
def get(self, request: HttpRequest) -> HttpResponse:
2225
context = get_context()

src/sentry/web/frontend/debug/debug_cron_muted_monitor_email.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from django.http import HttpRequest, HttpResponse
44
from django.views.generic import View
55

6+
from sentry.web.frontend.base import internal_region_silo_view
7+
68
from .mail import MailPreview
79

810

@@ -17,6 +19,7 @@ def get_context():
1719
}
1820

1921

22+
@internal_region_silo_view
2023
class DebugCronMutedMonitorEmailView(View):
2124
def get(self, request: HttpRequest) -> HttpResponse:
2225
context = get_context()

src/sentry/web/frontend/debug/debug_error_embed.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
from django.views.generic import View
66

77
from sentry.models.projectkey import ProjectKey
8+
from sentry.web.frontend.base import internal_region_silo_view
89
from sentry.web.helpers import render_to_response
910

1011

12+
@internal_region_silo_view
1113
class DebugErrorPageEmbedView(View):
1214
def _get_project_key(self):
1315
return ProjectKey.objects.filter(project=settings.SENTRY_PROJECT)[0]

0 commit comments

Comments
 (0)