Every page re-reads the package metadata for the footer's version, and the dashboard does it once per widget #560
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#560
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo at
95348908d, by counting and timing theuicontext processor on the dashboard and the applications page.Checked again on 2026-10-01 against
mainat0a5cad587: still present. The code is now atcore/updates.py:106-126(installed_version, moved there by #248 and still uncached;core/context_processors.py:9imports it and hands it on tohealthz),core/context_processors.py:91(the call inui) andcore/templatetags/postulo.py:492-506(render_widget);templates/core/dashboard.html:150andcore/views.py:56-58have not moved.The
uicontext processor callsinstalled_version()on every render with a request, and that reads the installed distribution's metadata from disk each time, although the version cannot change without a restart. The dashboard renders each widget withrender_to_string(..., request=...), which builds a freshRequestContextand runs every context processor again, so the page pays forui()once per widget.core/context_processors.py:87("postulo_version": installed_version()inui)core/context_processors.py:125-139(installed_version:importlib.metadata.version("postulo"), uncached)core/templatetags/postulo.py:511-525(render_widget:render_to_string(rendered.spec.template, …, request=context.get("request")))templates/core/dashboard.html:150({% render_widget item %}per widget)core/views.py:56-58(healthzreads the metadata on every health check as well)ui()runs 8 times andinstalled_version()8 times; on the applications page, once. Measured on Windows,ui()costs 3–4 ms per call, about half of it ininstalled_version(), so the widgets alone add roughly 25 ms to a dashboard that renders in about 45 ms. Every htmx fragment rendered with a request (each pause while typing in a table filter) pays one metadata read.render_widgetdocstring also says "a widget can only see what it asked for", which is not true: each widget receives the wholeuidict, the messages and the rest of the processors' output.installed_versionwith@functools.cache.widget,requestandcsrf_tokentaken from the page's context (widgets/due_reminders.html:20andwidgets/gone_quiet.html:37,44,51post forms and need the token). That also makes the docstring true.Related to #231, whose item 4 memoised the site settings per request but left
uiitself running once per widget.Done when
tests/test_footer.pyrenders two pages in a row and assertsimportlib.metadata.versionwas called at most once.tests/test_dashboard_grid.pyrenders the dashboard with the default widgets and asserts theuicontext processor ran once.Landed on main with a green Forgejo CI run. Its entry in the CHANGELOG's Unreleased section ends in (#560).