Coverage for app/backend/src/couchers/server.py: 93%
88 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-03 11:56 +0000
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-03 11:56 +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.metrics import grpc_in_flight_gauge, start_worker_resource_sampler
10from couchers.middleware.interceptors import (
11 CouchersMiddlewareInterceptor,
12 ErrorSanitizationInterceptor,
13 OTelInterceptor,
14)
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 discussions_pb2_grpc,
25 donations_pb2_grpc,
26 editor_pb2_grpc,
27 events_pb2_grpc,
28 galleries_pb2_grpc,
29 gis_pb2_grpc,
30 groups_pb2_grpc,
31 iris_pb2_grpc,
32 jail_pb2_grpc,
33 media_pb2_grpc,
34 moderation_pb2_grpc,
35 notifications_pb2_grpc,
36 pages_pb2_grpc,
37 postal_verification_pb2_grpc,
38 public_pb2_grpc,
39 public_trips_pb2_grpc,
40 references_pb2_grpc,
41 reporting_pb2_grpc,
42 requests_pb2_grpc,
43 resources_pb2_grpc,
44 screens_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.discussions import Discussions
58from couchers.servicers.donations import Donations, Stripe
59from couchers.servicers.editor import Editor
60from couchers.servicers.events import Events
61from couchers.servicers.galleries import Galleries
62from couchers.servicers.gis import GIS
63from couchers.servicers.groups import Groups
64from couchers.servicers.jail import Jail
65from couchers.servicers.media import Media, get_media_auth_interceptor
66from couchers.servicers.moderation import Moderation
67from couchers.servicers.notifications import Notifications
68from couchers.servicers.pages import Pages
69from couchers.servicers.postal_verification import PostalVerification
70from couchers.servicers.public import Public
71from couchers.servicers.public_trips import PublicTrips
72from couchers.servicers.references import References
73from couchers.servicers.reporting import Reporting
74from couchers.servicers.requests import Requests
75from couchers.servicers.resources import Resources
76from couchers.servicers.screens import Screens
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 discussions_pb2_grpc.add_DiscussionsServicer_to_server(Discussions(), server)
114 donations_pb2_grpc.add_DonationsServicer_to_server(Donations(), server)
115 editor_pb2_grpc.add_EditorServicer_to_server(Editor(), server)
116 events_pb2_grpc.add_EventsServicer_to_server(Events(), server)
117 galleries_pb2_grpc.add_GalleriesServicer_to_server(Galleries(), server)
118 gis_pb2_grpc.add_GISServicer_to_server(GIS(), server)
119 groups_pb2_grpc.add_GroupsServicer_to_server(Groups(), server)
120 iris_pb2_grpc.add_IrisServicer_to_server(Iris(), server)
121 jail_pb2_grpc.add_JailServicer_to_server(Jail(), server)
122 notifications_pb2_grpc.add_NotificationsServicer_to_server(Notifications(), server)
123 pages_pb2_grpc.add_PagesServicer_to_server(Pages(), server)
124 postal_verification_pb2_grpc.add_PostalVerificationServicer_to_server(PostalVerification(), server)
125 public_pb2_grpc.add_PublicServicer_to_server(Public(), server)
126 public_trips_pb2_grpc.add_PublicTripsServicer_to_server(PublicTrips(), server)
127 references_pb2_grpc.add_ReferencesServicer_to_server(References(), server)
128 reporting_pb2_grpc.add_ReportingServicer_to_server(Reporting(), server)
129 requests_pb2_grpc.add_RequestsServicer_to_server(Requests(), server)
130 resources_pb2_grpc.add_ResourcesServicer_to_server(Resources(), server)
131 screens_pb2_grpc.add_ScreensServicer_to_server(Screens(), 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