Problem/Motivation

In #3258714: Manage attachments cache, the user cache context was added to markerio_page_attachments(). This means every page now varies by user.

By the time the HtmlRenderer is done calling all page_attachments hooks, we now have a HtmlResponse object that has the user cache context. This means DynamicPageCacheSubscriber will refuse to cache the page, even though the page itself might have been perfectly cacheable otherwise.

Steps to reproduce

Enable this module, see that every page reports "UNCACHEABLE (poor cacheability)" in the "X-Drupal-Dynamic-Cache" header.

Proposed resolution

It seems you're adding some drupal settings in markerio_page_attachments, but can't you use a #lazy_builder somewhere during the render process? Then it will get placeholdered and the page will become cacheable again by DynamicPageCacheSubscriber.

When it gets to HtmlResponseSubscriber, the HtmlResponseAttachmentsProcessor will process the placeholders, adding your attachments to the response. After that, your JavaScript should still get added, but only after DPC has finished doing its thing.

I'm not sure if this widget is intended to be used by anonymous users, but if not then the above should be more than enough to fix the issue.

Remaining tasks

Rethink the caching strategy

User interface changes

/

API changes

/

Data model changes

/

Issue fork markerio-3506671

Command icon 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

kristiaanvandeneynde created an issue. See original summary.

kristiaanvandeneynde’s picture

P.S.: I'm willing to explain more about caching if you need guidance.

moshe weitzman’s picture

I wrote a patch for datalayer module that might be a helpful model - https://www.drupal.org/project/datalayer/issues/3345817

kristiaanvandeneynde’s picture

That's exactly the type of fix I had in mind, thanks @moshe weitzman!

tijsdeboeck’s picture

Thanks @kristiaanvandeneynde @moshe weitzman, we're planning to work on this module in the coming weeks, and will update the caching strategy.

Regarding anonymous users, it is perfectly plausible that you want enable this for anonymous users. I can imagine that you would want to enable this during a test phase, where not all testers would have an account. So it is something we need to take into account.

vensires’s picture

Title: This module kills Dynamic Page Cache » Replace using user cache context by lazy loaders to avoid killing the Dynamic Page Cache
Status: Active » Needs work
Issue tags: +GreeceSprints2025
jacerider’s picture

We ran into this on a current LIVE site. We had permission set so only admins would see Markerio. After debugging why our pages were resulting in UNCACHEABLE, we nailed it down to this module. Just wanted to +1 on this being a pretty important issue to resolve.

macsim made their first commit to this issue’s fork.

macsim’s picture

Here is a proposed fix.

The root cause is that hook_page_attachments() unconditionally adds a user cache context, which makes every page report UNCACHEABLE to Dynamic Page Cache.

The fix moves all user-dependent logic into a lazy builder (LazyBuilder::build()), registered as a service. hook_page_attachments() now only adds the config:markerio.settings cache tag. A new hook_page_bottom() installs the lazy builder placeholder with #create_placeholder = TRUE, so Dynamic Page Cache can cache the page normally and the placeholder is resolved per-user at render time.

Changes:

  • markerio.module: replace hook_page_attachments() logic with hook_page_bottom() + lazy builder
  • markerio.services.yml: new file registering the markerio.lazy_builder service
  • src/LazyBuilder.php: new class implementing TrustedCallbackInterface, containing all user/route-dependent attachment logic
  • tests/src/Unit/LazyBuilderTest.php: 8 unit tests covering all branches of build()
macsim’s picture

Status: Needs work » Needs review
macsim’s picture

Note: TrustedCallbackInterface was introduced in Drupal 8.8.0, not 8.0.0, so this patch is technically not compatible with the full ^8 range declared in markerio.info.yml. In practice this should not be an issue since Drupal 8 and 9 are both EOL. Dropping those from core_version_requirement would be the clean solution, but that is a separate topic.

tijsdeboeck’s picture

Status: Needs review » Reviewed & tested by the community

Thanks for the MR, we've tested this, and will ship a new release soon!

  • tijsdeboeck committed deac7aa1 on 1.x authored by macsim
    fix: #3506671 Replace using user cache context by lazy loaders to avoid...