Skip to content

优化代码,增加 Ruby4 CI#245

Open
OuYangJinTing wants to merge 1 commit into
qiniu:developfrom
OuYangJinTing:develop
Open

优化代码,增加 Ruby4 CI#245
OuYangJinTing wants to merge 1 commit into
qiniu:developfrom
OuYangJinTing:develop

Conversation

@OuYangJinTing
Copy link
Copy Markdown

  • 删除 Config 中的 multi_region 选项,HostManager 始终使用多区域 hosts(单区域貌似已废弃了)
  • 调整 Auth 模块中类方法的位置,避免存在多处 class << self; ... end
  • 测试覆盖率工具由 codecov 切换为 simplecov-cobertura,codecov 已不再维护
  • 新增 base64 运行时依赖,Ruby 3.4 已经将 base64 从标准库中移除
  • CI 增加 Ruby 4.0 测试矩阵
  • 测试使用的 bucket 支持通过环境变量配置

- 删除 Config 中的 multi_region 选项,HostManager 始终使用多区域 hosts
- 调整 Auth 模块中类方法的位置,避免存在多处 `class << self; ... end`
- 测试覆盖率工具由 codecov 切换为 simplecov-cobertura,codecov 已不再维护
- 新增 base64 运行时依赖,Ruby 3.4 已经将 base64 从标准库中移除
- CI 增加 Ruby 4.0 测试矩阵
- 测试使用的 bucket 支持通过环境变量配置
@OuYangJinTing OuYangJinTing changed the title 优化代码,增加 ruby4 ci 优化代码,增加 Ruby4 CI May 11, 2026
Copy link
Copy Markdown

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

Choose a reason for hiding this comment

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

Code Review

This pull request removes the multi_region configuration flag, making multi-region support the default behavior across the SDK. Key changes include refactoring HostManager to remove conditional logic, updating gemspec dependencies (adding base64 and transitioning to simplecov-cobertura), and modernizing the test suite to use environment-defined bucket names. Feedback identifies several reliability issues in the refactored HostManager methods, specifically the removal of bucket presence checks and the use of fragile inline rescue logic, which could lead to NoMethodError or unhandled exceptions if API responses are incomplete.

Comment thread lib/qiniu/host_manager.rb
Comment on lines 15 to 18
def up_host(bucket, opts = {})
if !multi_region_support?
"#{extract_protocol(opts)}://up.qiniup.com"
elsif bucket
host = hosts(bucket)
"#{extract_protocol(opts)}://" + host.dig('up', 'acc', 'main', 0) rescue "#{extract_protocol(opts)}://" + host.dig('up', 'src', 'main', 0)
end
host = hosts(bucket)
"#{extract_protocol(opts)}://" + host.dig('up', 'acc', 'main', 0) rescue "#{extract_protocol(opts)}://" + host.dig('up', 'src', 'main', 0)
end
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

移除 bucket 检查并简化逻辑引入了回归风险和潜在的运行时错误:

  1. 回归风险:以前如果 bucketnil,该方法会返回 nil。现在它会调用 hosts(nil),这可能会触发 API 错误并抛出异常。
  2. 脆弱的 Rescue 逻辑:行内的 rescue 仅能处理第一个 dig 返回 nil 时(导致与字符串相加产生 TypeError)的情况。如果第二个 dig 也返回 nil,产生的 TypeError 将不会被捕获,从而导致程序崩溃。
  3. 健壮性:建议使用字符串插值并提供显式的回退逻辑,这样更安全且代码意图更清晰。
    def up_host(bucket, opts = {})
      return nil if bucket.nil?
      host = hosts(bucket)
      up_host = host.dig('up', 'acc', 'main', 0) || host.dig('up', 'src', 'main', 0)
      "#{extract_protocol(opts)}://#{up_host}" if up_host
    end

Comment thread lib/qiniu/host_manager.rb
Comment on lines 20 to 23
def fetch_host(bucket, opts = {})
if !multi_region_support?
"#{extract_protocol(opts)}://iovip.qbox.me"
elsif bucket
host = hosts(bucket)
"#{extract_protocol(opts)}://" + host.dig('io', 'acc', 'main', 0) rescue "#{extract_protocol(opts)}://" + host.dig('io', 'src', 'main', 0)
end
host = hosts(bucket)
"#{extract_protocol(opts)}://" + host.dig('io', 'acc', 'main', 0) rescue "#{extract_protocol(opts)}://" + host.dig('io', 'src', 'main', 0)
end
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

