Skip to content

fix(registry): handle 304 Not Modified by returning cached FullManifest - #2562

Closed
elrrrrrrr wants to merge 1 commit into
nextfrom
fix-issue-2561
Closed

fix(registry): handle 304 Not Modified by returning cached FullManifest#2562
elrrrrrrr wants to merge 1 commit into
nextfrom
fix-issue-2561

Conversation

@elrrrrrrr

Copy link
Copy Markdown
Contributor

Summary

When the npm registry returns 304 Not Modified, instead of returning an error with a helpful message that the caller could not use, we now construct a minimal FullManifest from the cached versions info and return it.

This allows callers like ut view to get dist_tags and the version list even when the full manifest is already cached locally.

Changes

In resolve_full_manifest:

  1. On 304 response, first try to use memory cache for full manifest (preload phase may have cached it)
  2. If no memory cache, use versions cache to build a minimal FullManifest with:
    • Package name
    • dist_tags from cached versions info
    • Version manifests from disk cache (if available)
  3. Only fallback to fresh fetch if no cache is available

The fix maintains backward compatibility - if cache is fully populated, the behavior is identical to before. The improvement is specifically for the 304 case when only versions info is cached.

Testing

Issue #2561 describes the problem where ut view lodash failed with:
ERROR Failed to fetch package info for lodash: 304 Not Modified - use versions cache for lodash

With this fix, the 304 case now returns a usable FullManifest constructed from cache, allowing the command to succeed.

Fixes #2561

When npm registry returns 304 Not Modified, instead of returning an error,
we now construct a minimal FullManifest from cached versions info and
return it. This allows callers like  to get dist_tags and version
list even when the full manifest is cached.

The fix reconstructs FullManifest with:
- Package name
- dist_tags from cached versions info
- Version manifests from disk cache (if available)

If no cache is available, it fetches fresh data as before.

Fixes #2561
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @elrrrrrrr, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the robustness of the registry service's caching mechanism. By implementing a sophisticated strategy for handling HTTP 304 Not Modified responses, the system can now reconstruct and provide essential package metadata from various cache layers, preventing errors and ensuring continuous access to information like distribution tags and version lists, even when a full manifest update isn't required.

Highlights

  • Improved 304 Not Modified Handling: The system now intelligently handles HTTP 304 Not Modified responses by constructing a usable "FullManifest" from cached data instead of returning an error.
  • Tiered Caching Strategy: A new caching hierarchy is introduced, prioritizing memory cache, then versions cache (disk/memory), before falling back to a fresh network request for "FullManifest" retrieval.
  • Minimal FullManifest Construction: When a 304 is received and a full manifest isn't in memory, a minimal "FullManifest" is built using cached "dist_tags" and individual version manifests from disk, ensuring essential package metadata is available.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@elrrrrrrr elrrrrrrr closed this Feb 2, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This is a great fix that improves the handling of 304 Not Modified responses from the registry. Instead of returning an error, constructing a minimal manifest from the cache is much more useful for callers. The logic is sound and covers different caching scenarios well. I have a couple of suggestions to further improve the implementation by removing a redundant cache call and parallelizing part of the cache population, which should improve performance.

Comment on lines 227 to 229
// Cache versions in memory for later use
self.cache
.set_versions(name.to_string(), versions_info.clone());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This call to set_versions appears to be redundant. The versions_info is guaranteed to be in the memory cache at this point because both get_versions_from_disk (which populates disk_versions) and get_versions either load it into or retrieve it from the memory cache. You can remove these lines to avoid the redundant operation and a clone.

