Introduce Formulary platform cache

This commit is contained in:
Bo Anderson 2024-01-09 11:12:49 +00:00
parent 5b9f8b6269
commit 310b5ecbe7
No known key found for this signature in database
5 changed files with 28 additions and 23 deletions

View File

@ -64,7 +64,6 @@ module Homebrew
os_arch_combinations.each do |os, arch| os_arch_combinations.each do |os, arch|
SimulateSystem.with os: os, arch: arch do SimulateSystem.with os: os, arch: arch do
Formulary.clear_cache
formula = Formulary.factory(ref) formula = Formulary.factory(ref)
print_formula_cache(formula, os: os, arch: arch, args: args) print_formula_cache(formula, os: os, arch: arch, args: args)
end end

View File

@ -99,7 +99,6 @@ module Homebrew
os_arch_combinations.each do |os, arch| os_arch_combinations.each do |os, arch|
SimulateSystem.with os: os, arch: arch do SimulateSystem.with os: os, arch: arch do
Formulary.clear_cache
formula = Formulary.factory(ref, args.HEAD? ? :head : :stable) formula = Formulary.factory(ref, args.HEAD? ? :head : :stable)
formula.print_tap_action verb: "Fetching" formula.print_tap_action verb: "Fetching"

View File

@ -205,8 +205,6 @@ module Homebrew
spdx_license_data = SPDX.license_data spdx_license_data = SPDX.license_data
spdx_exception_data = SPDX.exception_data spdx_exception_data = SPDX.exception_data
clear_formulary_cache = [args.os, args.arch].any?
formula_problems = audit_formulae.sort.each_with_object({}) do |f, problems| formula_problems = audit_formulae.sort.each_with_object({}) do |f, problems|
path = f.path path = f.path
@ -228,8 +226,6 @@ module Homebrew
SimulateSystem.with os: os, arch: arch do SimulateSystem.with os: os, arch: arch do
odebug "Auditing Formula #{f} on os #{os} and arch #{arch}" odebug "Auditing Formula #{f} on os #{os} and arch #{arch}"
Formulary.clear_cache if clear_formulary_cache
audit_proc = proc { FormulaAuditor.new(Formulary.factory(path), **options).tap(&:audit) } audit_proc = proc { FormulaAuditor.new(Formulary.factory(path), **options).tap(&:audit) }
# Audit requires full Ruby source so disable API. # Audit requires full Ruby source so disable API.

View File

