Skip to content

Commit

Permalink
Merge pull request #1636 from nanoc/denis/reliable-bin-write
Browse files Browse the repository at this point in the history
Let Store#store support large amounts of data
  • Loading branch information
denisdefreyne committed Dec 3, 2022
2 parents 2d05b82 + 85e0e8c commit a266603
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
27 changes: 25 additions & 2 deletions nanoc-core/lib/nanoc/core/store.rb
Expand Up @@ -128,8 +128,9 @@ def unsafe_load_uninstrumented
self.data = read_obj_from_file(data_filename)
end

def write_obj_to_file(fn, obj)
File.binwrite(fn, Marshal.dump(obj))
def write_obj_to_file(filename, obj)
data = Marshal.dump(obj)
write_data_to_file(filename, data)
end

def read_obj_from_file(fn)
Expand All @@ -143,6 +144,28 @@ def version_filename
def data_filename
"#{filename}.data.db"
end

def write_data_to_file(filename, data)
basename = File.basename(filename)
dirname = File.dirname(filename)

# Write to a temporary file first, and then (atomically) move it into
# place.
Tempfile.open(".#{basename}", dirname) do |temp_file|
temp_file.binmode

# Write the data as a stream, because File.binwrite can’t
# necessarily deal with writing that much data all at once.
#
# See https://github.com/nanoc/nanoc/issues/1635.
reader = StringIO.new(data)
IO.copy_stream(reader, temp_file)
temp_file.close

# Rename (atomic)
File.rename(temp_file.path, filename)
end
end
end
end
end
21 changes: 21 additions & 0 deletions nanoc-core/spec/nanoc/core/store_spec.rb
Expand Up @@ -109,4 +109,25 @@ def gen_hash(path)
store.load
expect(store.data).to be_nil
end

it 'can write humongous amounts of data' do
# Skip running on GitHub actions etc because this thing just uses far too many resources
skip if ENV['CI']

store = test_store_klass.new('test', 1)

# Create huge string
array = []
100.times do |i|
raw = 'x' * 1_000_037
raw << i.to_s
io = StringIO.new
100.times { io << raw }
array << io.string
end

# Write
store.data = { data: array }
expect { store.store }.not_to raise_exception
end
end

0 comments on commit a266603

Please sign in to comment.