up_host 类似,此方法现在缺少对 bucket 是否为 nil 的检查,并且使用了脆弱的 rescue 逻辑。如果 API 响应中同时缺少 accsrc 主机配置,程序将会崩溃。

    def fetch_host(bucket, opts = {})
      return nil if bucket.nil?
      host = hosts(bucket)
      fetch_host = host.dig('io', 'acc', 'main', 0) || host.dig('io', 'src', 'main', 0)
      "#{extract_protocol(opts)}://#{fetch_host}" if fetch_host
    end

Comment thread lib/qiniu/host_manager.rb
Comment on lines 25 to 31
def up_hosts(bucket, opts = {})
if multi_region_support?
host = hosts(bucket)['up']
multi_region_hosts = []
multi_region_hosts |= host.dig('acc', 'main') || []
multi_region_hosts |= host.dig('src', 'main') || []
return multi_region_hosts
else
raise 'HostManager#up_hosts: multi_region must be enabled'
end
host = hosts(bucket)['up']
up_hosts = []
up_hosts |= host.dig('acc', 'main') || []
up_hosts |= host.dig('src', 'main') || []
up_hosts
end
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

如果 hosts(bucket) 的响应不包含 'up' 键,或者 bucketnil,此方法会抛出 NoMethodError(因为 hostnil)。建议增加卫语句并为 host 变量提供默认的空哈希以提高代码的健壮性。

    def up_hosts(bucket, opts = {})
      return [] if bucket.nil?
      host = hosts(bucket)['up'] || {}
      up_hosts = []
      up_hosts |= host.dig('acc', 'main') || []
      up_hosts |= host.dig('src', 'main') || []
      up_hosts
    end

Comment thread lib/qiniu/host_manager.rb
Comment on lines 33 to 35
def global(bucket, opts = {})
if multi_region_support?
!!hosts(bucket)['global']
else
raise 'HostManager#global: multi_region must be enabled'
end
!!hosts(bucket)['global']
end
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

建议为 bucket 增加卫语句,以避免在缺少存储桶名称时进行不必要的 API 调用,并防止潜在的异常抛出。

    def global(bucket, opts = {})
      return false if bucket.nil?
      !!hosts(bucket)['global']
    end

Copy link
Copy Markdown

@fennoai fennoai Bot left a comment

Choose a reason for hiding this comment

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

Found 3 issues after code quality, performance, security, and documentation review. Two are behavioral regressions (HostManager nil-bucket handling and a brittle integration assertion), and one is a documentation/CI mismatch in the coverage upload step.

Comment thread lib/qiniu/host_manager.rb
host = hosts(bucket)
"#{extract_protocol(opts)}://" + host.dig('up', 'acc', 'main', 0) rescue "#{extract_protocol(opts)}://" + host.dig('up', 'src', 'main', 0)
end
host = hosts(bucket)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

up_host and fetch_host used to short-circuit when bucket was nil (elsif bucket in the old implementation). After this change they always call hosts(bucket), so Config.up_host(nil)/fetch_host(nil) now issues a UC query with an empty bucket and raises Host query is failed instead of returning nil (or the legacy fixed host when multi_region was disabled). Since these methods are public API, this is a breaking behavior change unless you add an explicit guard or raise a clearer argument error.

BUCKET_NA0: ${{ secrets.BUCKET_NA0 }}
BUCKET_BC: ${{ secrets.BUCKET_BC }}

- name: After_success
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The PR switches the test stack from codecov to simplecov-cobertura, but CI still runs bash <(curl -s https://codecov.io/bash). That means the workflow still depends on the deprecated Codecov uploader, and the newly generated Cobertura report is not actually consumed anywhere. If the intent is to stop relying on Codecov, this step needs to be updated or removed as part of the same change.

Comment thread spec/qiniu/auth_spec.rb
pp = Auth::PutPolicy.new(@bucket, key)
expect(pp.instance_variable_get(:@global)).to be false
uphosts = pp.instance_variable_get(:@uphosts)
expect(uphosts.size).to eq 2
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This assertion hard-codes the host list size to exactly 2 even though the API contract here is really “contains at least one upload-* host and one up-* host.” If UC starts returning additional upload endpoints for the bucket, the test will fail even though the SDK behavior is still correct. Dropping the exact-size check would make this integration spec much less brittle.

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.

1 participant