Move caching into SourceTransformingLoader, remove CachingTransformer - #595
Merged
Conversation
…gTransformer The cache decision now lives directly in the stream filter, next to the StreamMetaData construction: a usable cache record makes filter() emit the cached file content as-is - without parsing the source, constructing any transformer or building StreamMetaData. Only a real miss parses the source, runs the transformer chain (assembled lazily from the tagged container services) and persists the result. This removes the CachingTransformer wrapper entirely and with it the old cached-branch double work of re-parsing the cached file just to rebuild the token stream - so the warm-cache fast path now applies in debug mode too, while all freshness checks (filemtime, recorded cacheUri, tracked resources) are preserved verbatim. BC break (4.0): CachingTransformer is gone, transformCode() returns the overall TransformerResultEnum, addTransformer() is removed - transformers are registered as container services via registerTransformerServices(). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V1Z87HZ2iz23WPTtTYqFxE
Member
Author
|
i do not see any tests here - please cover with tests |
Unit tests for every branch of the filter's cache decision: fresh transformed/untransformed records served without constructing any transformer, stale records falling back to the chain, miss persisting the woven file and the untransformed record, abort short-circuiting the chain, PREBUILT_CACHE trusting a stale record without consulting the freshness collaborators, and the pass-through guard when the cache path equals the original file. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V1Z87HZ2iz23WPTtTYqFxE
Member
Author
|
Added in fd84b7e:
Full suite green on PHP 8.5/8.4 (2494 tests), PHPStan clean. Generated by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to the boot-time series (#589, #591, #592, #593, #594), as requested:
CachingTransformeris removed and the caching logic lives right inSourceTransformingLoader::filter(), next to theStreamMetaDataconstruction. If a usable cache record exists for the streamed file, its content is returned from there as the result — otherwise the code falls back totransformCode().What changed
SourceTransformingLoader::filter()decides in this order:RESULT_ABORTEDbranch of the wrapper).findCachedContent()) — the cached file content (or, for a known-untransformed file, the buffered original source) is emitted as-is: noStreamMetaData, no parsing, no transformer is ever constructed. All freshness rules are ported verbatim:filemtimecomparison, recorded-cacheUrimatch,hasAnyResourceChangedSince(), and thePREBUILT_CACHEtrusted-record short-circuit.StreamMetaData, run the transformer chain, persist viasaveToCache()(ported verbatim:__AopProxiedsuffix rename,mkdir/LOCK_EX/chmod,setCacheState()with the class-map recording from perf(cache): split runtime include map from transformation metadata #594 intact).transformCode()now returns the overallTransformerResultEnum(the logic formerly inCachingTransformer::processTransformers()); the chain is assembled lazily on the first miss from the tagged container services (getServicesByInterface(SourceTransformer::class)), so nounset()exclusion is needed anymore.src/Instrument/Transformer/CachingTransformer.php, its container definition inAspectKernel::init(), andSourceTransformingLoader::addTransformer(). TheregisterTransformerServices()extension hook is unchanged.Why it helps
The old cached branch went through the whole filter pipeline anyway and then re-parsed the cached file (
ReflectionEngine::parseFile()) just to rebuild the token stream. Now a hit skips parsing entirely — which finally makes the warm-cache fast path apply in debug mode too, with unchanged invalidation semantics.Local numbers (fixture app, opcache file cache, median of 21):
PHP 8.4 debug warm shows the same shape: 16.2 ms → 5.5 ms (−66 %).
Validation
phpunitgreen on PHP 8.5 and 8.4 (2486 tests), including the functional warmup / debug:weaving / inconsistent-weaving coverage that exercises the moved logic on real cachesphpstan(level max) clean🤖 Generated with Claude Code
https://claude.ai/code/session_01V1Z87HZ2iz23WPTtTYqFxE
Generated by Claude Code