Skip to content

Add ResultCacheMetaExtension so the result cache tracks the Drupal site - #1030

Draft
mglaman wants to merge 1 commit into
audit/4-bc-changesfrom
audit/5-result-cache
Draft

Add ResultCacheMetaExtension so the result cache tracks the Drupal site#1030
mglaman wants to merge 1 commit into
audit/4-bc-changesfrom
audit/5-result-cache

Conversation

@mglaman

@mglaman mglaman commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Part 9 of 9 in the legacy-code audit stack (on top of #1029). The highest-impact finding from the audit: PHPStan's result cache never invalidated when the analyzed Drupal site changed.

Why

PHPStan hashes its bootstrap files, but knows nothing about the Drupal extensions, services.yml files, and config schemas our bootstrap discovers. Enabling a module, editing a services.yml, or upgrading core silently reused stale analysis results until the user ran --no-result-cache or the cache expired.

What changed

BootstrapResultCacheMetaExtension implements PHPStan's ResultCacheMetaExtension (phpstan.resultCacheMetaExtension tag). Its hash covers:

  • the discovered extension inventory — info-file path and content per module/theme/profile,
  • every consumed services.yml (path and content),
  • all *.schema.yml files in the collected schema directories,
  • \Drupal::VERSION, which catches tarball core upgrades (composer-managed upgrades are already covered by PHPStan's own composer.lock hashing).

Any change invalidates the whole result cache. The hashing runs once per analysis over a few hundred small YAML files — well under 50ms. Discovered PHP files are deliberately not hashed; PHPStan hashes analyzed files itself.

To feed the extension, ServiceMap::setDrupalServices() gains an optional second parameter recording the consumed yml paths (backwards compatible), and ConfigSchemaData exposes its schema directories.

Testing

New unit tests assert the hash is deterministic, and changes when the extension list, a services.yml's content, or a schema directory changes. The tests run in separate processes because the underlying state is static. Full suite, self-analysis, and phpcs are green.

🤖 Generated with Claude Code

@mglaman
mglaman force-pushed the audit/5-result-cache branch from 3678ba5 to 6ee0ef6 Compare August 5, 2026 16:20
@mglaman
mglaman force-pushed the audit/5-result-cache branch from 6ee0ef6 to e89c527 Compare August 5, 2026 16:44
@mglaman
mglaman force-pushed the audit/5-result-cache branch from e89c527 to 206c73d Compare August 5, 2026 17:15
@mglaman
mglaman force-pushed the audit/5-result-cache branch from 206c73d to 94480e0 Compare August 5, 2026 19:13
PHPStan hashes its bootstrap files but knows nothing about the Drupal
extensions, services.yml files, and config schemas the bootstrap
discovers. Enabling a module, editing a services.yml, or upgrading core
silently reused stale results from the cache.

BootstrapResultCacheMetaExtension hashes the discovered extension
inventory (info-file paths and content), every consumed services.yml,
all config schema files, and the core version. Any change invalidates
the whole result cache. The hashing runs once per analysis and covers
a few hundred small YAML files, well under 50ms.

ServiceMap now records which services.yml paths it consumed (new
optional parameter, backwards compatible) and ConfigSchemaData exposes
its schema directories.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mglaman
mglaman force-pushed the audit/5-result-cache branch from 94480e0 to f526bdb Compare August 5, 2026 19:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant