Writing the per-domain HTTP->HTTPS redirect notified restart-openresty, which
runs container service update --force and waits for a swarm rolling update. It
fired once per domain. Measured across both passes of a green Nextcloud round:
the forced redeploy ran 47 times at a mean of 40s, and 34 of those
notifications came from this task; the remaining 11 came from the genuine
fallback in sys-stk-front-proxy. The role accounted for 1178s of a 9694s sync
pass and 1043s of the async pass, so roughly 2.2ks of an 18.8ks job against a
20.4ks budget.
The redeploy is not needed here. plugins/lookup/nginx.py resolves
files.domain to conf.d/servers/<protocol>/<domain>.conf, which sits inside the
conf.d DIRECTORY bind, and handlers/reload.yml states the rule for exactly this
case: a directory keeps its inode across an atomic file write, so the running
container already sees the new file and SIGHUP is enough. Only nginx.conf is
bound as a file whose inode the task pins at create time, and nothing here
writes it.
The choice was never made deliberately: a46348b6cf only renamed
"restart openresty" to "restart-openresty" in this file, carrying the topic
forward unchanged.
Correctness does not rest on the reload being sufficient. sys-stk-front-proxy
probes each domain after the reload and notifies restart-openresty when it is
not served, a guard that demonstrably fires today. If SIGHUP falls short the
redeploy still happens; the worst case is no saving rather than a broken vhost.
Expected saving is 1.5 to 1.75ks per job, about 8% of the distro budget. That
makes the comfortable jobs comfortable and leaves the heaviest Nextcloud
variants marginal; it does not on its own end the budget kills.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A handler name was doing two jobs at once: the line an operator reads in the
play output, and the identifier a `notify:` binds to. The two pull in opposite
directions -- the log wants "restart the SSH service, with diagnostics", the
binding wants a token that survives quoting, YAML flow style and a shell
round-trip -- and a name that changes for readability silently changes which
handler runs.
Every handler that a notify reached by name now carries a `listen:` with that
exact wording, so the binding is explicit before anything is renamed. The
topics themselves become identifiers: `compose up` reads `compose-up`,
`Restart NFS ganesha` reads `restart-nfs-ganesha`, 22 of them across both
sides of every notify. Where the topic is assembled at runtime, both branches
moved together: the conditional in sys-service carries two literals, and the
LDAP renderer interpolates `import-{{ folder }}-ldif-files`, which is what
makes those handlers reachable at all.
Freed from the binding, the names take the emoji prefix every other task line
already has.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Add tests/lint/repository/test_task_file_numbering.py: numbered task
files use exactly two leading digits, a numbered *_core.yml must be
00_core.yml, per directory the numbers are unique/consecutive and start
at 01 (00 with a core file), numbered includes appear in ascending
order, and shared helpers live in tasks/utils/ instead of the numbered
chain.
Apply it across every role: rename NN_core.yml to 00_core.yml with a
consecutive down-shift of the siblings, move letter-suffix children into
a subdirectory named after their parent task, relocate helpers included
from more than one place into tasks/utils/, and update every reference
(include_tasks, path_absolute, .ansible-lint-ignore, requirement docs).
Legacy narration comments in the touched files are deleted; the upstream
xwiki.properties reference block opts out via nocheck. The unused
MAILU_IP6_PUBLIC var (only ever named in now-removed comments) is dropped.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>