Skip to content

Commit bd2ee06

Browse files
committed
cache maven requests
1 parent 544141e commit bd2ee06

4 files changed

Lines changed: 59 additions & 13 deletions

File tree

packages/react-native/scripts/cocoapods/rncore.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ def self.nightly_tarball_url(version, configuration, dsyms = false)
371371
artefact_name = "reactnative-core-#{dsyms ? "dSYM-" : ""}#{configuration ? configuration : "debug"}.tar.gz"
372372
xml_url = "https://central.sonatype.com/repository/maven-snapshots/com/facebook/react/#{artefact_coordinate}/#{version}-SNAPSHOT/maven-metadata.xml"
373373

374-
response = Net::HTTP.get_response(URI(xml_url))
374+
response = ReactNativePodsUtils.memoized_get_response(xml_url)
375375
if response.is_a?(Net::HTTPSuccess)
376376
xml = REXML::Document.new(response.body)
377377
timestamp = xml.elements['metadata/versioning/snapshot/timestamp'].text
@@ -476,11 +476,11 @@ def self.artifacts_dir()
476476
return File.join(Pod::Config.instance.project_pods_root, "ReactNativeCore-artifacts")
477477
end
478478

479-
# This function checks that ReactNativeCore artifact exists on the maven repo
479+
# This function checks that ReactNativeCore artifact exists on the maven repo.
480+
# The probe is memoized, so repeated podspec evaluations in one `pod install`
481+
# don't re-request the same URL.
480482
def self.artifact_exists(tarball_url)
481-
# -L is used to follow redirects, useful for the nightlies
482-
# I also needed to wrap the url in quotes to avoid escaping & and ?.
483-
return (`curl -o /dev/null --silent -Iw '%{http_code}' -L "#{tarball_url}"` == "200")
483+
return ReactNativePodsUtils.artifact_exists?(tarball_url)
484484
end
485485

486486
def self.rncore_log(message, level = :info)

packages/react-native/scripts/cocoapods/rndependencies.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ def self.nightly_tarball_url(version, build_type)
248248
artifact_name = "reactnative-dependencies-#{build_type.to_s}.tar.gz"
249249
xml_url = "https://central.sonatype.com/repository/maven-snapshots/com/facebook/react/#{artifact_coordinate}/#{version}-SNAPSHOT/maven-metadata.xml"
250250

251-
response = Net::HTTP.get_response(URI(xml_url))
251+
response = ReactNativePodsUtils.memoized_get_response(xml_url)
252252
if response.is_a?(Net::HTTPSuccess)
253253
xml = REXML::Document.new(response.body)
254254
timestamp = xml.elements['metadata/versioning/snapshot/timestamp'].text
@@ -378,11 +378,11 @@ def self.artifacts_dir()
378378
return File.join(Pod::Config.instance.project_pods_root, "ReactNativeDependencies-artifacts")
379379
end
380380

381-
# This function checks that ReactNativeDependencies artifact exists on the maven repo
381+
# This function checks that ReactNativeDependencies artifact exists on the maven repo.
382+
# The probe is memoized, so repeated podspec evaluations in one `pod install`
383+
# don't re-request the same URL.
382384
def self.artifact_exists(tarball_url)
383-
# -L is used to follow redirects, useful for the nightlies
384-
# I also needed to wrap the url in quotes to avoid escaping & and ?.
385-
return (`curl -o /dev/null --silent -Iw '%{http_code}' -L "#{tarball_url}"` == "200")
385+
return ReactNativePodsUtils.artifact_exists?(tarball_url)
386386
end
387387

388388
def self.rndeps_log(message, level = :info)

packages/react-native/scripts/cocoapods/utils.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
require 'shellwords'
77
require 'digest'
88
require 'uri'
9+
require 'net/http'
910

