Problem / Motivation
SitewideAlertRenderer::build()has three return paths. Two correctly applyCacheableMetadatato the returned render array. The third — taken when no active alerts exist — returns a bare empty array with no cache metadata:
// SitewideAlertRenderer::build() line 64–66 if (!$this->sitewideAlertManager->activeSitewideAlerts()) { return []; }
- Compare with the correctly handled permission-denied path immediately above it:
$build = []; $cacheMetadata->applyTo($build); return $build;
- This creates two distinct problems.
Problem 1: Uncached DB query on every page request when no alerts are active
- Because the returned
[]carries no cache tags or max-age, Drupal's render cache has nothing to store or reuse. - On every page render the block calls
activeSitewideAlerts(), which executes an entity storage query plusloadMultiple()against thesitewide_alerttable. - It receives an empty result and returns
[]again with no mechanism to avoid repeating this on the next request. - Sites with no active alerts — the typical steady state between campaigns — pay this DB query cost on every single page view.
Problem 2: Alerts created after initial page cache warm never appear
- When an alert is created or enabled, Drupal invalidates the
sitewide_alert_listcache tag. - Because the cached render array for the no-active-alerts path has no cache tags attached, there is nothing to invalidate.
- The page continues serving the empty result until the entire cache is manually cleared.
Steps to Reproduce
- Install
sitewide_alertandsitewide_alert_block. - Place the Sitewide Alert block on a page.
- Ensure no sitewide alert entities exist or all are unpublished.
- Load the page —
activeSitewideAlerts()fires an entity query on every request with no render cache short-circuit. - Create and publish a new sitewide alert.
- Load the page again without clearing caches — the alert does not appear.
Proposed Resolution
- Apply
$cacheMetadatato the empty-result return path and add thesitewide_alert_listentity list cache tag so the cache correctly invalidates when an alert is created or enabled:
if (!$this->sitewideAlertManager->activeSitewideAlerts()) { $build = []; $cacheMetadata ->addCacheTags(['sitewide_alert_list']) ->applyTo($build); return $build; }
- The
sitewide_alert_listtag is already used bySitewideAlertsController::setCacheTags(['sitewide_alert_list']), confirming it is the correct tag for this entity type's list invalidation. - The permission-denied path at lines 54–61 should also add
sitewide_alert_listto its$cacheMetadatafor the same reason — if a user gains theview published sitewide alert entitiespermission and an alert exists, their cached permission-denied render array would not invalidate correctly.
Issue fork sitewide_alert-3593274
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
mglamanLooks like 3.1.x has this fixed.
Comment #4
mglamanLooks like it's fixed on 3.0.x but only tagged in 3.1.x. and this is a dupe of #3506754: The "Sitewide Alert" block return an empty array if no alert exists
Patch of the commit for those needing it: https://git.drupalcode.org/project/sitewide_alert/-/commit/0e8f1161a845c...