class Bootsnap::LoadPathCache::Store

Constants

NestedTransactionError
SetOutsideTransactionNotAllowed

Public Class Methods

new(store_path) click to toggle source
# File lib/bootsnap/load_path_cache/store.rb, line 13
def initialize(store_path)
  @store_path = store_path
  # TODO: Remove conditional once Ruby 2.2 support is dropped.
  @txn_mutex =  defined?(::Mutex) ? ::Mutex.new : ::Thread::Mutex.new
  @dirty = false
  load_data
end

Public Instance Methods

fetch(key) { || ... } click to toggle source
# File lib/bootsnap/load_path_cache/store.rb, line 25
def fetch(key)
  raise(SetOutsideTransactionNotAllowed) unless @txn_mutex.owned?
  v = get(key)
  unless v
    @dirty = true
    v = yield
    @data[key] = v
  end
  v
end
get(key) click to toggle source
# File lib/bootsnap/load_path_cache/store.rb, line 21
def get(key)
  @data[key]
end
set(key, value) click to toggle source
# File lib/bootsnap/load_path_cache/store.rb, line 36
def set(key, value)
  raise(SetOutsideTransactionNotAllowed) unless @txn_mutex.owned?
  if value != @data[key]
    @dirty = true
    @data[key] = value
  end
end
transaction() { || ... } click to toggle source
# File lib/bootsnap/load_path_cache/store.rb, line 44
def transaction
  raise(NestedTransactionError) if @txn_mutex.owned?
  @txn_mutex.synchronize do
    begin
      yield
    ensure
      commit_transaction
    end
  end
end

Private Instance Methods

commit_transaction() click to toggle source
# File lib/bootsnap/load_path_cache/store.rb, line 57
def commit_transaction
  if @dirty
    dump_data
    @dirty = false
  end
end
dump_data() click to toggle source
# File lib/bootsnap/load_path_cache/store.rb, line 75
def dump_data
  # Change contents atomically so other processes can't get invalid
  # caches if they read at an inopportune time.
  tmp = "#{@store_path}.#{Process.pid}.#{(rand * 100000).to_i}.tmp"
  FileUtils.mkpath(File.dirname(tmp))
  exclusive_write = File::Constants::CREAT | File::Constants::EXCL | File::Constants::WRONLY
  # `encoding:` looks redundant wrt `binwrite`, but necessary on windows
  # because binary is part of mode.
  File.binwrite(tmp, MessagePack.dump(@data), mode: exclusive_write, encoding: Encoding::BINARY)
  FileUtils.mv(tmp, @store_path)
rescue Errno::EEXIST
  retry
end
load_data() click to toggle source
# File lib/bootsnap/load_path_cache/store.rb, line 64
def load_data
  @data = begin
    MessagePack.load(File.binread(@store_path))
          # handle malformed data due to upgrade incompatibility
          rescue Errno::ENOENT, MessagePack::MalformedFormatError, MessagePack::UnknownExtTypeError, EOFError
            {}
          rescue ArgumentError => e
            e.message =~ /negative array size/ ? {} : raise
  end
end