Problem/Motivation

In Drupal 8 and 9, some weird behaviour happens in Views Time-based cache.

The problem only occurs when using Time-based "Custom" time.

Problem 1:
Configuration results_lifespan and output_lifespan are never saved as 'custom'.
It is saved as 0, even if we choose 'Custom'.

Problem 2: (php8 only)
in getLifespan, we have this one liner
$lifespan = $this->options[$type . '_lifespan'] == 'custom' ? $this->options[$type . '_lifespan_custom'] : $this->options[$type . '_lifespan'];

Since $this->options[$type . '_lifespan'] is never 'custom' but 0 instead (problem 1),
it is like:
0 == 'custom'

Now in php7, this returns TRUE.
But in php8, this returns FALSE, so when views_ui loads the views, custom time-based cache will always show '0sec, 0sec'.

Why this happens

When building options (buildOptionsForm), there is some formatted [60, 300, 1800, 3600, 21600, 518400] options as $options
and then
$options = [0 => $this->t('Never cache')] + $options + ['custom' => $this->t('Custom')];

But views.cache.schema.yml type for both results_lifespan and output_lifespan is integer

Steps to reproduce

Edit a view
Set Caching as Time-based with Custom value
Save the view
Check Caching value again

Proposed resolution

Remove the _custom storage fields - the view config always should store the raw value in a single field.

The UI still offers a dropdown with a "custom" option, but stores the value in the single field, and recreates the custom option on reload if required.

Remaining tasks

Reviews and input from community.

Issue fork drupal-3233105

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

simgui8 created an issue. See original summary.

simgui8’s picture

StatusFileSize
new2.48 KB

Here is a patch for the proposed solution.

longwave’s picture

-1 seems a better choice than 7 to mean "custom".

However, isn't this really only a UI issue? Why do we need both results_lifespan and results_lifespan_custom? We could store only one value, and then display the custom setting if the value isn't in the list of dropdown options, we don't need to store both.

longwave’s picture

simgui8’s picture

Thanks longwave,

For the related issue 3024941, I missed it even if I did search a lot for similar issues.

3024941 assume that results_lifespan_custom gets emptied when passing from Custom time-based caching to another time-based options.
This is not the case, it is only updated every time 'custom' is chosen.

We need both results_lifespan and results_lifespan_custom by design.
results_lifespan stores Never-cache + some predefined options and custom
results_lifespan_custom only stores custom int values

It is a UI issue only with php7.
It is broken and non-functional with php8, because getLifespan gets called very often.

