Skip to content

Commit

Permalink
cache search network calls
Browse files Browse the repository at this point in the history
  • Loading branch information
brettfo committed Dec 5, 2023
1 parent f3548ca commit 26f1b0a
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 5 deletions.
22 changes: 17 additions & 5 deletions nuget/lib/dependabot/nuget/file_parser/project_file_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ def self.dependency_set_cache
CacheManager.cache("project_file_dependency_set")
end

def self.dependency_url_search_cache
CacheManager.cache("dependency_url_search_cache")
end

def initialize(dependency_files:, credentials:)
@dependency_files = dependency_files
@credentials = credentials
Expand Down Expand Up @@ -285,11 +289,8 @@ def dependency_has_search_results?(dependency)
if dependency_urls.empty?
dependency_urls = [UpdateChecker::RepositoryFinder.get_default_repository_details(dependency.name)]
end
dependency_urls_with_package = dependency_urls.select do |u|
response = Dependabot::RegistryClient.get(
url: u.fetch(:search_url),
headers: u.fetch(:auth_header)
)
dependency_urls_with_package = dependency_urls.select do |dependency_url|
response = execute_search_for_dependency_url(dependency_url)
next unless response.status == 200

body = JSON.parse(response.body)
Expand All @@ -303,6 +304,17 @@ def dependency_has_search_results?(dependency)
dependency_urls_with_package.any?
end

def execute_search_for_dependency_url(dependency_url)
search_url = dependency_url.fetch(:search_url)
cache = ProjectFileParser.dependency_url_search_cache
cache[search_url] ||= Dependabot::RegistryClient.get(
url: search_url,
headers: dependency_url.fetch(:auth_header)
)

cache[search_url]
end

def dependency_name(dependency_node, project_file)
raw_name = get_attribute_value(dependency_node, "Include") ||
get_attribute_value(dependency_node, "Update")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,63 @@ def dependencies_from(dep_info)
)
end
end

describe "multiple dependencies, but each search URI is only hit once" do
let(:file_body) do
<<~XML
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyModel_cached" Version="1.1.1" />
<ProjectReference Include="my2.csproj" />
</ItemGroup>
</Project>
XML
end
let(:file) do
Dependabot::DependencyFile.new(name: "my.csproj", content: file_body)
end
let(:file_2_body) do
<<~XML
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyModel_cached" Version="1.1.1" />
</ItemGroup>
</Project>
XML
end
let(:file2) do
Dependabot::DependencyFile.new(name: "my2.csproj", content: file_2_body)
end
let(:parser) { described_class.new(dependency_files: [file, file2], credentials: credentials) }

before do
stub_no_search_results("this.dependency.does.not.exist")
end

it "has the right details" do
query_stub = stub_search_results_with_versions("microsoft.extensions.dependencymodel_cached",
["1.1.1", "1.1.0"])
expect(top_level_dependencies.count).to eq(1)
expect(top_level_dependencies.first).to be_a(Dependabot::Dependency)
expect(top_level_dependencies.first.name).to eq("Microsoft.Extensions.DependencyModel_cached")
expect(top_level_dependencies.first.version).to eq("1.1.1")
expect(top_level_dependencies.first.requirements).to eq(
[{
requirement: "1.1.1",
file: "my.csproj",
groups: ["dependencies"],
source: nil
}]
)
expect(WebMock::RequestRegistry.instance.times_executed(query_stub.request_pattern)).to eq(1)
end
end
end
end

Expand Down

0 comments on commit 26f1b0a

Please sign in to comment.