Coverage for app/backend/src/couchers/server.py: 93%
88 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-22 18:39 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-22 18:39 +0000
1from concurrent import futures
2from typing import Any
4import grpc
6from couchers.config import config
7from couchers.constants import SERVER_THREADS
8from couchers.db import _get_base_engine
9from couchers.interceptors import (
10 CouchersMiddlewareInterceptor,
11 ErrorSanitizationInterceptor,
12 OTelInterceptor,
13)
14from couchers.metrics import grpc_in_flight_gauge, start_worker_resource_sampler
15from couchers.proto import (
16 account_pb2_grpc,
17 admin_pb2_grpc,
18 api_pb2_grpc,
19 auth_pb2_grpc,
20 blocking_pb2_grpc,
21 bugs_pb2_grpc,
22 communities_pb2_grpc,
23 conversations_pb2_grpc,
24 dashboard_pb2_grpc,
25 discussions_pb2_grpc,
26 donations_pb2_grpc,
27 editor_pb2_grpc,
28 events_pb2_grpc,
29 galleries_pb2_grpc,
30 gis_pb2_grpc,
31 groups_pb2_grpc,
32 iris_pb2_grpc,
33 jail_pb2_grpc,
34 media_pb2_grpc,
35 moderation_pb2_grpc,
36 notifications_pb2_grpc,
37 pages_pb2_grpc,
38 postal_verification_pb2_grpc,
39 public_pb2_grpc,
40 public_trips_pb2_grpc,
41 references_pb2_grpc,
42 reporting_pb2_grpc,
43 requests_pb2_grpc,
44 resources_pb2_grpc,
45 search_pb2_grpc,
46 stripe_pb2_grpc,
47 threads_pb2_grpc,
48)
49from couchers.servicers.account import Account, Iris
50from couchers.servicers.admin import Admin
51from couchers.servicers.api import API
52from couchers.servicers.auth import Auth
53from couchers.servicers.blocking import Blocking
54from couchers.servicers.bugs import Bugs
55from couchers.servicers.communities import Communities
56from couchers.servicers.conversations import Conversations
57from couchers.servicers.dashboard import Dashboard
58from couchers.servicers.discussions import Discussions
59from couchers.servicers.donations import Donations, Stripe
60from couchers.servicers.editor import Editor
61from couchers.servicers.events import Events
62from couchers.servicers.galleries import Galleries
63from couchers.servicers.gis import GIS
64from couchers.servicers.groups import Groups
65from couchers.servicers.jail import Jail
66from couchers.servicers.media import Media, get_media_auth_interceptor
67from couchers.servicers.moderation import Moderation
68from couchers.servicers.notifications import Notifications
69from couchers.servicers.pages import Pages
70from couchers.servicers.postal_verification import PostalVerification
71from couchers.servicers.public import Public
72from couchers.servicers.public_trips import PublicTrips
73from couchers.servicers.references import References
74from couchers.servicers.reporting import Reporting
75from couchers.servicers.requests import Requests
76from couchers.servicers.resources import Resources
77from couchers.servicers.search import Search
78from couchers.servicers.threads import Threads
81class _InstrumentedThreadPoolExecutor(futures.ThreadPoolExecutor):
82 # gRPC submits one task per RPC
83 def submit(self, fn: Any, /, *args: Any, **kwargs: Any) -> futures.Future[Any]:
84 grpc_in_flight_gauge.inc()
85 future = super().submit(fn, *args, **kwargs)
86 future.add_done_callback(lambda _: grpc_in_flight_gauge.dec())
87 return future
90def create_main_server(port: int, start_resource_sampler: bool = False) -> grpc.Server:
91 executor = _InstrumentedThreadPoolExecutor(SERVER_THREADS)
92 server = grpc.server(
93 executor,
94 interceptors=[
95 ErrorSanitizationInterceptor(),
96 OTelInterceptor(),
97 CouchersMiddlewareInterceptor(),
98 ],
99 )
100 if start_resource_sampler: 100 ↛ 101line 100 didn't jump to line 101 because the condition on line 100 was never true
101 start_worker_resource_sampler(executor, _get_base_engine())
102 server.add_insecure_port(f"[::]:{port}")
104 account_pb2_grpc.add_AccountServicer_to_server(Account(), server)
105 admin_pb2_grpc.add_AdminServicer_to_server(Admin(), server)
106 api_pb2_grpc.add_APIServicer_to_server(API(), server)
107 moderation_pb2_grpc.add_ModerationServicer_to_server(Moderation(), server)
108 auth_pb2_grpc.add_AuthServicer_to_server(Auth(), server)
109 blocking_pb2_grpc.add_BlockingServicer_to_server(Blocking(), server)
110 bugs_pb2_grpc.add_BugsServicer_to_server(Bugs(), server)
111 communities_pb2_grpc.add_CommunitiesServicer_to_server(Communities(), server)
112 conversations_pb2_grpc.add_ConversationsServicer_to_server(Conversations(), server)
113 dashboard_pb2_grpc.add_DashboardServicer_to_server(Dashboard(), server)
114 discussions_pb2_grpc.add_DiscussionsServicer_to_server(Discussions(), server)
115 donations_pb2_grpc.add_DonationsServicer_to_server(Donations(), server)
116 editor_pb2_grpc.add_EditorServicer_to_server(Editor(), server)
117 events_pb2_grpc.add_EventsServicer_to_server(Events(), server)
118 galleries_pb2_grpc.add_GalleriesServicer_to_server(Galleries(), server)
119 gis_pb2_grpc.add_GISServicer_to_server(GIS(), server)
120 groups_pb2_grpc.add_GroupsServicer_to_server(Groups(), server)
121 iris_pb2_grpc.add_IrisServicer_to_server(Iris(), server)
122 jail_pb2_grpc.add_JailServicer_to_server(Jail(), server)
123 notifications_pb2_grpc.add_NotificationsServicer_to_server(Notifications(), server)
124 pages_pb2_grpc.add_PagesServicer_to_server(Pages(), server)
125 postal_verification_pb2_grpc.add_PostalVerificationServicer_to_server(PostalVerification(), server)
126 public_pb2_grpc.add_PublicServicer_to_server(Public(), server)
127 public_trips_pb2_grpc.add_PublicTripsServicer_to_server(PublicTrips(), server)
128 references_pb2_grpc.add_ReferencesServicer_to_server(References(), server)
129 reporting_pb2_grpc.add_ReportingServicer_to_server(Reporting(), server)
130 requests_pb2_grpc.add_RequestsServicer_to_server(Requests(), server)
131 resources_pb2_grpc.add_ResourcesServicer_to_server(Resources(), server)
132 search_pb2_grpc.add_SearchServicer_to_server(Search(), server)
133 stripe_pb2_grpc.add_StripeServicer_to_server(Stripe(), server)
134 threads_pb2_grpc.add_ThreadsServicer_to_server(Threads(), server)
135 return server
138def create_media_server(port: int, threads: int = 8) -> grpc.Server:
139 media_server = grpc.server(
140 futures.ThreadPoolExecutor(threads),
141 interceptors=[
142 get_media_auth_interceptor(config.MEDIA_SERVER_BEARER_TOKEN),
143 ],
144 )
145 media_server.add_insecure_port(f"[::]:{port}")
146 media_pb2_grpc.add_MediaServicer_to_server(Media(), media_server)
147 return media_server