|
14 | 14 | # limitations under the License.
|
15 | 15 |
|
16 | 16 | import argparse
|
17 |
| -from typing import Any, List, Union |
| 17 | +import logging |
| 18 | +from typing import Any, Dict, List, Union |
18 | 19 |
|
19 | 20 | import attr
|
20 | 21 |
|
|
42 | 43 | Please add ``start_pushers: false`` to the main config
|
43 | 44 | """
|
44 | 45 |
|
| 46 | +_DEPRECATED_WORKER_DUTY_OPTION_USED = """ |
| 47 | +The '%s' configuration option is deprecated and will be removed in a future |
| 48 | +Synapse version. Please use ``%s: name_of_worker`` instead. |
| 49 | +""" |
| 50 | + |
| 51 | +logger = logging.getLogger(__name__) |
| 52 | + |
45 | 53 |
|
46 | 54 | def _instance_to_list_converter(obj: Union[str, List[str]]) -> List[str]:
|
47 | 55 | """Helper for allowing parsing a string or list of strings to a config
|
@@ -296,6 +304,105 @@ def read_config(self, config: JsonDict, **kwargs: Any) -> None:
|
296 | 304 | self.worker_name is None and background_tasks_instance == "master"
|
297 | 305 | ) or self.worker_name == background_tasks_instance
|
298 | 306 |
|
| 307 | + self.should_notify_appservices = self._should_this_worker_perform_duty( |
| 308 | + config, |
| 309 | + legacy_master_option_name="notify_appservices", |
| 310 | + legacy_worker_app_name="synapse.app.appservice", |
| 311 | + new_option_name="notify_appservices_from_worker", |
| 312 | + ) |
| 313 | + |
| 314 | + def _should_this_worker_perform_duty( |
| 315 | + self, |
| 316 | + config: Dict[str, Any], |
| 317 | + legacy_master_option_name: str, |
| 318 | + legacy_worker_app_name: str, |
| 319 | + new_option_name: str, |
| 320 | + ) -> bool: |
| 321 | + """ |
| 322 | + Figures out whether this worker should perform a certain duty. |
| 323 | +
|
| 324 | + This function is temporary and is only to deal with the complexity |
| 325 | + of allowing old, transitional and new configurations all at once. |
| 326 | +
|
| 327 | + Contradictions between the legacy and new part of a transitional configuration |
| 328 | + will lead to a ConfigError. |
| 329 | +
|
| 330 | + Parameters: |
| 331 | + config: The config dictionary |
| 332 | + legacy_master_option_name: The name of a legacy option, whose value is boolean, |
| 333 | + specifying whether it's the master that should handle a certain duty. |
| 334 | + e.g. "notify_appservices" |
| 335 | + legacy_worker_app_name: The name of a legacy Synapse worker application |
| 336 | + that would traditionally perform this duty. |
| 337 | + e.g. "synapse.app.appservice" |
| 338 | + new_option_name: The name of the new option, whose value is the name of a |
| 339 | + designated worker to perform the duty. |
| 340 | + e.g. "notify_appservices_from_worker" |
| 341 | + """ |
| 342 | + |
| 343 | + # None means 'unspecified'; True means 'run here' and False means |
| 344 | + # 'don't run here'. |
| 345 | + new_option_should_run_here = None |
| 346 | + if new_option_name in config: |
| 347 | + designated_worker = config[new_option_name] or "master" |
| 348 | + new_option_should_run_here = ( |
| 349 | + designated_worker == "master" and self.worker_name is None |
| 350 | + ) or designated_worker == self.worker_name |
| 351 | + |
| 352 | + legacy_option_should_run_here = None |
| 353 | + if legacy_master_option_name in config: |
| 354 | + run_on_master = bool(config[legacy_master_option_name]) |
| 355 | + |
| 356 | + legacy_option_should_run_here = ( |
| 357 | + self.worker_name is None and run_on_master |
| 358 | + ) or (self.worker_app == legacy_worker_app_name and not run_on_master) |
| 359 | + |
| 360 | + # Suggest using the new option instead. |
| 361 | + logger.warning( |
| 362 | + _DEPRECATED_WORKER_DUTY_OPTION_USED, |
| 363 | + legacy_master_option_name, |
| 364 | + new_option_name, |
| 365 | + ) |
| 366 | + |
| 367 | + if self.worker_app == legacy_worker_app_name and config.get( |
| 368 | + legacy_master_option_name, True |
| 369 | + ): |
| 370 | + # As an extra bit of complication, we need to check that the |
| 371 | + # specialised worker is only used if the legacy config says the |
| 372 | + # master isn't performing the duties. |
| 373 | + raise ConfigError( |
| 374 | + f"Cannot use deprecated worker app type '{legacy_worker_app_name}' whilst deprecated option '{legacy_master_option_name}' is not set to false.\n" |
| 375 | + f"Consider setting `worker_app: synapse.app.generic_worker` and using the '{new_option_name}' option instead.\n" |
| 376 | + f"The '{new_option_name}' option replaces '{legacy_master_option_name}'." |
| 377 | + ) |
| 378 | + |
| 379 | + if new_option_should_run_here is None and legacy_option_should_run_here is None: |
| 380 | + # Neither option specified; the fallback behaviour is to run on the main process |
| 381 | + return self.worker_name is None |
| 382 | + |
| 383 | + if ( |
| 384 | + new_option_should_run_here is not None |
| 385 | + and legacy_option_should_run_here is not None |
| 386 | + ): |
| 387 | + # Both options specified; ensure they match! |
| 388 | + if new_option_should_run_here != legacy_option_should_run_here: |
| 389 | + update_worker_type = ( |
| 390 | + " and set worker_app: synapse.app.generic_worker" |
| 391 | + if self.worker_app == legacy_worker_app_name |
| 392 | + else "" |
| 393 | + ) |
| 394 | + # If the values conflict, we suggest the admin removes the legacy option |
| 395 | + # for simplicity. |
| 396 | + raise ConfigError( |
| 397 | + f"Conflicting configuration options: {legacy_master_option_name} (legacy), {new_option_name} (new).\n" |
| 398 | + f"Suggestion: remove {legacy_master_option_name}{update_worker_type}.\n" |
| 399 | + ) |
| 400 | + |
| 401 | + # We've already validated that these aren't conflicting; now just see if |
| 402 | + # either is True. |
| 403 | + # (By this point, these are either the same value or only one is not None.) |
| 404 | + return bool(new_option_should_run_here or legacy_option_should_run_here) |
| 405 | + |
299 | 406 | def generate_config_section(self, **kwargs: Any) -> str:
|
300 | 407 | return """\
|
301 | 408 | ## Workers ##
|
|
0 commit comments