Skip to content
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

feat: proxy模式增强 #724

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

fangzhengjin
Copy link
Contributor

@fangzhengjin fangzhengjin commented Nov 1, 2024

  1. 刷新代理缓存时,如果source仓库找不到(404)时,尝试在private仓库中查找,以private仓库查询结果返回
  2. 刷新代理缓存时,如果在同时在source与private中找到,则将private结果中的versions与time数组合并至source查询的结果中(只合并source中不存在的key)
  3. 当在private中推送私有包时,立即从private库中刷新该包的缓存信息,可即时被查询或下载,无需等待凌晨3点刷新缓存

Summary by CodeRabbit

  • New Features

    • Enhanced error handling during cache retrieval to prevent unhandled exceptions.
    • Improved logic for managing proxy cache updates, allowing for concurrent processing of package manifests.
  • Bug Fixes

    • Refined handling of 404 responses to ensure successful retrieval of package manifests from private sources.
  • Documentation

    • Updated internal documentation to reflect changes in error logging and proxy cache management.

Copy link
Contributor

coderabbitai bot commented Nov 1, 2024

Walkthrough

The ProxyCacheService class in app/core/service/ProxyCacheService.ts has been updated to enhance its functionality and error handling. A new dependency, PackageManagerService, has been introduced to assist with managing package manifests, particularly when handling 404 responses from upstream requests. The getRewrittenManifest method has been enhanced to retrieve manifests from private sources if necessary, while error handling in the getPackageManifest method has been strengthened to ensure resilience during cache retrieval. Additionally, the UpdatePackageController class has been modified to incorporate proxy cache updates.

Changes

File Path Change Summary
app/core/service/ProxyCacheService.ts - Injected PackageManagerService into ProxyCacheService.
- Updated getRewrittenManifest to handle 404 responses and retrieve manifests from private sources.
- Improved error handling in getPackageManifest with try-catch and logging.
- Destructured response for concise access and adjusted tarball URL replacement logic.
app/port/controller/package/UpdatePackageController.ts - Added dependencies for SyncMode, ProxyCacheRepository, and ProxyCacheService.
- Introduced properties proxyCacheRepository and proxyCacheService.
- Updated update method to handle proxy cache updates based on synchronization mode.

Possibly related PRs

  • feat: proxy mode [sql changed] #571: The changes in ProxyCacheService regarding the handling of package manifests and integration with private sources are directly related to the modifications made in the same service within this PR, which also focuses on caching mechanisms and managing package versions.

Suggested labels

sql

Suggested reviewers

  • elrrrrrrr

Poem

🐰 In the garden where the packages grow,
A service now smarter, with a new flow.
When 404s come knocking, it won't miss,
Private sources to fetch, a manifest bliss.
With errors now caught, like leaves in the breeze,
ProxyCache dances, with grace and with ease! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

sweep-ai bot commented Nov 1, 2024

Hey @fangzhengjin, here is an example of how you can ask me to improve this pull request:

@Sweep Add unit tests for the updated `getPackageManifest` method to verify error handling behavior when cache retrieval fails

📖 For more information on how to use Sweep, please read our documentation.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (1)
app/core/service/ProxyCacheService.ts (1)

184-194: Avoid variable shadowing of 'manifest'

Within the if (status === 404) block, the variable manifest is redefined when destructuring from data, which can lead to confusion due to variable shadowing. Consider renaming the inner manifest variable to avoid this issue.

Apply this diff to rename the variable:

- const { etag, data: manifest, blockReason } = ...
+ const { etag, data: privateManifest, blockReason } = ...

And update the return statement:

- return manifest as any;
+ return privateManifest as any;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 4facf90 and e2c4c36.

📒 Files selected for processing (1)
  • app/core/service/ProxyCacheService.ts (6 hunks)
