From 7180e178b317ca2eca510e304def03855eb8253b Mon Sep 17 00:00:00 2001 From: Thierry Deo Date: Fri, 24 Feb 2023 15:02:30 +0100 Subject: [PATCH] Implement cache in schema loading --- lib/committee/drivers.rb | 30 +++++++++++++++++++++++------- test/drivers_test.rb | 29 +++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/lib/committee/drivers.rb b/lib/committee/drivers.rb index 6b19142c..f48c5ddc 100644 --- a/lib/committee/drivers.rb +++ b/lib/committee/drivers.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require 'digest' + module Committee module Drivers # Gets a driver instance from the specified name. Raises ArgumentError for @@ -36,13 +38,16 @@ def self.load_from_yaml(schema_path, parser_options: {}) # @param [String] schema_path # @return [Committee::Driver] def self.load_from_file(schema_path, parser_options: {}) - case File.extname(schema_path) - when '.json' - load_from_json(schema_path, parser_options: parser_options) - when '.yaml', '.yml' - load_from_yaml(schema_path, parser_options: parser_options) - else - raise "Committee only supports the following file extensions: '.json', '.yaml', '.yml'" + @__load_from_file_cache ||= {} + @__load_from_file_cache[cache_key(schema_path, parser_options)] ||= begin + case File.extname(schema_path) + when '.json' + load_from_json(schema_path, parser_options: parser_options) + when '.yaml', '.yml' + load_from_yaml(schema_path, parser_options: parser_options) + else + raise "Committee only supports the following file extensions: '.json', '.yaml', '.yml'" + end end end @@ -74,6 +79,17 @@ def self.load_from_data(hash, schema_path = nil, parser_options: {}) # TODO: in the future, pass `opts` here and allow optionality in other drivers? driver.parse(hash) end + + class << self + private + + def cache_key(schema_path, parser_options) + [ + File.exist?(schema_path) ? Digest::MD5.hexdigest(File.read(schema_path)) : nil, + parser_options.hash, + ].join('_') + end + end end end diff --git a/test/drivers_test.rb b/test/drivers_test.rb index 2df356d0..fbe0e9d9 100644 --- a/test/drivers_test.rb +++ b/test/drivers_test.rb @@ -67,6 +67,35 @@ end assert_equal "Committee only supports the following file extensions: '.json', '.yaml', '.yml'", e.message end + + describe 'cache behavior' do + describe 'when loading the same file' do + it 'returns the same object when the options are identical' do + assert_equal( + Committee::Drivers.load_from_file(open_api_3_schema_path, parser_options:{strict_reference_validation: true}).object_id, + Committee::Drivers.load_from_file(open_api_3_schema_path, parser_options:{strict_reference_validation: true}).object_id, + ) + end + + it 'returns different objects if the options are different' do + refute_equal( + Committee::Drivers.load_from_file(open_api_3_schema_path, parser_options:{strict_reference_validation: true}).object_id, + Committee::Drivers.load_from_file(open_api_3_schema_path, parser_options:{strict_reference_validation: false}).object_id, + ) + end + + it 'returns different objects if the file contents have changed' do + object_id = Committee::Drivers.load_from_file(open_api_3_schema_path, parser_options:{strict_reference_validation: true}).object_id + original_file_contents = File.read(open_api_3_schema_path) + File.write(open_api_3_schema_path, original_file_contents + "\n") + refute_equal( + Committee::Drivers.load_from_file(open_api_3_schema_path, parser_options:{strict_reference_validation: true}).object_id, + object_id, + ) + File.write(open_api_3_schema_path, original_file_contents) + end + end + end end describe 'load_from_json(schema_path)' do