1011
require_relative "./helpers.rb"
1112
require_relative "./jsengine.rb"
@@ -757,6 +758,38 @@ def self.resolve_use_frameworks(spec, header_mappings_dir: nil, module_name: nil
757758
end
758759
end
759760

761+
# ============================ #
762+
# Network request memoization #
763+
# ============================ #
764+
# CocoaPods evaluates the prebuilt podspecs several times during a single
765+
# `pod install`, and every evaluation re-resolves the artifact URLs from
766+
# scratch: existence probes against the mirror/Maven Central and nightly
767+
# metadata lookups. The answers should not change within one install, so
768+
# each request is issued at most once per process and then served from
769+
# these in-memory caches.
770+
@@artifact_exists_cache = {}
771+
@@get_response_cache = {}
772+
773+
# Memoized existence probe (HTTP HEAD) for a prebuilt artifact URL.
774+
def self.artifact_exists?(tarball_url)
775+
unless @@artifact_exists_cache.key?(tarball_url)
776+
# -L is used to follow redirects, useful for the nightlies
777+
# The url is wrapped in quotes to avoid escaping & and ?.
778+
@@artifact_exists_cache[tarball_url] = (`curl -o /dev/null --silent -Iw '%{http_code}' -L "#{tarball_url}"` == "200")
779+
end
780+
return @@artifact_exists_cache[tarball_url]
781+
end
782+
783+
# Memoized HTTP GET for small metadata lookups (Maven snapshot metadata).
784+
# Returns the Net::HTTPResponse. Raised network errors are not cached, so
785+
# a later call can retry.
786+
def self.memoized_get_response(url)
787+
unless @@get_response_cache.key?(url)
788+
@@get_response_cache[url] = Net::HTTP.get_response(URI(url))
789+
end
790+
return @@get_response_cache[url]
791+
end
792+
760793
# ==================== #
761794
# Shared download cache #
762795
# ==================== #

packages/react-native/sdks/hermes-engine/hermes-utils.rb

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010
MAVEN_CENTRAL_REPOSITORY = "https://repo1.maven.org/maven2"
1111
REACT_NATIVE_MAVEN_MIRROR_REPOSITORY = "https://repo.reactnative.dev/maven2"
1212

13+
# Memoized results of requests to the Maven repositories (mirror or central).
14+
# hermes-engine.podspec is evaluated several times during a single
15+
# `pod install`, and every evaluation re-resolves the artifact source from
16+
# scratch; without memoization that re-issues identical artifact existence
17+
# probes. The answers should not change within one install, so each request
18+
# is issued at most once per process.
19+
HERMES_ARTIFACT_EXISTS_CACHE = {}
20+
1321
module HermesEngineSourceType
1422
LOCAL_PREBUILT_TARBALL = :local_prebuilt_tarball
1523
DOWNLOAD_PREBUILD_RELEASE_TARBALL = :download_prebuild_release_tarball
@@ -339,14 +347,19 @@ def resolve_url_redirects(url)
339347

340348
# This function checks that Hermes artifact exists.
341349
# As of now it should check it on the Maven repo.
350+
# The probe is memoized, so repeated podspec evaluations in one `pod install`
351+
# don't re-request the same URL.
342352
#
343353
# Parameters
344354
# - version: the version of React Native
345355
# - build_type: debug or release
346356
def hermes_artifact_exists(tarball_url)
347-
# -L is used to follow redirects, useful for the nightlies
348-
# I also needed to wrap the url in quotes to avoid escaping & and ?.
349-
return (`curl -o /dev/null --silent -Iw '%{http_code}' -L "#{tarball_url}"` == "200")
357+
unless HERMES_ARTIFACT_EXISTS_CACHE.key?(tarball_url)
358+
# -L is used to follow redirects, useful for the nightlies
359+
# I also needed to wrap the url in quotes to avoid escaping & and ?.
360+
HERMES_ARTIFACT_EXISTS_CACHE[tarball_url] = (`curl -o /dev/null --silent -Iw '%{http_code}' -L "#{tarball_url}"` == "200")
361+
end
362+
return HERMES_ARTIFACT_EXISTS_CACHE[tarball_url]
350363
end
351364

352365
def hermes_log(message, level = :warning)

0 commit comments

Comments
 (0)