🧰 Additional context used
📓 Learnings (1)
app/core/service/ProxyCacheService.ts (3)
Learnt from: hezhengxu2018
PR: cnpm/cnpmcore#571
File: app/core/service/ProxyCacheService.ts:161-209
Timestamp: 2024-10-09T03:45:47.108Z
Learning: In the `ProxyCacheService` class, requests to the upstream repository already throw an error if they fail, making additional checks for the response status unnecessary.
Learnt from: hezhengxu2018
PR: cnpm/cnpmcore#571
File: app/core/service/ProxyCacheService.ts:161-209
Timestamp: 2024-10-09T03:45:48.990Z
Learning: In the `ProxyCacheService` class, requests to the upstream repository already throw an error if they fail, making additional checks for the response status unnecessary.
Learnt from: hezhengxu2018
PR: cnpm/cnpmcore#571
File: app/core/service/ProxyCacheService.ts:161-209
Timestamp: 2024-07-19T06:26:05.533Z
Learning: In the `ProxyCacheService` class, requests to the upstream repository already throw an error if they fail, making additional checks for the response status unnecessary.

app/core/service/ProxyCacheService.ts Outdated Show resolved Hide resolved
app/core/service/ProxyCacheService.ts Outdated Show resolved Hide resolved
@fangzhengjin fangzhengjin changed the title [WIP] feat: 在proxy模式下,可以返回私有包 feat: 在proxy模式下,可以返回私有包 Nov 1, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (3)
app/core/service/ProxyCacheService.ts (1)

218-225: Add timestamp validation for time merging

The time merging logic should validate timestamp formats to prevent invalid dates.

Consider adding timestamp validation:

 if (manifest.time) {
   const privateTimeMap = data?.time || {};
   for (const key in privateTimeMap) {
+    const timestamp = privateTimeMap[key];
+    if (!timestamp || isNaN(Date.parse(timestamp))) continue;
     if (!manifest.time[key]) {
       manifest.time[key] = privateTimeMap[key];
     }
   }
 }
app/port/controller/package/UpdatePackageController.ts (2)

74-74: Maintain consistency in comment language

The comment on line 74 is in Chinese: // 代理模式下,更新代理缓存. To maintain consistency across the codebase, consider translating comments to English.


79-79: Maintain consistency in comment language

The comment on line 79 is in Chinese: // 仅manifests需要更新,指定版本的package.json文件发布后不会改变. To maintain consistency across the codebase, consider translating comments to English.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e2c4c36 and b430e6d.

📒 Files selected for processing (2)
  • app/core/service/ProxyCacheService.ts (6 hunks)
  • app/port/controller/package/UpdatePackageController.ts (3 hunks)
🧰 Additional context used
📓 Learnings (1)
app/core/service/ProxyCacheService.ts (3)
Learnt from: hezhengxu2018
PR: cnpm/cnpmcore#571
File: app/core/service/ProxyCacheService.ts:161-209
Timestamp: 2024-10-09T03:45:47.108Z
Learning: In the `ProxyCacheService` class, requests to the upstream repository already throw an error if they fail, making additional checks for the response status unnecessary.
Learnt from: hezhengxu2018
PR: cnpm/cnpmcore#571
File: app/core/service/ProxyCacheService.ts:161-209
Timestamp: 2024-10-09T03:45:48.990Z
Learning: In the `ProxyCacheService` class, requests to the upstream repository already throw an error if they fail, making additional checks for the response status unnecessary.
Learnt from: hezhengxu2018
PR: cnpm/cnpmcore#571
File: app/core/service/ProxyCacheService.ts:161-209
Timestamp: 2024-07-19T06:26:05.533Z
Learning: In the `ProxyCacheService` class, requests to the upstream repository already throw an error if they fail, making additional checks for the response status unnecessary.
🔇 Additional comments (6)
app/core/service/ProxyCacheService.ts (4)

20-20: LGTM: PackageManagerService integration

The PackageManagerService dependency is correctly imported and injected following the established pattern.

Also applies to: 55-56


66-76: LGTM: Robust error handling for cache retrieval

The error handling implementation is well-structured:

  • Gracefully handles cache misses
  • Properly logs errors without breaking execution
  • Uses correct context in log messages

Line range hint 197-226: Optimize version map merging logic

The current implementation of merging private and public versions could be more efficient and safer.

Consider refactoring to use a more functional approach:

