1212# See the License for the specific language governing permissions and
1313# limitations under the License.
1414import logging
15+ from http import HTTPStatus
1516from typing import TYPE_CHECKING , Tuple
1617
1718from synapse .api .errors import SynapseError
18- from synapse .http .servlet import RestServlet , parse_json_object_from_request
19+ from synapse .http .servlet import (
20+ RestServlet ,
21+ assert_params_in_dict ,
22+ parse_json_object_from_request ,
23+ )
1924from synapse .http .site import SynapseRequest
2025from synapse .rest .admin ._base import admin_patterns , assert_user_is_admin
2126from synapse .types import JsonDict
2934class BackgroundUpdateEnabledRestServlet (RestServlet ):
3035 """Allows temporarily disabling background updates"""
3136
32- PATTERNS = admin_patterns ("/background_updates/enabled" )
37+ PATTERNS = admin_patterns ("/background_updates/enabled$ " )
3338
3439 def __init__ (self , hs : "HomeServer" ):
35- self .group_server = hs .get_groups_server_handler ()
36- self .is_mine_id = hs .is_mine_id
37- self .auth = hs .get_auth ()
38-
39- self .data_stores = hs .get_datastores ()
40+ self ._auth = hs .get_auth ()
41+ self ._data_stores = hs .get_datastores ()
4042
4143 async def on_GET (self , request : SynapseRequest ) -> Tuple [int , JsonDict ]:
42- requester = await self .auth .get_user_by_req (request )
43- await assert_user_is_admin (self .auth , requester .user )
44+ requester = await self ._auth .get_user_by_req (request )
45+ await assert_user_is_admin (self ._auth , requester .user )
4446
4547 # We need to check that all configured databases have updates enabled.
4648 # (They *should* all be in sync.)
47- enabled = all (db .updates .enabled for db in self .data_stores .databases )
49+ enabled = all (db .updates .enabled for db in self ._data_stores .databases )
4850
49- return 200 , {"enabled" : enabled }
51+ return HTTPStatus . OK , {"enabled" : enabled }
5052
5153 async def on_POST (self , request : SynapseRequest ) -> Tuple [int , JsonDict ]:
52- requester = await self .auth .get_user_by_req (request )
53- await assert_user_is_admin (self .auth , requester .user )
54+ requester = await self ._auth .get_user_by_req (request )
55+ await assert_user_is_admin (self ._auth , requester .user )
5456
5557 body = parse_json_object_from_request (request )
5658
5759 enabled = body .get ("enabled" , True )
5860
5961 if not isinstance (enabled , bool ):
60- raise SynapseError (400 , "'enabled' parameter must be a boolean" )
62+ raise SynapseError (
63+ HTTPStatus .BAD_REQUEST , "'enabled' parameter must be a boolean"
64+ )
6165
62- for db in self .data_stores .databases :
66+ for db in self ._data_stores .databases :
6367 db .updates .enabled = enabled
6468
6569 # If we're re-enabling them ensure that we start the background
6670 # process again.
6771 if enabled :
6872 db .updates .start_doing_background_updates ()
6973
70- return 200 , {"enabled" : enabled }
74+ return HTTPStatus . OK , {"enabled" : enabled }
7175
7276
7377class BackgroundUpdateRestServlet (RestServlet ):
7478 """Fetch information about background updates"""
7579
76- PATTERNS = admin_patterns ("/background_updates/status" )
80+ PATTERNS = admin_patterns ("/background_updates/status$ " )
7781
7882 def __init__ (self , hs : "HomeServer" ):
79- self .group_server = hs .get_groups_server_handler ()
80- self .is_mine_id = hs .is_mine_id
81- self .auth = hs .get_auth ()
82-
83- self .data_stores = hs .get_datastores ()
83+ self ._auth = hs .get_auth ()
84+ self ._data_stores = hs .get_datastores ()
8485
8586 async def on_GET (self , request : SynapseRequest ) -> Tuple [int , JsonDict ]:
86- requester = await self .auth .get_user_by_req (request )
87- await assert_user_is_admin (self .auth , requester .user )
87+ requester = await self ._auth .get_user_by_req (request )
88+ await assert_user_is_admin (self ._auth , requester .user )
8889
8990 # We need to check that all configured databases have updates enabled.
9091 # (They *should* all be in sync.)
91- enabled = all (db .updates .enabled for db in self .data_stores .databases )
92+ enabled = all (db .updates .enabled for db in self ._data_stores .databases )
9293
9394 current_updates = {}
9495
95- for db in self .data_stores .databases :
96+ for db in self ._data_stores .databases :
9697 update = db .updates .get_current_update ()
9798 if not update :
9899 continue
@@ -104,4 +105,72 @@ async def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
104105 "average_items_per_ms" : update .average_items_per_ms (),
105106 }
106107
107- return 200 , {"enabled" : enabled , "current_updates" : current_updates }
108+ return HTTPStatus .OK , {"enabled" : enabled , "current_updates" : current_updates }
109+
110+
111+ class BackgroundUpdateStartJobRestServlet (RestServlet ):
112+ """Allows to start specific background updates"""
113+
114+ PATTERNS = admin_patterns ("/background_updates/start_job" )
115+
116+ def __init__ (self , hs : "HomeServer" ):
117+ self ._auth = hs .get_auth ()
118+ self ._store = hs .get_datastore ()
119+
120+ async def on_POST (self , request : SynapseRequest ) -> Tuple [int , JsonDict ]:
121+ requester = await self ._auth .get_user_by_req (request )
122+ await assert_user_is_admin (self ._auth , requester .user )
123+
124+ body = parse_json_object_from_request (request )
125+ assert_params_in_dict (body , ["job_name" ])
126+
127+ job_name = body ["job_name" ]
128+
129+ if job_name == "populate_stats_process_rooms" :
130+ jobs = [
131+ {
132+ "update_name" : "populate_stats_process_rooms" ,
133+ "progress_json" : "{}" ,
134+ },
135+ ]
136+ elif job_name == "regenerate_directory" :
137+ jobs = [
138+ {
139+ "update_name" : "populate_user_directory_createtables" ,
140+ "progress_json" : "{}" ,
141+ "depends_on" : "" ,
142+ },
143+ {
144+ "update_name" : "populate_user_directory_process_rooms" ,
145+ "progress_json" : "{}" ,
146+ "depends_on" : "populate_user_directory_createtables" ,
147+ },
148+ {
149+ "update_name" : "populate_user_directory_process_users" ,
150+ "progress_json" : "{}" ,
151+ "depends_on" : "populate_user_directory_process_rooms" ,
152+ },
153+ {
154+ "update_name" : "populate_user_directory_cleanup" ,
155+ "progress_json" : "{}" ,
156+ "depends_on" : "populate_user_directory_process_users" ,
157+ },
158+ ]
159+ else :
160+ raise SynapseError (HTTPStatus .BAD_REQUEST , "Invalid job_name" )
161+
162+ try :
163+ await self ._store .db_pool .simple_insert_many (
164+ table = "background_updates" ,
165+ values = jobs ,
166+ desc = f"admin_api_run_{ job_name } " ,
167+ )
168+ except self ._store .db_pool .engine .module .IntegrityError :
169+ raise SynapseError (
170+ HTTPStatus .BAD_REQUEST ,
171+ "Job %s is already in queue of background updates." % (job_name ,),
172+ )
173+
174+ self ._store .db_pool .updates .start_doing_background_updates ()
175+
176+ return HTTPStatus .OK , {}
0 commit comments