To replicate with php8:
Set N seconds custom value on a view with random sort.
Navigate to the view with a non anonymous user
and reload the page every N seconds
Nothing happens (problem #2)

Switch back to php7:
The views get updated every N seconds.

longwave’s picture

Why can't results_lifespan always store 0 for never cache, or the exact number of seconds? Then the UI can show the dropdown and hide or show the custom field depending on if the stored value is in the dropdown or not? This would simplify the logic of using the value at least.

There is nothing at present stopping you from saving a value that's not in the dropdown for results_lifespan, and it will work (except in the UI). There is also no difference between results_lifespan = 600 and results_lifespan = custom, results_lifespan_custom = 600.

simgui8’s picture

Ok sounds great.

I will test this and upload a new patch.

simgui8’s picture

StatusFileSize
new2.49 KB
new2.31 KB

After reviewing what's there now, the most straightforward and less intrusive fix would be to use a specific integer for custom option, let say -1.
That way we can easily keep "legacy" UI options at one place in buildOptionsForm.

There is also the option to remove legacy options, and only use Never cache or Custom. Then I guess results_lifespan_custom and output_lifespan_custom would become obsolete.

Another path could be to create a method to return legacy options, and rely on that in:
buildOptionsForm (show/hide)
validateOptionsForm
getLifespan

Anyhow, here is the 1st option patch.

simgui8’s picture

Status: Active » Needs review

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.1.10 (June 4, 2021) and Drupal 9.2.10 (November 24, 2021) were the last bugfix releases of those minor version series. Drupal 9 bug reports should be targeted for the 9.3.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

joachim’s picture

Status: Needs review » Needs work

LGTM, just one small suggestion:

+++ b/core/modules/views/src/Plugin/views/cache/Time.php
@@ -96,7 +96,8 @@ class Time extends CachePluginBase {
+    $options = [0 => $this->t('Never cache')] + $options + [-1 => $this->t('Custom')];

Could we make this -1 value a class constant for better DX? e.g. static::LIFESPAN_CUSTOM

simgui8’s picture

StatusFileSize
new2.84 KB
new2.57 KB

Here is an updated patch.

@joachim, let me know if it looks good to you so I can integrate your better DX suggestion into my dev routine :)

simgui8’s picture

Status: Needs work » Needs review

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

lendude’s picture

This issue came up as a triage issue in #bugsmash

Nice work on this. #12 does look like the less invasive approach, but I think I like the proposed #6 more, getting rid of any setting sounds good to me, we have too many in Views anyway. It also feels like it would indeed simplify the logic a little.

Anyway, this needs test coverage and if we go for #6 it would need an upgrade path to get rid of the old settings.

simgui8’s picture

I agree with dropping settings.

So this would mean removing results_lifespan_custom and output_lifespan_custom
and adjusting core/modules/views/src/Plugin/views/display/DisplayPluginBase.php accordingly ?

+ test coverage

smustgrave’s picture

Closed https://www.drupal.org/project/drupal/issues/3024941 as duplicate of this
Moving over credit for

asya_asina = initial patch
Aanal.addweb = first testing
Amber Himes Matz = triaging and discovering the duplicate

smustgrave’s picture

Status: Needs review » Needs work

Moving to NW for the tests

Verified the issue exists in 9.5
Verified the patch in #12 still applies and fixes the issue.

Not sure if some kind of notice will be needed since site admins will have to go in and fix their views if currently using that setting.

simgui8’s picture

StatusFileSize
new6.74 KB

Here is another shot a it,
completely different approach (more like #6).

longwave’s picture

PHPCS failed:

FILE: /var/www/html/core/modules/views/src/Plugin/views/cache/Time.php
----------------------------------------------------------------------
FOUND 0 ERRORS AND 1 WARNING AFFECTING 1 LINE
----------------------------------------------------------------------
 155 | WARNING | [x] A comma should follow the last multiline array
     |         |     item. Found: $output_default
smustgrave’s picture

Also will still need tests.

simgui8’s picture

StatusFileSize
new6.74 KB

This one should pass phpcs

smustgrave’s picture

Issue tags: +Needs subsystem maintainer review

So the current question is the approach in #25 better than #12.

Adding Needs subsystem maintainer review to get their review on this as I don't have much an opinion on either approach.

smustgrave’s picture

So after testing it seems #12 is the more complete solution.

#25 when I exported my view it didn't show that I had a custom setting. It exported the seconds but if those seconds were say 3600 the view would load that as non custom.

smustgrave’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
StatusFileSize
new2.53 KB
new2.9 KB
new5.84 KB

Adding a test

simgui8’s picture

Thanks for the test! I will have a run at it and report back.

As for #27
If we remove results_lifespan_custom and output_lifespan_custom configurations, we have to show/hide the custom seconds form element based on results_lifespan and output_lifespan

So if we put any of the defaults options as "custom", we can't trigger show/hide
$options = [60, 300, 1800, 3600, 21600, 518400];

If we want to fix this issue, #12/#28 should do the work.

If we want to remove some settings for time based cache,
#25 is a try, but it might be better to open another issue with a detailed shopping list.

Status: Needs review » Needs work

The last submitted patch, 28: 3233105-28.patch, failed testing. View results

smustgrave’s picture

StatusFileSize
new5.84 KB

Here's the patch I meant to upload. Just uppercase C

simgui8’s picture

The updated patch with uppercase C pass tests on my side (#31).

Thanks

simgui8’s picture

Status: Needs work » Needs review
longwave’s picture

Status: Needs review » Reviewed & tested by the community

I have run into this again on a project, #31 works for me and is the simplest way to fix this; we can improve this later in followup issues.

Note that usually this sort of change would require an upgrade path but currently this feature is broken and views are not saved correctly when the custom option is used, so I don't think an upgrade is viable or useful here.

The last submitted patch, 28: 3233105-28-tests-only.patch, failed testing. View results

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

I think given this is quite broken we should consider how this works. I think saving both results_lifespan_custom and results_lifespan (and the duplicate for output_lifespan*) is really odd. We should be saving on lifespan.

The logic could be something like this. If the lifespan is not in the preset list then set it to the custom lifespan option and set the default value of the test field. On save if the lifespan is set to custom then replace it with the integer from the custom lifespan field. That way the final view has less fields and makes more sense.

alexpott’s picture

Sorry looked at the patch directly... didn't read #35. Sorry @longwave. As per #36 I think that considering this is totally broken we should take the opportunity to fix it in the best way possible rather than do it in steps because it's not as if it is partially working.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

fgm’s picture

Similar bug with more details and different explanations at #3371265: Views time-based caching stores and custom duration as zero, marking as duplicate since this one already has a patch in the works.

crutch’s picture

Patch isn't applying to 10.1.8. Needing 24 hours.

$options = [60, 300, 1800, 3600, 21600, 86400, 518400];

simgui8’s picture

Assigned: simgui8 » Unassigned

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

mrinalini9’s picture

Status: Needs work » Needs review
StatusFileSize
new5.84 KB

Hi,
Rerolled patch #31 for 11.x branch, please review it.
Thanks!

smustgrave’s picture

Status: Needs review » Needs work

mrinalini9’s picture

Status: Needs work » Needs review

Created MR for the changes in patch #44, please review.

smustgrave’s picture

Status: Needs review » Needs work

Pipeline has issues.

Would recommend checking that everything is green before putting into review.

mrinalini9’s picture

Status: Needs work » Needs review

Fixed pipeline issues and updated MR, please review it.
Thanks!

longwave’s picture

Status: Needs review » Needs work

This still uses two separate config keys, which isn't necessary - to make the config simpler we should implement @alexpott's suggestion from #36.

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

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

longwave’s picture

Status: Needs work » Needs review

Implemented #36 with help from Claude Code. The _custom fields are gone, there are now just results_lifespan and output_lifespan keys that store the raw value, the UI handles the selection of preset vs custom values.

The update hook removes _custom fields and preserves existing behaviour: only if the raw value is the string "custom" then the custom value is actually used.

smustgrave’s picture

Status: Needs review » Needs work

Sorry can we clean up the summary some? Solution says option7?

longwave’s picture

Issue summary: View changes
Status: Needs work » Needs review

Updated IS.

marcoscano’s picture

Status: Needs review » Needs work

I have reviewed the MR and tested manually. Didn't find anything major IMO, so I think we should be close to ready here.
Setting as NW just to update the CR URL in the MR, then to me this is ready for RTBC