Repository navigation
Serve cached Composer releases without a metadata lookup - #568
Merged
andrew merged 1 commit intoOct 23, 2026
Merged
Conversation
Every Composer archive download resolved its dist from the package metadata before checking the artifact cache. With cache_metadata off, the default, that meant an uncoalesced upstream GET of the p2 document for every download of an archive the proxy already had: three downloads of a cached archive made three metadata requests. With the cache on, each download after the TTL revalidated and rescanned the document. The lookup is only needed for the publish time cooldown checks downloads against, since lock files name archive URLs directly. Like the npm handler, record that time in the versions table when the dist is first resolved, and on later downloads of a tagged release read it from there and serve the cached archive straight away. Without a stored time, as for archives cached by an older proxy, the download takes the metadata path, which then records it. The time is stored even with cooldown off, so enabling cooldown later keeps the fast path. The cache still enforces the denylist and verifies the stored digest, and an archive is only ever cached under a name that was checked against the metadata, so those guarantees hold. Branches, whose archive and time change with every push, routed packages, whose versions row would not say which repository the time came from, and requests with a query string such as ?sha= keep resolving from the metadata.
andrew
approved these changes
Oct 23, 2026
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.
Every Composer archive download looked up its dist in the package metadata before checking the artifact cache. With
cache_metadataoff, which is the default, each download of an archive the proxy already had cost an uncoalesced upstream GET of the p2 document: three downloads meant three metadata requests. With the cache on, each download after the TTL revalidated the document and scanned it again.The download only needs that lookup for the publish time it checks cooldown against, because lock files name archive URLs directly. Like npm, the handler now stores that time in the versions table when the dist is first resolved. Later downloads of a tagged release then work like this:
Guarantees that still hold:
Downloads that stay on the metadata path:
?sha=.One behaviour change: a cached release is now served even if upstream has since removed or re-tagged the version. With
cache_metadataoff, that request used to get 404. npm already behaves the new way.Tests:
TestComposerCachedReleaseSkipsMetadata: with metadata caching off, on with the TTL expired, and with cooldown, three downloads now make one metadata request instead of three.TestComposerDownloadStoresPublishTime.TestComposerCachedReleaseCooldownFromStoredTime: cooldown enabled or raised after caching still withholds the archive.TestComposerCachedReleaseWithoutStoredTime.TestComposerCachedDevVersionUsesMetadataandTestComposerCachedRoutedReleaseUsesMetadata.TestComposerCachedReleaseDenied.