Problem/Motivation

Drupal\Core\Extension\ExtensionList::getPathnames() attempts to store and retrieve path names in both cache and state values; however, it does so inconsitently. If the cache value is cleared, then the state value will be returned. Clearing cache will have no affect.

Here's a human-reabable version of the logic:

  • Does a cache value exist?
    • If yes, then return the cache value.
  • Else, does a state value exist?
    • If yes, then return the state value.
    • If no, then recalculate path names
      • Save recalculated path names to cache and state.
      • Return recalculated path names

Here's the code in question:

  /**
   * Returns a list of extension file paths keyed by machine name.
   *
   * @return string[]
   */
  public function getPathnames() {
    if ($this->pathNames === NULL) {
      $cache_id = $this->getPathnamesCacheId();
      if ($cache = $this->cache->get($cache_id)) {
        $path_names = $cache->data;
      }
      // We use $file_names below.
      elseif (!$path_names = $this->state->get($cache_id)) {
        $path_names = $this->recalculatePathnames();
        // Store filenames to allow static::getPathname() to retrieve them
        // without having to rebuild or scan the filesystem.
        $this->state->set($cache_id, $path_names);
        $this->cache->set($cache_id, $path_names);
      }
     $this->pathNames = $path_names;
    }
    return $this->pathNames;
  }

Cache vs state is discussed in #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList where this code originated. See below:

#2208429-62: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList by Mile23:

But it should be in the cache, instead. I don't think we have a way to clear state from the UI, and having a filesystem problem and a non-clearable cache is bad news for users.

#2208429-63: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList by almaudoh:

Totally agree it should be in cache, not state, but I guess the main consideration was maintaining BC, since we don't know how many contrib modules out there are using \Drupal::state() directly to get module info.

#2208429-70: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList by almaudoh:

As a matter of fact, we cannot use State to store extension lists and info because State depends on the system module, and the system module needs module lists for installation -> a circular dependency. So we have no choice but to use cache.

#2208429-88: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList by catch:

That's OK to change in a minor version. Module info happening to be in state isn't part of the public API, per https://www.drupal.org/core/d8-bc-policy

#2208429-329: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList by catch:

Also what is the situation where the cache will be cleared but the state entry won't be (except for say a memcache eviction)?

#2208429-330: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList by dawehner:

Well yes this was the idea. Avoid disc IO as much as possible.

#2208429-332: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList by catch:

I'm not sure about this, it means that it will persist past a bin flush. For example what happens if you move a module from modules/custom to modules/contrib?

#2208429-334: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList by dawehner:

Well, in this case \Drupal\Core\Extension\ExtensionList::reset is called, which removes the state entry. Given that it is totally able to move modules.
Also keep in mind, we do have set('system.module.files', $files); already in core as it is. We are "just" moving it around basically. Does that makes sense?

Unfortunately, \Drupal\Core\Extension\ExtensionList::reset() is not called in all circumstances.

Proposed resolution

Switch to storing exclusively in cache. (I'm not seeing the benefit of the current behavior. How does it reduce IO?)

Remaining tasks

  • Community feedback
  • Open an MR and update tests

User interface changes

None.

API changes

None.

Data model changes

None.

Release notes snippet

TBD.

CommentFileSizeAuthor
#7 3240928-nr-bot.txt150 bytesneeds-review-queue-bot

Issue fork drupal-3240928

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

Chris Burge created an issue. See original summary.

chris burge’s picture

Status: Active » Needs review

Opened a MR. Let's see what happens with tests.

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

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now 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.

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

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now 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.

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

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now 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.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new150 bytes

The Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

Version: 10.1.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, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

mile23’s picture

Given that state is optionally cached in 10.3+ (and always on in 11.x), if you have a giant collection of modules you're filling up the state table with a list of info files on the file system. This means the state table can then become too large to fit into your caching backend such as memcache.

Relevant CR: https://www.drupal.org/node/3177901

And given that the file system can change, and also that we have no way of emptying the state records for these files, we should only cache the paths and not put them in the state system.

The PR here seems to do the right thing, AFAICT, but needs updating for D11 (and eventual back port to 10.3.x).

I'd tag with 'needs reroll' but I'm not sure whether that's the right tag in the time of gitlab.

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

capysara changed the visibility of the branch 11.1.x to hidden.

capysara changed the visibility of the branch 10.3.x to hidden.

capysara changed the visibility of the branch 3240928-getpathnames-conflates-cache to hidden.

capysara changed the visibility of the branch 3240928-getpathnames-conflates-cache-11.1.x to hidden.

nicxvan’s picture

This needs some updates for what is mentioned in 9.

What is mentioned in the issue summary no longer describes the code flow.

I'm wondering if we close this and open a new issue targeting what you mentioned @mile23

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.

nicxvan’s picture

Why is that issue related to this?