From b9c093b536ef85de225d279998bb45a69e92705e Mon Sep 17 00:00:00 2001 From: QEDeD Date: Sun, 27 Sep 2026 18:16:44 +0200 Subject: [PATCH] Resolve shared Synapse worker unit values once per run The worker systemd service template is rendered once per worker, and Ansible re-evaluates every variable it references (and every variable those depend on) on each render. Most of these values are identical for all workers, e.g. the Redis/Valkey and Postgres socket settings, which fan out into chains like matrix_playbook_synapse_uses_managed_valkey -> valkey_enabled -> matrix_bridge_hookshot_*. Resolve the worker-independent values once in setup_install.yml, before the per-worker loop, and have the template read them from a single fact. The per-worker-type argument selection becomes a lookup, so a render no longer evaluates all 12 type-specific argument lists. Rendered units are byte-identical. With the specialized-workers preset (19 workers), the systemd service tasks went from 28.8s to ~13.5s on ansible-core 2.20.1 (connection=local), close to the ~0.6s-per-task cost of templating a static file. Deployments whose inventory makes these variables more expensive to evaluate gain proportionally more. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../tasks/synapse/workers/setup_install.yml | 44 ++++++++++ .../workers/util/setup_files_for_worker.yml | 2 +- .../systemd/matrix-synapse-worker.service.j2 | 83 +++++++------------ 3 files changed, 74 insertions(+), 55 deletions(-) diff --git a/roles/custom/matrix-synapse/tasks/synapse/workers/setup_install.yml b/roles/custom/matrix-synapse/tasks/synapse/workers/setup_install.yml index e50df3259..f1cf2be75 100644 --- a/roles/custom/matrix-synapse/tasks/synapse/workers/setup_install.yml +++ b/roles/custom/matrix-synapse/tasks/synapse/workers/setup_install.yml @@ -59,6 +59,50 @@ with_items: "{{ matrix_synapse_workers_current_label_files.files }}" when: "not ansible_check_mode and (item.path | basename | replace ('worker.', '') | replace('.labels', '')) not in matrix_synapse_enabled_worker_names" +# Ansible re-evaluates every variable a template references (and all variables those depend on) each time the template is rendered. +# The worker systemd service template is rendered once per worker and mostly references values that are the same for all workers, +# so we resolve those once here instead of re-deriving them for every worker. +- name: Resolve worker-independent values for the worker systemd service template + ansible.builtin.set_fact: + matrix_synapse_worker_systemd_shared: + config_dir_path: "{{ matrix_synapse_config_dir_path }}" + base_path: "{{ matrix_synapse_base_path }}" + storage_path: "{{ matrix_synapse_storage_path }}" + uid: "{{ matrix_synapse_uid }}" + gid: "{{ matrix_synapse_gid }}" + tmp_directory_size_mb: "{{ matrix_synapse_tmp_directory_size_mb }}" + container_image_final: "{{ matrix_synapse_container_image_final }}" + container_network: "{{ matrix_synapse_container_network }}" + container_additional_networks: "{{ matrix_synapse_container_additional_networks }}" + container_additional_volumes: "{{ matrix_synapse_container_additional_volumes }}" + container_arguments: "{{ matrix_synapse_container_arguments }}" + container_worker_arguments_by_type: + room_worker: "{{ matrix_synapse_workers_room_workers_container_arguments }}" + sync_worker: "{{ matrix_synapse_workers_sync_workers_container_arguments }}" + client_reader: "{{ matrix_synapse_workers_client_reader_workers_container_arguments }}" + federation_reader: "{{ matrix_synapse_workers_federation_reader_workers_container_arguments }}" + generic_worker: "{{ matrix_synapse_workers_generic_workers_container_arguments }}" + stream_writer: "{{ matrix_synapse_workers_stream_writers_container_arguments }}" + federation_sender: "{{ matrix_synapse_workers_federation_sender_workers_container_arguments }}" + pusher: "{{ matrix_synapse_workers_pusher_workers_container_arguments }}" + appservice: "{{ matrix_synapse_workers_appservice_workers_container_arguments }}" + user_dir: "{{ matrix_synapse_workers_user_dir_workers_container_arguments }}" + background: "{{ matrix_synapse_workers_background_workers_container_arguments }}" + media_repository: "{{ matrix_synapse_workers_media_repository_workers_container_arguments }}" + workers_enabled: "{{ matrix_synapse_workers_enabled }}" + workers_container_host_bind_address: "{{ matrix_synapse_workers_container_host_bind_address }}" + redis_path_enabled: "{{ matrix_synapse_redis_path_enabled }}" + redis_path: "{{ matrix_synapse_redis_path }}" + redis_path_host: "{{ matrix_synapse_redis_path_host }}" + database_socket_enabled: "{{ matrix_synapse_database_socket_enabled }}" + database_socket_path: "{{ matrix_synapse_database_socket_path }}" + database_socket_path_host: "{{ matrix_synapse_database_socket_path_host }}" + systemd_path: "{{ devture_systemd_docker_base_systemd_path }}" + systemd_unit_home_path: "{{ devture_systemd_docker_base_systemd_unit_home_path }}" + host_command_sh: "{{ devture_systemd_docker_base_host_command_sh }}" + host_command_docker: "{{ devture_systemd_docker_base_host_command_docker }}" + container_stop_grace_time_seconds: "{{ devture_systemd_docker_base_container_stop_grace_time_seconds }}" + - name: Ensure creation of worker systemd service files and configuration files ansible.builtin.include_tasks: "{{ role_path }}/tasks/synapse/workers/util/setup_files_for_worker.yml" with_items: "{{ matrix_synapse_workers_enabled_list }}" diff --git a/roles/custom/matrix-synapse/tasks/synapse/workers/util/setup_files_for_worker.yml b/roles/custom/matrix-synapse/tasks/synapse/workers/util/setup_files_for_worker.yml index d6c55fb25..47d44a592 100644 --- a/roles/custom/matrix-synapse/tasks/synapse/workers/util/setup_files_for_worker.yml +++ b/roles/custom/matrix-synapse/tasks/synapse/workers/util/setup_files_for_worker.yml @@ -32,5 +32,5 @@ - name: Ensure systemd service exists for {{ matrix_synapse_worker_systemd_service_name }} ansible.builtin.template: src: "{{ role_path }}/templates/synapse/systemd/matrix-synapse-worker.service.j2" - dest: "{{ devture_systemd_docker_base_systemd_path }}/{{ matrix_synapse_worker_systemd_service_name }}.service" + dest: "{{ matrix_synapse_worker_systemd_shared.systemd_path }}/{{ matrix_synapse_worker_systemd_service_name }}.service" mode: '0644' diff --git a/roles/custom/matrix-synapse/templates/synapse/systemd/matrix-synapse-worker.service.j2 b/roles/custom/matrix-synapse/templates/synapse/systemd/matrix-synapse-worker.service.j2 index 1ff0e9606..dc18314c2 100644 --- a/roles/custom/matrix-synapse/templates/synapse/systemd/matrix-synapse-worker.service.j2 +++ b/roles/custom/matrix-synapse/templates/synapse/systemd/matrix-synapse-worker.service.j2 @@ -1,100 +1,75 @@ #jinja2: lstrip_blocks: True [Unit] Description=Synapse worker ({{ matrix_synapse_worker_container_name }}) -AssertPathExists={{ matrix_synapse_config_dir_path }}/{{ matrix_synapse_worker_config_file_name }} +AssertPathExists={{ matrix_synapse_worker_systemd_shared.config_dir_path }}/{{ matrix_synapse_worker_config_file_name }} After=matrix-synapse.service Requires=matrix-synapse.service -{% set matrix_synapse_container_worker_arguments = [] %} +{% set matrix_synapse_container_worker_arguments = matrix_synapse_worker_systemd_shared.container_worker_arguments_by_type[matrix_synapse_worker_type] | default([]) %} -{% if matrix_synapse_worker_type == "room_worker" %} - {% set matrix_synapse_container_worker_arguments = matrix_synapse_workers_room_workers_container_arguments %} -{% elif matrix_synapse_worker_type == "sync_worker" %} - {% set matrix_synapse_container_worker_arguments = matrix_synapse_workers_sync_workers_container_arguments %} -{% elif matrix_synapse_worker_type == "client_reader" %} - {% set matrix_synapse_container_worker_arguments = matrix_synapse_workers_client_reader_workers_container_arguments %} -{% elif matrix_synapse_worker_type == "federation_reader" %} - {% set matrix_synapse_container_worker_arguments = matrix_synapse_workers_federation_reader_workers_container_arguments %} -{% elif matrix_synapse_worker_type == "generic_worker" %} - {% set matrix_synapse_container_worker_arguments = matrix_synapse_workers_generic_workers_container_arguments %} -{% elif matrix_synapse_worker_type == "stream_writer" %} - {% set matrix_synapse_container_worker_arguments = matrix_synapse_workers_stream_writers_container_arguments %} -{% elif matrix_synapse_worker_type == "federation_sender" %} - {% set matrix_synapse_container_worker_arguments = matrix_synapse_workers_federation_sender_workers_container_arguments %} -{% elif matrix_synapse_worker_type == "pusher" %} - {% set matrix_synapse_container_worker_arguments = matrix_synapse_workers_pusher_workers_container_arguments %} -{% elif matrix_synapse_worker_type == "appservice" %} - {% set matrix_synapse_container_worker_arguments = matrix_synapse_workers_appservice_workers_container_arguments %} -{% elif matrix_synapse_worker_type == "user_dir" %} - {% set matrix_synapse_container_worker_arguments = matrix_synapse_workers_user_dir_workers_container_arguments %} -{% elif matrix_synapse_worker_type == "background" %} - {% set matrix_synapse_container_worker_arguments = matrix_synapse_workers_background_workers_container_arguments %} -{% elif matrix_synapse_worker_type == "media_repository" %} - {% set matrix_synapse_container_worker_arguments = matrix_synapse_workers_media_repository_workers_container_arguments %} -{% endif %} [Service] Type=simple -Environment="HOME={{ devture_systemd_docker_base_systemd_unit_home_path }}" +Environment="HOME={{ matrix_synapse_worker_systemd_shared.systemd_unit_home_path }}" -ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} stop -t {{ devture_systemd_docker_base_container_stop_grace_time_seconds }} {{ matrix_synapse_worker_container_name }} 2>/dev/null || true' -ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm {{ matrix_synapse_worker_container_name }} 2>/dev/null || true' +ExecStartPre=-{{ matrix_synapse_worker_systemd_shared.host_command_sh }} -c '{{ matrix_synapse_worker_systemd_shared.host_command_docker }} stop -t {{ matrix_synapse_worker_systemd_shared.container_stop_grace_time_seconds }} {{ matrix_synapse_worker_container_name }} 2>/dev/null || true' +ExecStartPre=-{{ matrix_synapse_worker_systemd_shared.host_command_sh }} -c '{{ matrix_synapse_worker_systemd_shared.host_command_docker }} rm {{ matrix_synapse_worker_container_name }} 2>/dev/null || true' -ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} create \ +ExecStartPre={{ matrix_synapse_worker_systemd_shared.host_command_docker }} create \ --rm \ --name={{ matrix_synapse_worker_container_name }} \ --log-driver=none \ - --user={{ matrix_synapse_uid }}:{{ matrix_synapse_gid }} \ + --user={{ matrix_synapse_worker_systemd_shared.uid }}:{{ matrix_synapse_worker_systemd_shared.gid }} \ --cap-drop=ALL \ --read-only \ - --tmpfs=/tmp:rw,noexec,nosuid,size={{ matrix_synapse_tmp_directory_size_mb }}m \ - --network={{ matrix_synapse_container_network }} \ + --tmpfs=/tmp:rw,noexec,nosuid,size={{ matrix_synapse_worker_systemd_shared.tmp_directory_size_mb }}m \ + --network={{ matrix_synapse_worker_systemd_shared.container_network }} \ {% if matrix_synapse_worker_details.port != 0 and matrix_synapse_worker_details.webserving %} --health-cmd 'curl -fSs http://localhost:{{ matrix_synapse_worker_details.port }}/health || exit 1' \ {% else %} --no-healthcheck \ {% endif %} - {% if matrix_synapse_workers_enabled and matrix_synapse_workers_container_host_bind_address %} + {% if matrix_synapse_worker_systemd_shared.workers_enabled and matrix_synapse_worker_systemd_shared.workers_container_host_bind_address %} {% if matrix_synapse_worker_details.port != 0 %} - -p {{ '' if matrix_synapse_workers_container_host_bind_address == '*' else (matrix_synapse_workers_container_host_bind_address + ':') }}{{ matrix_synapse_worker_details.port }}:{{ matrix_synapse_worker_details.port }} \ + -p {{ '' if matrix_synapse_worker_systemd_shared.workers_container_host_bind_address == '*' else (matrix_synapse_worker_systemd_shared.workers_container_host_bind_address + ':') }}{{ matrix_synapse_worker_details.port }}:{{ matrix_synapse_worker_details.port }} \ {% endif %} {% if matrix_synapse_worker_details.metrics_port != 0 %} - -p {{ '' if matrix_synapse_workers_container_host_bind_address == '*' else (matrix_synapse_workers_container_host_bind_address + ':') }}{{ matrix_synapse_worker_details.metrics_port }}:{{ matrix_synapse_worker_details.metrics_port }} \ + -p {{ '' if matrix_synapse_worker_systemd_shared.workers_container_host_bind_address == '*' else (matrix_synapse_worker_systemd_shared.workers_container_host_bind_address + ':') }}{{ matrix_synapse_worker_details.metrics_port }}:{{ matrix_synapse_worker_details.metrics_port }} \ {% endif %} {% endif %} - --mount type=bind,src={{ matrix_synapse_config_dir_path }},dst=/data,ro \ - --mount type=bind,src={{ matrix_synapse_storage_path }},dst=/matrix-media-store-parent,bind-propagation=slave \ - {% for volume in matrix_synapse_container_additional_volumes %} + --mount type=bind,src={{ matrix_synapse_worker_systemd_shared.config_dir_path }},dst=/data,ro \ + --mount type=bind,src={{ matrix_synapse_worker_systemd_shared.storage_path }},dst=/matrix-media-store-parent,bind-propagation=slave \ + {% for volume in matrix_synapse_worker_systemd_shared.container_additional_volumes %} --mount type={{ volume.type | default('bind' if '/' in volume.src else 'volume') }},src={{ volume.src }},dst={{ volume.dst }}{{ (',' + volume.options) if volume.options else '' }} \ {% endfor %} - {% if matrix_synapse_redis_path_enabled %} - --mount type=bind,src={{ matrix_synapse_redis_path_host }},dst={{ matrix_synapse_redis_path }} \ + {% if matrix_synapse_worker_systemd_shared.redis_path_enabled %} + --mount type=bind,src={{ matrix_synapse_worker_systemd_shared.redis_path_host }},dst={{ matrix_synapse_worker_systemd_shared.redis_path }} \ {% endif %} - {% if matrix_synapse_database_socket_enabled %} - --mount type=bind,src={{ matrix_synapse_database_socket_path_host }},dst={{ matrix_synapse_database_socket_path }} \ + {% if matrix_synapse_worker_systemd_shared.database_socket_enabled %} + --mount type=bind,src={{ matrix_synapse_worker_systemd_shared.database_socket_path_host }},dst={{ matrix_synapse_worker_systemd_shared.database_socket_path }} \ {% endif %} - --label-file={{ matrix_synapse_base_path }}/{{ matrix_synapse_worker_labels_file_name }} \ - {% for arg in matrix_synapse_container_arguments %} + --label-file={{ matrix_synapse_worker_systemd_shared.base_path }}/{{ matrix_synapse_worker_labels_file_name }} \ + {% for arg in matrix_synapse_worker_systemd_shared.container_arguments %} {{ arg }} \ {% endfor %} {% for arg in matrix_synapse_container_worker_arguments %} {{ arg }} \ {% endfor %} - {{ matrix_synapse_container_image_final }} \ + {{ matrix_synapse_worker_systemd_shared.container_image_final }} \ run -m synapse.app.{{ matrix_synapse_worker_details.app }} -c /data/homeserver.yaml -c /data/{{ matrix_synapse_worker_config_file_name }} -{% if matrix_synapse_container_network != 'host' %} -{% for network in matrix_synapse_container_additional_networks %} -ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} network connect {{ network }} {{ matrix_synapse_worker_container_name }} +{% if matrix_synapse_worker_systemd_shared.container_network != 'host' %} +{% for network in matrix_synapse_worker_systemd_shared.container_additional_networks %} +ExecStartPre={{ matrix_synapse_worker_systemd_shared.host_command_docker }} network connect {{ network }} {{ matrix_synapse_worker_container_name }} {% endfor %} {% endif %} -ExecStart={{ devture_systemd_docker_base_host_command_docker }} start --attach {{ matrix_synapse_worker_container_name }} +ExecStart={{ matrix_synapse_worker_systemd_shared.host_command_docker }} start --attach {{ matrix_synapse_worker_container_name }} -ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} stop -t {{ devture_systemd_docker_base_container_stop_grace_time_seconds }} {{ matrix_synapse_worker_container_name }} 2>/dev/null || true' -ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm {{ matrix_synapse_worker_container_name }} 2>/dev/null || true' +ExecStop=-{{ matrix_synapse_worker_systemd_shared.host_command_sh }} -c '{{ matrix_synapse_worker_systemd_shared.host_command_docker }} stop -t {{ matrix_synapse_worker_systemd_shared.container_stop_grace_time_seconds }} {{ matrix_synapse_worker_container_name }} 2>/dev/null || true' +ExecStop=-{{ matrix_synapse_worker_systemd_shared.host_command_sh }} -c '{{ matrix_synapse_worker_systemd_shared.host_command_docker }} rm {{ matrix_synapse_worker_container_name }} 2>/dev/null || true' -ExecReload={{ devture_systemd_docker_base_host_command_docker }} exec {{ matrix_synapse_worker_container_name }} /bin/sh -c 'kill -HUP 1' +ExecReload={{ matrix_synapse_worker_systemd_shared.host_command_docker }} exec {{ matrix_synapse_worker_container_name }} /bin/sh -c 'kill -HUP 1' Restart=always RestartSec=30 SyslogIdentifier={{ matrix_synapse_worker_container_name }}