Problem/Motivation
When a Patternkit block is rendered on a page, it attaches cache tags for the associated block entity and the pattern entity being referenced. This is intentional and correct since it describes the content being rendered and allows for it to be targeted when changes affecting it should invalidate associated cache entries. The issue comes in instead with these related entities being saved at the wrong time causing a premature invalidation of all associated cache entries.
The current implementation of the Patternkit blocks saves these associated entities whenever the block form is submitted. This save triggers Drupal's default entity behaviors to invalidate the cache tags for those entities immediately. When used in Layout Builder, and likely other scenarios, this can result in the cache tags for a pattern and/or block being invalidated during the layout editing process before the changes to the layout are ever published. Since the pattern entity is also updated, any other pages that may render different blocks based on the same pattern entity would have their cache entries invalidated as well despite the specific revision they reference not being affected.
As an example, suppose two Nodes exist. Each is using Layout Builder and has an overridden layout set for it containing the Patternkit Example pattern. At this point the rendered cache entries for each node contain cache tags for the separate Patternkit Block entities and the same Pattern entity.
Assume now an editor edits the layout for Node 1, edits the content for the Patternkit Example block, and submits the form. They have not saved the layout yet, so no changes to the rendered content on the published Node would be visible yet. However, once the block form was submitted, a new revision of the Patternkit Block entity was created and saved which triggered invalidation of the rendered output of Node 1. The Patternkit Example Pattern entity was also saved despite there being no changes to reflect which results in the cache entries for both the rendered content of Node 1 and Node 2 being invalidated since both contain a block using that pattern.
Ideally, in this scenario, no rendered output caches should have been invalidated until the complete layout was saved. At this point, only the rendered content for Node 1 should have been invalidated since there were no changes to the Pattern entity that should cause the content for Node 2 to change.
Steps to reproduce
Initial Setup
These steps are intended to test the initial setup for the test scenarios and confirm cache tags are represented as expected after initial content creation.
- Install the following modules: Patternkit, Patternkit Example, Layout Builder
- Enable cache header output
- Enable Layout Builder with page-specific overrides on a content type
- Create and save a new page (Page 1)
- Edit the layout for this page and place a new "[Patternkit] Example" block
- Save the layout
- In an incognito window, navigate to Page 1 and view the cache headers:
- Expect to see a cache miss and the following cache tags included:
- "pattern:@patternkit/atoms/example/src/example"
- "patternkit_block:1" (The number may vary if this is not a fresh installation.)
- "patternkit_pattern:1" (The number may vary if this is not a fresh installation.)
- Expect to see a cache miss and the following cache tags included:
- In the original window, create and save a new page (Page 2)
- Edit the layout for this page and place a new "[Patternkit] Example" block, saving the layout
- In an incognito window, navigate to Page 2 and inspect the cache headers:
- Expect to see a cache miss and the following cache tags included:
- "pattern:@patternkit/atoms/example/src/example"
- "patternkit_block:2" (The number may vary if this is not a fresh installation.)
- "patternkit_pattern:1" (The number may vary if this is not a fresh installation.)
- Expect to see a cache miss and the following cache tags included:
Block Editiing
These steps are intended to verify the cache invalidation behavior during typical block editing processes.
- Edit the layout for Page 1
- Edit the example block already on the page
- Change some field content and submit the block form (Do not save the layout yet)
- At this point, the changed content should be visible on the layout preview screen.
- In an incognito window, view the published version of Page 1:
- Expect to see the unedited block content and a cache hit for the page
- In the original tab, save the updated block layout.
- Expect to see the changed content on the published view of Page 1
- Expect to see a cache miss for the page
- In an incognito window, view the published view of Page 2:
- Expect to see a cache hit for the page
Pattern Updating
These steps should cover validation of caching behaviors when the underlying Patterns for these blocks are updated. Unfortunately, triggering the update process for a Pattern within a block isn't possible through the UI, so testing this only through the browser isn't currently possible. The hash for the pattern may be edited directly in the database which would enable the update process through the UI if this is an option in the testing environment. The following steps assume this or a similar change has been implemented to trigger the detection of an available pattern update for the "[Patternkit] Example" pattern.
- As an editor, edit the layout for Page 1
- Edit the example block placed on the page previously
- Expect to see a prompt to update the block to the latest version
- In a separate tab, edit the layout and block for Page 2
- Expect to see a prompt to update the block to the latest version
- In the original tab for Page 1, click the "Update pattern" button
- Submit the block form
- In a separate tab, view Page 1
- Expect to see a cache hit
- In the same tab, view Page 2
- Expect to see a cache hit
- In the original tab, save the layout for Page 1
- Expect to see a cache miss for Page 1
- View the published view of Page 2
- Expect to see a cache hit
- Edit the layout and example block for Page 2
- Expect to see a prompt to update the pattern
Proposed resolution
Mimic the update and save solution used by Inline Blocks provided by the Layout Builder module to serialize content updates in blocks and defer entity updates (and related cache invalidations) until the layout and entity are saved.
Remaining tasks
User interface changes
None.
API changes
- Patternkit Block config schema now includes a
block_serializedstring value to capture unsaved content changes to blocks - Pattern name cache tags (like
pattern:@patternkit/atoms/example/src/example) are only invalidated now when an existing pattern is updated and marked as the default revision - Updates to patternkit blocks in Layout Builder are saved in the new
serialized_blockvalue until a layout is saved instead of being saved immediately when a block form is submitted - New entity insert and update hooks use the new
PatternkitBlockEntityOperationsservice to save patternkit block and pattern entity updates when an entity using a layout containing them is saved - When a Pattern entity is updated through the block edit form, a new revision of it is saved and referenced from the updated block configuration. However, this new revision is not marked as the default revision until the layout is saved at which time the
PatternkitBlockEntityOperationsservice resaves the Pattern entity as the default revision triggering invalidation of the related Pattern entity cache tags.
Data model changes
- Patternkit Block config schema now includes a
block_serializedstring value to capture unsaved content changes to blocks
| Comment | File | Size | Author |
|---|---|---|---|
| #9 | DAT 3533_Retest.odt | 1.55 MB | minsharm |
Issue fork patternkit-3339014
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 #3
sluceroComment #4
sluceroIt got rather complex trying to separate out the different types of cache tags and what their desired behavior should be, but this is what I settled on (obviously open to feedback).
Types of cache tags
patternkit_block:123patternkit_pattern:456pattern:@patternkit/example/src/exampleIntended behavior
With the different types of cache tags and their intentions clarified, we can tackle the invalidation behavior a bit more clearly.
patternkit_block:123) should be invalidated, but only once the layout itself is actually saved. Unless a block is marked as reusable and placed on multiple pages, this shouldn't cause invalidations anywhere else.patternkit_pattern:456) and the pattern name (pattern:@patternkit/example/src/example), neither of which should have records to invalidate if this is the first usage.TL;DR
Comment #5
kunalkursija commentedI have tested the patch and the
patternkit_block:BLOCK-IDcache tags are now getting invalidated only when a new node revision is created. This is how Drupal core is operating as well with custom-blocks. Things are looking good.+1 on getting this merged in.
Comment #6
sluceroComment #7
sluceroComment #8
sluceroComment #9
minsharm commentedRetested the changes and it is working as expected now.
Steps:
1) Install the modules: Patternkit, Patternkit Example, Layout Builder
2) Enable cache header output by enabling http.response.debug_cacheability_headers as true in core.services.yml file
3) Enable Layout Builder with page-specific overrides on a content type
4) Create and save a new page (Page 1)
5) Edit the layout for this page and place a new "[Patternkit] Example" block
6) Save the layout and view the page
7) View the cache headers for page 1
Results : Expect to see a cache miss
8) In the original window, create and save a new page (Page 2)
9) Edit the layout for this page and place a new "[Patternkit] Example" block, saving the layout
10) View the cache headers for Page 2:
Results : Expect to see a cache miss
Block Editing
11) Edit the layout for Page 1
12) Edit the example block already on the page
13) Change some field content and submit the block form (Do not save the layout yet)
Results : At this point, the changed content should be visible on the layout preview screen.
view the published version of Page 1:
Results: Expect to see the unedited block content and a cache hit for the page
14) In the original tab, save the updated block layout.
Results :
Expect to see the changed content on the published view of Page 1
Expect to see a cache miss for the page.
15) View the published view of Page 2:
Results: Expect to see a cache hit for the page
Attaching Screenshots.
Comment #10
minsharm commentedComment #11
sluceroComment #13
sluceroMerging for inclusion in the Beta 7 release.