-      const privateVersionMap = data?.versions || {};
-      for (const key in privateVersionMap) {
-        if (!versionMap[key]) {
-          versionMap[key] = privateVersionMap[key];
-        }
-      }
+      manifest.versions = {
+        ...privateVersionMap,
+        ...versionMap,
+      };

Also, consider adding a lock or synchronization mechanism to prevent potential race conditions during version map updates.


184-194: Consider adding manifest validation

The code handles 404 status and private package retrieval, but there's no validation of the manifest structure before processing.

Consider adding validation before processing the manifest:

 const { status, data: { manifest } } = responseResult;
+if (!manifest || typeof manifest !== 'object') {
+  throw new Error('Invalid manifest structure received');
+}
 // sourceRegistry not found, check private package
app/port/controller/package/UpdatePackageController.ts (2)

20-22: Imports are properly added

The modules SyncMode, ProxyCacheRepository, isPkgManifest, and ProxyCacheService are correctly imported and used in the code.


36-39: Dependency injection setup is correct

The dependencies proxyCacheRepository and proxyCacheService are properly injected as private readonly class properties with the @Inject() decorator.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e2c4c36 and 760c862.

📒 Files selected for processing (2)
  • app/core/service/ProxyCacheService.ts (5 hunks)
  • app/port/controller/package/UpdatePackageController.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/core/service/ProxyCacheService.ts

@fangzhengjin fangzhengjin force-pushed the feature/proxySupportPrivatePackage branch from c54a9e4 to 3aea4c8 Compare November 1, 2024 15:35
@fangzhengjin fangzhengjin changed the title feat: 在proxy模式下,可以返回私有包 feat: proxy模式增强 Nov 1, 2024
@fangzhengjin
Copy link
Contributor Author

@fengmk2 空了麻烦看下有啥要调整的

@@ -171,9 +181,24 @@ export class ProxyCacheService extends AbstractService {
}

// replace tarball url
const manifest = responseResult.data;
const { status, data: manifest } = responseResult;
Copy link
Member

Choose a reason for hiding this comment

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

manifest 是 const 的话,下面会被重新赋值,应该先设置它是 let manifest = undefined,确保代码的可读性。

Copy link
Contributor Author

Choose a reason for hiding this comment

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

manifest 是 const 的话,下面会被重新赋值,应该先设置它是 let manifest = undefined,确保代码的可读性。

两个manifest的作用域不一样,不存在重新赋值的说法吧?如果是为了可读性的话,一个改成remoteManifest一个改成privateManifest,这样可以吗?

@fengmk2
Copy link
Member

fengmk2 commented Nov 3, 2024

需要增加对应的单元测试

@fengmk2 fengmk2 added the enhancement New feature or request label Nov 3, 2024
@fengmk2
Copy link
Member

fengmk2 commented Nov 3, 2024

需要 @hezhengxu2018 参与 CR

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (1)
app/core/service/ProxyCacheService.ts (1)

184-194: Add error logging for 404 scenarios

