Menu warm cache
Drupal access-checks every menu link on the request that renders the menu, and
tags the cached result with every node the menu links to. On a large site those
two facts fight each other: any node save drops the cached menu, and the next
anonymous visitor pays for a full access check of the whole tree.
Menu Warm Cache breaks that coupling. It stores the anonymous access decision
for every link of the menus you choose in a dedicated table, renders those menus
from the table, and invalidates the menu render cache only once the table has
been rebuilt. The rebuild runs off the request path, in a Symfony Messenger
worker, so visitors keep being served the previous menu, fully cached, until the
new one is ready.
What it does
- Watches a configurable list of menus. Menus you do not list keep Drupal's
standard behaviour, so you can adopt the module one menu at a time. - Marks a menu dirty when a menu link or a linked node changes, and queues the
rebuild through Symfony Messenger. A burst of edits to the same menu rebuilds it
once, not once per edit. - Only queues a rebuild when something that actually changes the menu changed:
the link's menu, title, parent, weight, enabled or expanded state, or target, or
a node's published status. Other edits are ignored. Sites with custom fields can
subscribe to an event to force or veto a rebuild. - Ships a Materialized Menu block that replaces the core menu block. It drops
the node cache tags and theconfig:system.menu.NAMEtag and carries a single tag
that the rebuild invalidates. - Decorates
menu.default_tree_manipulatorsso the access check reads the
materialized table first, and falls back to the runtime check (caching the
result) for anything it has not seen. - Provides a Drush command to rebuild dirty menus on demand.
Requirements
- Drupal 11.2 or newer, PHP 8.3 or newer.
- Symfony Messenger integration
(sm), with a transport configured and a worker running. - A worker reset subscriber on
WorkerMessageReceivedEvent. The Messenger
worker never tears down between messages, and Drupal's per-request cache tag
guard silently drops every invalidation after the first one. Without the reset,
the table is rebuilt, but the menu never refreshes. The README gives a ready-to-paste implementation. The module does not ship it, because it is generic worker
hygiene that every message handler on the site needs, not only menu
rebuilds.
Trade-offs
Menu updates are eventually consistent by design. The menu changes for
anonymous visitors when the worker has finished the rebuild, not when the editor
presses save. If that is not acceptable, this module is not the right tool.
The materialized access is computed for the anonymous user. Authenticated
role combinations fall back to the runtime check and are then cached in the same
table.
Menus are configured through configuration only for now; there is no
administration form yet. Patches welcome.
Depends on
Dependencies of the latest stable release
- Symfony Messenger + Drupal: Realtime Queues and Cron
- menu_link_content Drupal core
- menu_ui Drupal core
- node Drupal core
- system Drupal core
Required by
Tracked projects that depend on this one
No tracked projects depend on this one yet.