Comment on lines +240 to +244
for v in &versions_info.versions.version_list {
if let Some(manifest) = self.cache.get_version_manifest_from_disk(name, v).await {
minimal_manifest.versions.insert(v.clone(), manifest);
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This loop populates version manifests by awaiting a disk read for each version sequentially. This can be slow if a package has many versions. You can improve performance by fetching them concurrently using futures::stream. This will execute the I/O-bound get_version_manifest_from_disk calls in parallel.

Note: This requires futures to be a dependency.

Suggested change
for v in &versions_info.versions.version_list {
if let Some(manifest) = self.cache.get_version_manifest_from_disk(name, v).await {
minimal_manifest.versions.insert(v.clone(), manifest);
}
}
minimal_manifest.versions = futures::stream::iter(&versions_info.versions.version_list)
.filter_map(|v| async move {
self.cache
.get_version_manifest_from_disk(name, v)
.await
.map(|manifest| (v.clone(), manifest))
})
.collect()
.await;

@github-actions

github-actions Bot commented Feb 2, 2026

Copy link
Copy Markdown

📊 Performance Benchmark Report (with-antd)

🚀 Utoopack Performance Report: Async Task Scheduling Overhead Analysis

Report ID: utoopack_performance_report_20260202_120634
Generated: 2026-02-02 12:06:34
Trace File: trace_antd.json (1.5GB, 8.01M events)
Test Project: examples/with-antd


📊 Executive Summary

This report analyzes the performance of Utoopack/Turbopack, covering the full spectrum of the Performance Analysis Protocol (P0-P4).

Key Findings

Metric Value Assessment
Total Wall Time 10,609.5 ms Baseline
Total Thread Work 91,719.3 ms ~8.6x parallelism
Thread Utilization 50.9% ⚠️ Suboptimal
turbo_tasks::function Invocations 3,885,010 Total count
Meaningful Tasks (≥ 10µs) 1,567,856 (40.4% of total)
Tracing Noise (< 10µs) 2,317,154 (59.6% of total)

Workload Distribution by Tier

Category Tasks Total Time (ms) % of Work
P0: Runtime/Resolution 1,076,773 55,736.5 60.8%
P1: I/O & Heavy Tasks 38,020 3,867.7 4.2%
P3: Asset Pipeline 28,459 4,561.8 5.0%
P4: Bridge/Interop 0 0.0 0.0%
Other 424,604 20,389.3 22.2%

⚡ Parallelization Analysis (P0-P2)

Thread Utilization

Metric Value
Number of Threads 17
Total Thread Work 91,719.3 ms
Avg Work per Thread 5,395.3 ms
Theoretical Parallelism 8.64x
Thread Utilization 50.9%

Assessment: With 17 threads available, achieving 8.6x parallelism indicates significant loss of potential parallelism.


📈 Top 20 Tasks (Global)

These are the most significant tasks by total duration:

Total (ms) Count Avg (µs) % Work Task Name
46,314.1 890,877 52.0 50.5% turbo_tasks::function
8,705.7 127,446 68.3 9.5% task execution completed
6,786.9 85,822 79.1 7.4% turbo_tasks::resolve_call
3,213.8 33,062 97.2 3.5% analyze ecmascript module
2,246.7 67,854 33.1 2.4% precompute code generation
2,142.9 68,737 31.2 2.3% resolving
1,868.7 36,703 50.9 2.0% module
1,826.8 20,917 87.3 2.0% effects processing
1,560.7 11,782 132.5 1.7% process parse result
1,158.1 6,796 170.4 1.3% parse ecmascript
1,139.0 33,999 33.5 1.2% process module
1,060.0 36,529 29.0 1.2% internal resolving
816.7 29,245 27.9 0.9% resolve_relative_request
700.6 1,921 364.7 0.8% analyze variable values
519.3 22,690 22.9 0.6% handle_after_resolve_plugins
471.1 16,180 29.1 0.5% resolve_module_request
461.9 1,950 236.9 0.5% swc_parse
424.5 10,961 38.7 0.5% code generation
392.6 17,901 21.9 0.4% resolved
366.7 4,255 86.2 0.4% read file

🔍 Deep Dive by Tier

🔴 Tier 1: Runtime & Resolution (P0)

Focus: Task scheduling and dependency resolution.

Metric Value Status
Total Scheduling Time 55,736.5 ms ⚠️ High
Resolution Hotspots 9 tasks 🔍 Check Top Tasks

Potential P0 Issues:

  • Low thread utilization (50.9%) suggests critical path serialization or lock contention.
  • 2,317,154 tasks < 10µs (59.6%) contribute to scheduler pressure.

🟠 Tier 2: Physical & Resource Barriers (P1)

Focus: Hardware utilization, I/O, and heavy monoliths.

Metric Value Status
I/O Work (Estimated) 3,867.7 ms ✅ Healthy
Large Tasks (> 100ms) 20 🚨 Critical

Potential P1 Issues:

  • 20 tasks exceed 100ms. These "Heavy Monoliths" are prime candidates for splitting.

🟡 Tier 3: Architecture & Asset Pipeline (P2-P3)

Focus: Global state and transformation pipeline.

Metric Value Status
Asset Processing (P3) 4,561.8 ms 5.0% of work
Bridge Overhead (P4) 0.0 ms ✅ Low

💡 Recommendations (Prioritized P0-P2)

🚨 Critical: (P0) Improvement

Problem: 50.9% thread utilization.
Action:

  1. Profile lock contention if utilization < 60%.
  2. Convert sequential await chains to try_join.

⚠️ High Priority: (P1) Optimization

Problem: 20 heavy tasks detected.
Action:

  1. Identify module-level bottlenecks (e.g., barrel files).
  2. Optimize I/O batching for metadata.

⚠️ Medium Priority: (P3) Pipeline Efficiency

Action:

  1. Review transformation logic for frequently changed assets.
  2. Minimize cross-language serialization (P4) if overhead exceeds 10%.

📐 Diagnostic Signal Summary

Signal Status Finding
Tracing Noise (P0) ✅ Acceptable 59.6% of tasks < 10µs
Thread Utilization (P0) 🚨 Low 50.9% utilization
Heavy Monoliths (P1) ⚠️ Detected 20 tasks > 100ms
Asset Pipeline (P3) 🔍 Review 4,561.8 ms total
Bridge/Interop (P4) ✅ Low 0.0 ms total

🎯 Action Items (Comprehensive P0-P4)

  1. [P0] Profile lock contention to address 49% lost parallelism
  2. [P1] Breakdown heavy monolith tasks (>100ms) to improve granularity
  3. [P1] Review I/O patterns for potential batching opportunities
  4. [P3] Optimize asset transformation pipeline hot-spots
  5. [P4] Reduce "chatty" bridge operations if interop overhead is significant

Report generated by Utoopack Performance Analysis Agent on 2026-02-02
Following: Utoopack Performance Analysis Agent Protocol

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.

🐛 <BUG> ut view manifest 304 cache error

1 participant