While the 404 handling logic is correct, consider adding error logging to track when packages are not found in the source registry and successfully retrieved from private registry. This will help with monitoring and debugging.

 if (status === 404) {
+  this.logger.info('[ProxyCacheService:getRewrittenManifest] Package %s not found in source registry, checking private registry', fullname);
   const { etag, data: manifest, blockReason } = fileType === DIST_NAMES.FULL_MANIFESTS ?
     await this.packageManagerService.listPackageFullManifests(scope, name, false) :
     await this.packageManagerService.listPackageAbbreviatedManifests(scope, name, false);
   // found in private package
   if (etag && !blockReason) {
+    this.logger.info('[ProxyCacheService:getRewrittenManifest] Package %s found in private registry', fullname);
     return manifest as any;
   }
+  this.logger.info('[ProxyCacheService:getRewrittenManifest] Package %s not found in private registry', fullname);
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 760c862 and 3aea4c8.

📒 Files selected for processing (2)
  • app/core/service/ProxyCacheService.ts (6 hunks)
  • app/port/controller/package/UpdatePackageController.ts (3 hunks)
🧰 Additional context used
📓 Learnings (1)
app/core/service/ProxyCacheService.ts (3)
Learnt from: hezhengxu2018
PR: cnpm/cnpmcore#571
File: app/core/service/ProxyCacheService.ts:161-209
Timestamp: 2024-10-09T03:45:47.108Z
Learning: In the `ProxyCacheService` class, requests to the upstream repository already throw an error if they fail, making additional checks for the response status unnecessary.
Learnt from: hezhengxu2018
PR: cnpm/cnpmcore#571
File: app/core/service/ProxyCacheService.ts:161-209
Timestamp: 2024-10-09T03:45:48.990Z
Learning: In the `ProxyCacheService` class, requests to the upstream repository already throw an error if they fail, making additional checks for the response status unnecessary.
Learnt from: hezhengxu2018
PR: cnpm/cnpmcore#571
File: app/core/service/ProxyCacheService.ts:161-209
Timestamp: 2024-07-19T06:26:05.533Z
Learning: In the `ProxyCacheService` class, requests to the upstream repository already throw an error if they fail, making additional checks for the response status unnecessary.
🔇 Additional comments (5)
app/port/controller/package/UpdatePackageController.ts (3)

20-22: LGTM! Clean import additions for proxy functionality

The new imports are well-organized and properly scoped for the proxy mode enhancement.


36-39: LGTM! Well-structured service injections

The new proxy-related services are properly injected with readonly modifiers, following good dependency injection practices.


74-93: Verify package type check for private packages

The implementation refreshes proxy cache on package updates, but let's verify that it correctly identifies private packages.

app/core/service/ProxyCacheService.ts (2)

20-21: LGTM: Clean dependency injection for PackageManagerService

The addition of PackageManagerService as a dependency is well-structured and necessary for implementing the private package handling functionality.

Also applies to: 55-56


66-76: LGTM: Robust error handling for cache retrieval

The added try-catch block with proper error logging ensures system resilience during cache retrieval failures, allowing the system to fall back to fresh manifest retrieval.

Comment on lines +74 to +93
// 代理模式下,更新代理缓存
if (this.config.cnpmcore.syncMode === SyncMode.proxy) {
const refreshList = await this.proxyCacheRepository.findProxyCaches(fullname);
if (refreshList.length !== 0) {
const taskList = refreshList
// 仅manifests需要更新,指定版本的package.json文件发布后不会改变
.filter(i => isPkgManifest(i.fileType))
.map(async item => {
const task = await this.proxyCacheService.createTask(
`${item.fullname}/${item.fileType}`,
{
fullname: item.fullname,
fileType: item.fileType,
},
);
return task;
});
await Promise.all(taskList);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for proxy cache updates

While the proxy cache update logic is correct, it lacks error handling for the Promise.all operation. Failed cache updates should be logged but not block the main operation.

Consider applying this improvement:

    if (this.config.cnpmcore.syncMode === SyncMode.proxy) {
      const refreshList = await this.proxyCacheRepository.findProxyCaches(fullname);
      if (refreshList.length !== 0) {
        const taskList = refreshList
          .filter(i => isPkgManifest(i.fileType))
          .map(item => 
            this.proxyCacheService.createTask(
              `${item.fullname}/${item.fileType}`,
              {
                fullname: item.fullname,
                fileType: item.fileType,
              },
            )
          );
+       try {
          await Promise.all(taskList);
+       } catch (error) {
+         // Log error but don't block the main operation
+         ctx.logger.error('[UpdatePackageController] Failed to update proxy cache', {
+           error,
+           fullname,
+           taskCount: taskList.length,
+         });
+       }
      }
    }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +210 to +226
// private manifest
if (hasPrivatePackage) {
const privateVersionMap = data?.versions || {};
for (const key in privateVersionMap) {
if (!versionMap[key]) {
versionMap[key] = privateVersionMap[key];
}
}
if (manifest.time) {
const privateTimeMap = data?.time || {};
for (const key in privateTimeMap) {
if (!manifest.time[key]) {
manifest.time[key] = privateTimeMap[key];
}
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add defensive checks for manifest merging

The manifest merging logic should include additional checks to handle edge cases and ensure data integrity.

-if (hasPrivatePackage) {
+if (hasPrivatePackage && data && manifest) {
+  // Ensure versions object exists
+  manifest.versions = manifest.versions || {};
+  manifest.time = manifest.time || {};
+
   const privateVersionMap = data?.versions || {};
   for (const key in privateVersionMap) {
-    if (!versionMap[key]) {
+    if (!versionMap[key] && privateVersionMap[key]?.version === key) {
       versionMap[key] = privateVersionMap[key];
     }
   }
-  if (manifest.time) {
-    const privateTimeMap = data?.time || {};
-    for (const key in privateTimeMap) {
-      if (!manifest.time[key]) {
-        manifest.time[key] = privateTimeMap[key];
-      }
+  const privateTimeMap = data?.time || {};
+  for (const key in privateTimeMap) {
+    const timeValue = privateTimeMap[key];
+    if (!manifest.time[key] && typeof timeValue === 'string' && isValidISODateString(timeValue)) {
+      manifest.time[key] = timeValue;
     }
   }
 }

Consider adding a helper function to validate ISO date strings:

function isValidISODateString(dateString: string): boolean {
  if (typeof dateString !== 'string') return false;
  const date = new Date(dateString);
  return date instanceof Date && !isNaN(date.getTime()) && date.toISOString() === dateString;
}

🛠️ Refactor suggestion

Add version format validation before merging

The version merging logic should validate the format of version strings before merging to prevent invalid versions from being added to the manifest. Consider using the semver package that's already imported.

 if (hasPrivatePackage) {
   const privateVersionMap = data?.versions || {};
   for (const key in privateVersionMap) {
-    if (!versionMap[key]) {
+    if (!versionMap[key] && semverValid(key)) {
       versionMap[key] = privateVersionMap[key];
+    } else if (!semverValid(key)) {
+      this.logger.warn('[ProxyCacheService:getRewrittenManifest] Skipping invalid version %s from private package %s', key, fullname);
     }
   }
   if (manifest.time) {
     const privateTimeMap = data?.time || {};
     for (const key in privateTimeMap) {
-      if (!manifest.time[key]) {
+      if (!manifest.time[key] && (key === 'created' || key === 'modified' || semverValid(key))) {
         manifest.time[key] = privateTimeMap[key];
+      } else if (key !== 'created' && key !== 'modified' && !semverValid(key)) {
+        this.logger.warn('[ProxyCacheService:getRewrittenManifest] Skipping invalid time entry %s from private package %s', key, fullname);
       }
     }
   }
 }

Committable suggestion skipped: line range outside the PR's diff.

@hezhengxu2018
Copy link
Collaborator

这确实是现在这个功能和verdaccio不一致。最关键的区别是verdaccio有一个自己的存储区还有一个对依赖的缓存区,但是现在cnpmcore的模式是不是缓存,而是对包的一次sync。比如自己先在仓库发布了一个自己修改版的react依赖在这个仓库中对依赖有发布权限的人就成了你,当你去同步公共npm仓库的react的包时会因为包的维护信息不一致而更新错误(应该)。即这个包在当前仓库的所有者到底公网npm仓库的团队还是本地的npm仓库,应该用哪个manifest?所以现在的代理模式还是作为一种特殊情况下的同步模式(syncMode)。verdaccio是有两个独立的存储区域,即优先访问内部仓库找不到时才访问有缓存的代理模式但是一个cnpmcore只有一个表和一个对象存储。
现在我在使用时是通过部署两套cnpmcore来实现原来的verdaccio的功能的。一套存储私有依赖一套是代理的同步加速。我觉得把这个404访问私有包的功能引入会让依赖变得混乱和难以理解,开启代理模式和关闭代理模式会有两套不一样的manifest返回。我认为部署两套仓库是比较干净的做法不会引起依赖所有权的冲突。

另外同步时间上确实设置的过于保守了,nexus的代理缓存刷新时间是30分钟还是15分钟,现在只有每天凌晨3点去刷新缓存。但是这个好像不能通过配置项去设置,需要的话可以在启动之前改一下这个参数。

@fangzhengjin
Copy link
Contributor Author

fangzhengjin commented Nov 3, 2024

这确实是现在这个功能和verdaccio不一致。最关键的区别是verdaccio有一个自己的存储区还有一个对依赖的缓存区,但是现在cnpmcore的模式是不是缓存,而是对包的一次sync。比如自己先在仓库发布了一个自己修改版的react依赖在这个仓库中对依赖有发布权限的人就成了你,当你去同步公共npm仓库的react的包时会因为包的维护信息不一致而更新错误(应该)。即这个包在当前仓库的所有者到底公网npm仓库的团队还是本地的npm仓库,应该用哪个manifest?所以现在的代理模式还是作为一种特殊情况下的同步模式(syncMode)。verdaccio是有两个独立的存储区域,即优先访问内部仓库找不到时才访问有缓存的代理模式但是一个cnpmcore只有一个表和一个对象存储。 现在我在使用时是通过部署两套cnpmcore来实现原来的verdaccio的功能的。一套存储私有依赖一套是代理的同步加速。我觉得把这个404访问私有包的功能引入会让依赖变得混乱和难以理解,开启代理模式和关闭代理模式会有两套不一样的manifest返回。我认为部署两套仓库是比较干净的做法不会引起依赖所有权的冲突。

另外同步时间上确实设置的过于保守了,nexus的代理缓存刷新时间是30分钟还是15分钟,现在只有每天凌晨3点去刷新缓存。但是这个好像不能通过配置项去设置,需要的话可以在启动之前改一下这个参数。

我看过verdaccio的数据存储结构,实际上并没有两个独立的存储区,对于相同package的不同版本(包括自定义版本)都是存储在一个目录在的,在这个package的manifest中会合并自定义版本与代理缓存版本的time / version等数据,他是先在存储的manifest中查找你要下载的版本在存储中是否存在,如果不存在则立即向上游尝试下载你请求的版本并添加到存储中,同时刷新存储中的manifest(manifest中会包含自定义版本),当然他可能会有其他地方会记录哪些版本是自定义的,但是在存储区并没有看到这个东西

所以并不存在说manifest混乱这个事情,如果有相同的package,但是有一些私有版本,verdaccio返回的始终都是合并私有包后的manifest

image image

@fangzhengjin
Copy link
Contributor Author

不管是npm还是Maven等,如果对上游仓库的公共包进行二次修改在私服发布,不覆盖公共仓库中的版本号应该是一个共识吧?所以作者怎么变根本无所谓呀,只有你单独查询你的这个私有版本的时候会返回你自己定义的manifest,但是如果你查询的是版本列表,那么以公共仓库的manifest为基础,仅仅是合并你私有的版本信息,就更没有问题了,不是吗?

对于404这个,如果公共仓库都找不到这个package,那么从本地存储中查找并返回,这个逻辑与开不开代理都保持了一致吧?怎么会混乱呢?毕竟如果不开代理模式,默认的策略不就是从本地存储查找并返回吗

@hezhengxu2018
Copy link
Collaborator

如果verdaccio的模式是这样的话其实这个问题就成了这个功能应该更像是verdaccio还是更像是nexus。nexus的代理仓库仅作代理,想发包就去hosted repository,想同时使用两个仓库就建group repository。
现在的模式还是更靠近nexus,但是要自己部署多套。应该转成verdaccio的模式吗?

@fangzhengjin
Copy link
Contributor Author

@fengmk2 有什么建议?

@fangzhengjin
Copy link
Contributor Author

如果verdaccio的模式是这样的话其实这个问题就成了这个功能应该更像是verdaccio还是更像是nexus。nexus的代理仓库仅作代理,想发包就去hosted repository,想同时使用两个仓库就建group repository。 现在的模式还是更靠近nexus,但是要自己部署多套。应该转成verdaccio的模式吗?

其实这种部署多套还可能存在一个问题,就是如果在第一层注册表里找不到,重定向到第二层注册表的时候,走的好像是302,这种在内网环境下其实不太友好,尤其是通过内网域名提供服务都情况下,本来很多机器已经配置过第一层的映射了,那么这样还需要再次添加第二层注册表的映射,对于通过IP+端口提供服务的,还需要在走一批白名单申请

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants