Repository navigation
perf(pm): drop redundant version_list / dist_tags clones on resolve hot path #2877
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -244,11 +244,19 @@ impl UnifiedRegistry { | |
| .await | ||
| .map_err(RegistryError)? | ||
| { | ||
| manifest::FetchManifestResult::Ok(manifest, new_etag) => { | ||
| manifest::FetchManifestResult::Ok(mut manifest, new_etag) => { | ||
| // MOVE version_list / dist_tags out of `manifest` | ||
| // into `VersionsInfo` instead of cloning. The cached | ||
| // `Arc<FullManifest>` keeps `raw` + scalar metadata; | ||
| // canonical version_list / dist_tags now live in the | ||
| // `versions_info` cache slot only. Readers of these | ||
| // fields go through `cache.get_versions(name)`. | ||
| let version_list = std::mem::take(&mut manifest.versions); | ||
| let dist_tags = std::mem::take(&mut manifest.dist_tags); | ||
|
Comment on lines
+254
to
+255
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using Additionally, since |
||
| let versions_info = Arc::new(VersionsInfo { | ||
| versions: Versions { | ||
| version_list: manifest.versions.clone(), | ||
| dist_tags: manifest.dist_tags.clone(), | ||
| version_list, | ||
| dist_tags, | ||
| }, | ||
| etag: new_etag, | ||
| last_updated: current_timestamp_secs(), | ||
|
|
@@ -269,18 +277,20 @@ impl UnifiedRegistry { | |
| self.cache.set_versions(name.to_string(), versions_info); | ||
| } else { | ||
| // Persistent store corrupted/missing, fetch fresh (without etag). | ||
| let (manifest, new_etag) = manifest::fetch_full_manifest_fresh( | ||
| let (mut manifest, new_etag) = manifest::fetch_full_manifest_fresh( | ||
| &self.registry_url, | ||
| name, | ||
| manifest::MetadataFormat::Abbreviated, | ||
| ) | ||
| .await | ||
| .map_err(RegistryError)?; | ||
|
|
||
| let version_list = std::mem::take(&mut manifest.versions); | ||
| let dist_tags = std::mem::take(&mut manifest.dist_tags); | ||
| let versions_info = Arc::new(VersionsInfo { | ||
| versions: Versions { | ||
| version_list: manifest.versions.clone(), | ||
| dist_tags: manifest.dist_tags.clone(), | ||
| version_list, | ||
| dist_tags, | ||
| }, | ||
| etag: new_etag, | ||
| last_updated: current_timestamp_secs(), | ||
|
|
@@ -429,12 +439,23 @@ impl UnifiedRegistry { | |
| ) -> Result<(String, CoreVersionManifest), RegistryError> { | ||
| match self.resolve_full_manifest(name).await? { | ||
| FullManifestResult::Full(full) => { | ||
| if full.versions.is_empty() { | ||
| // Canonical `version_list` / `dist_tags` live in the | ||
| // `versions_info` cache slot — the 200 path moved them | ||
| // there with `std::mem::take`. Read through the cache | ||
| // instead of the (now-empty) fields on the cached | ||
| // `Arc<FullManifest>`. | ||
| let versions_info = self.cache.get_versions(name).ok_or_else(|| { | ||
| RegistryError(anyhow!("Versions cache not found for {}", name)) | ||
| })?; | ||
|
Comment on lines
+447
to
+449
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This introduces an additional |
||
| if versions_info.versions.version_list.is_empty() { | ||
| return Err(RegistryError(anyhow!("No versions available for {}", name))); | ||
| } | ||
| let resolved_version = | ||
| resolve_target_version(&full.dist_tags, &full.versions, spec) | ||
| .map_err(|e| RegistryError(anyhow!("{}@{}: {}", name, spec, e)))?; | ||
| let resolved_version = resolve_target_version( | ||
| &versions_info.versions.dist_tags, | ||
| &versions_info.versions.version_list, | ||
| spec, | ||
| ) | ||
| .map_err(|e| RegistryError(anyhow!("{}@{}: {}", name, spec, e)))?; | ||
| let core = full.get_core_version(&resolved_version).ok_or_else(|| { | ||
| RegistryError(anyhow!( | ||
| "Version {} not found in manifest for {}", | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check (and the subsequent
resolve_target_versioncall) will incorrectly fail withNoVersionsif themanifestwas obtained from aUnifiedRegistrycache. Themem::takeoptimization introduced inservice/registry.rsempties theversionsfield of the cached manifest, breaking compatibility with this public function and any other external consumers of theFullManifeststruct.