Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: myronmarston/vcr
...
head fork: myronmarston/vcr
Checking mergeability… Don't worry, you can still create the pull request.
  • 4 commits
  • 7 files changed
  • 0 commit comments
  • 1 contributor
Commits on Dec 03, 2011
@myronmarston Fix spec to match method name. 2394ca6
@myronmarston Refactor to use a Cassette::Cache interface.
Note that the cache is not yet implemented--it currently just delegates to the file system.  But this gives us the interface that we want.
7304205
@myronmarston Started implementing cassette cache. 70ca447
@myronmarston First pass at pre-caching the cassettes. 0fc42e7
View
5 lib/vcr.rb
@@ -1,6 +1,7 @@
require 'vcr/util/variable_args_block_caller'
require 'vcr/cassette'
+require 'vcr/cassette/cache'
require 'vcr/cassette/serializers'
require 'vcr/configuration'
require 'vcr/deprecations'
@@ -89,6 +90,10 @@ def cassette_serializers
@cassette_serializers ||= Cassette::Serializers.new
end
+ def cassette_cache
+ @cassette_cache ||= Cassette::Cache.new
+ end
+
def configuration
@configuration ||= Configuration.new
end
View
9 lib/vcr/cassette.rb
@@ -44,7 +44,7 @@ def eject
end
def previously_recorded_interactions
- @previously_recorded_interactions ||= if file && File.size?(file)
+ @previously_recorded_interactions ||= if file && VCR.cassette_cache.exists_with_content?(file)
deserialized_hash['http_interactions'].map { |h| HTTPInteraction.from_hash(h) }.tap do |interactions|
invoke_hook(:before_playback, interactions)
@@ -89,7 +89,7 @@ def update_content_length_header?
def recording?
case record_mode
when :none; false
- when :once; file.nil? || !File.size?(file)
+ when :once; file.nil? || !VCR.cassette_cache.exists_with_content?(file)
else true
end
end
@@ -116,7 +116,6 @@ def raise_error_unless_valid_record_mode
def should_re_record?
return false unless @re_record_interval
return false unless earliest_interaction_recorded_at
- return false unless File.exist?(file)
return false unless InternetConnection.available?
earliest_interaction_recorded_at + @re_record_interval < Time.now
@@ -163,9 +162,7 @@ def write_recorded_interactions_to_disk
hash = serializable_hash
return if hash["http_interactions"].none?
- directory = File.dirname(file)
- FileUtils.mkdir_p directory unless File.exist?(directory)
- File.open(file, 'w') { |f| f.write @serializer.serialize(hash) }
+ VCR.cassette_cache[file] = @serializer.serialize(hash)
end
def invoke_hook(type, interactions)
View
62 lib/vcr/cassette/cache.rb
@@ -0,0 +1,62 @@
+require 'thread'
+
+module VCR
+ class Cassette
+ class Cache
+ def initialize
+ @files = Hash.new do |files, file_name|
+ files[file_name] = File.exist?(file_name) ?
+ File.read(file_name) :
+ nil
+ end
+
+ @mutex = Mutex.new
+ @file_queue = Queue.new
+ end
+
+ def [](file_name)
+ @mutex.synchronize do
+ @files[file_name]
+ end
+ end
+
+ def exists_with_content?(file_name)
+ @mutex.synchronize do
+ @files[file_name].to_s.size > 0
+ end
+ end
+
+ # TODO: test me
+ def []=(file_name, content)
+ directory = File.dirname(file_name)
+ FileUtils.mkdir_p directory unless File.exist?(directory)
+ File.open(file_name, 'w') { |f| f.write content }
+
+ @mutex.synchronize do
+ @files[file_name] = content
+ end
+ end
+
+ def prefetch_from(directory)
+ @threads = 20.times.map do
+ Thread.new do
+ loop do
+ file_name = @file_queue.pop
+ break if file_name == :exit
+ @mutex.synchronize do
+ @files[file_name] = File.read(file_name)
+ end
+ end
+ end
+ end
+
+ Dir["#{directory}/**/*.yml"].each do |file_name|
+ @file_queue << file_name
+ end
+
+ 20.times { @file_queue << :exit }
+ end
+ end
+ end
+end
+
View
2  lib/vcr/cassette/reader.rb
@@ -33,7 +33,7 @@ def erb_variables
end
def file_content
- @file_content ||= File.read(@file_name)
+ @file_content ||= VCR.cassette_cache[@file_name]
end
def template
View
1  lib/vcr/configuration.rb
@@ -25,6 +25,7 @@ def initialize
def cassette_library_dir=(cassette_library_dir)
@cassette_library_dir = cassette_library_dir
FileUtils.mkdir_p(cassette_library_dir) if cassette_library_dir
+ VCR.cassette_cache.prefetch_from(cassette_library_dir)
end
attr_reader :default_cassette_options
View
69 spec/vcr/cassette/cache_spec.rb
@@ -0,0 +1,69 @@
+require 'vcr/cassette/cache'
+
+module VCR
+ class Cassette
+ describe Cache do
+ describe "#[]" do
+ let(:content) { "the file content" }
+ let(:file_name) { "file.yml" }
+
+ it 'only reads the file once' do
+ File.stub(:exist?).with(file_name).and_return(true)
+ File.should_receive(:read).with(file_name).once.and_return(content)
+ subject[file_name].should eq(content)
+ subject[file_name].should eq(content)
+ subject[file_name].should eq(content)
+ end
+ end
+
+ describe "#exists_with_content?" do
+ context 'when the file exists with no content' do
+ let(:file_name) { "zero_bytes.yml" }
+
+ before(:each) do
+ File.stub(:exist?).with(file_name).and_return(true)
+ File.stub(:read).with(file_name).and_return("")
+ end
+
+ it 'returns false' do
+ subject.exists_with_content?(file_name).should be_false
+ end
+
+ it 'does not read the file multiple times' do
+ File.should_receive(:read).once
+ subject.exists_with_content?(file_name)
+ subject.exists_with_content?(file_name)
+ subject.exists_with_content?(file_name)
+ end
+
+ it "does not check for the file's existence multiple times" do
+ File.should_receive(:exist?).once
+ subject.exists_with_content?(file_name)
+ subject.exists_with_content?(file_name)
+ subject.exists_with_content?(file_name)
+ end
+ end
+
+ context 'when the file does not exist' do
+ let(:file_name) { "non_existant_file.yml" }
+
+ it 'returns false' do
+ subject.exists_with_content?(file_name).should be_false
+ end
+
+ it 'does not attempt to read the file' do
+ File.should_not_receive(:read)
+ subject.exists_with_content?(file_name)
+ end
+
+ it "does not check for the file's existence multiple times" do
+ File.should_receive(:exist?).once.with(file_name).and_return(false)
+ subject.exists_with_content?(file_name)
+ subject.exists_with_content?(file_name)
+ subject.exists_with_content?(file_name)
+ end
+ end
+ end
+ end
+ end
+end
View
9 spec/vcr_spec.rb
@@ -157,13 +157,20 @@ def insert_cassette(name = :cassette_test)
end
end
- describe '.serializers' do
+ describe '.cassette_serializers' do
it 'always returns the same memoized cassette serializers instance' do
VCR.cassette_serializers.should be_a(VCR::Cassette::Serializers)
VCR.cassette_serializers.should be(VCR.cassette_serializers)
end
end
+ describe '.cassette_cache' do
+ it 'always returns the same memoized cassette cache instance' do
+ VCR.cassette_cache.should be_a(VCR::Cassette::Cache)
+ VCR.cassette_cache.should be(VCR.cassette_cache)
+ end
+ end
+
describe '.configuration' do
it 'returns the configuration object' do
VCR.configuration.should be_a(VCR::Configuration)

No commit comments for this range

Something went wrong with that request. Please try again.