@ -1,7 +1,7 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "digest/md5" require "digest/sha2"
require "extend/cachable" require "extend/cachable"
require "tab" require "tab"
require "utils/bottles" require "utils/bottles"
@ -32,24 +32,28 @@ module Formulary
!@factory_cache.nil? !@factory_cache.nil?
end end
def self.platform_cache
cache["#{Homebrew::SimulateSystem.current_os}_#{Homebrew::SimulateSystem.current_arch}"] ||= {}
end
def self.formula_class_defined_from_path?(path) def self.formula_class_defined_from_path?(path)
cache.key?(:path) && cache[:path].key?(path) platform_cache.key?(:path) && platform_cache[:path].key?(path)
end end
def self.formula_class_defined_from_api?(name) def self.formula_class_defined_from_api?(name)
cache.key?(:api) && cache[:api].key?(name) platform_cache.key?(:api) && platform_cache[:api].key?(name)
end end
def self.formula_class_get_from_path(path) def self.formula_class_get_from_path(path)
cache[:path].fetch(path) platform_cache[:path].fetch(path)
end end
def self.formula_class_get_from_api(name) def self.formula_class_get_from_api(name)
cache[:api].fetch(name) platform_cache[:api].fetch(name)
end end
def self.clear_cache def self.clear_cache
cache.each do |type, cached_objects| platform_cache.each do |type, cached_objects|
next if type == :formulary_factory next if type == :formulary_factory
cached_objects.each_value do |klass| cached_objects.each_value do |klass|
@ -126,21 +130,28 @@ module Formulary
end end
end end
sig { params(identifier: String).returns(String) }
def self.namespace_key(identifier)
Digest::SHA2.hexdigest(
"#{Homebrew::SimulateSystem.current_os}_#{Homebrew::SimulateSystem.current_arch}:#{identifier}",
)
end
sig { sig {
params(name: String, path: Pathname, flags: T::Array[String], ignore_errors: T::Boolean) params(name: String, path: Pathname, flags: T::Array[String], ignore_errors: T::Boolean)
.returns(T.class_of(Formula)) .returns(T.class_of(Formula))
} }
def self.load_formula_from_path(name, path, flags:, ignore_errors:) def self.load_formula_from_path(name, path, flags:, ignore_errors:)
contents = path.open("r") { |f| ensure_utf8_encoding(f).read } contents = path.open("r") { |f| ensure_utf8_encoding(f).read }
namespace = "FormulaNamespace#{Digest::MD5.hexdigest(path.to_s)}" namespace = "FormulaNamespace#{namespace_key(path.to_s)}"
klass = load_formula(name, path, contents, namespace, flags: flags, ignore_errors: ignore_errors) klass = load_formula(name, path, contents, namespace, flags: flags, ignore_errors: ignore_errors)
cache[:path] ||= {} platform_cache[:path] ||= {}
cache[:path][path] = klass platform_cache[:path][path] = klass
end end
sig { params(name: String, flags: T::Array[String]).returns(T.class_of(Formula)) } sig { params(name: String, flags: T::Array[String]).returns(T.class_of(Formula)) }
def self.load_formula_from_api(name, flags:) def self.load_formula_from_api(name, flags:)
namespace = :"FormulaNamespaceAPI#{Digest::MD5.hexdigest(name)}" namespace = :"FormulaNamespaceAPI#{namespace_key(name)}"
mod = Module.new mod = Module.new
remove_const(namespace) if const_defined?(namespace) remove_const(namespace) if const_defined?(namespace)
@ -396,8 +407,8 @@ module Formulary
klass = T.cast(klass, T.class_of(Formula)) klass = T.cast(klass, T.class_of(Formula))
mod.const_set(class_name, klass) mod.const_set(class_name, klass)
cache[:api] ||= {} platform_cache[:api] ||= {}
cache[:api][name] = klass platform_cache[:api][name] = klass
end end
sig { params(name: String, spec: Symbol, force_bottle: T::Boolean, flags: T::Array[String]).returns(Formula) } sig { params(name: String, spec: Symbol, force_bottle: T::Boolean, flags: T::Array[String]).returns(Formula) }
@ -721,7 +732,9 @@ module Formulary
ignore_errors: T.unsafe(nil) ignore_errors: T.unsafe(nil)
) )
cache_key = "#{ref}-#{spec}-#{alias_path}-#{from}" cache_key = "#{ref}-#{spec}-#{alias_path}-#{from}"
return cache[:formulary_factory][cache_key] if factory_cached? && cache[:formulary_factory]&.key?(cache_key) if factory_cached? && platform_cache[:formulary_factory]&.key?(cache_key)
return platform_cache[:formulary_factory][cache_key]
end
loader_options = { from: from, warn: warn }.compact loader_options = { from: from, warn: warn }.compact
formula_options = { alias_path: alias_path, formula_options = { alias_path: alias_path,
@ -732,8 +745,8 @@ module Formulary
.get_formula(spec, **formula_options) .get_formula(spec, **formula_options)
if factory_cached? if factory_cached?
cache[:formulary_factory] ||= {} platform_cache[:formulary_factory] ||= {}
cache[:formulary_factory][cache_key] ||= formula platform_cache[:formulary_factory][cache_key] ||= formula
end end
formula formula

View File

@ -97,8 +97,6 @@ class TestRunnerFormula
end end
with_env(HOMEBREW_EVAL_ALL: eval_all_env) do with_env(HOMEBREW_EVAL_ALL: eval_all_env) do
Formulary.clear_cache
os = macos_version || platform os = macos_version || platform
arch = SIMULATE_SYSTEM_SYMBOLS.fetch(arch) arch = SIMULATE_SYSTEM_SYMBOLS.fetch(arch)