Class: Opal::Cache::FileCache
- Inherits:
-
Object
- Object
- Opal::Cache::FileCache
- Defined in:
- opal/lib/opal/cache/file_cache.rb
Class Method Summary collapse
-
.dir_writable?(*paths) ⇒ Boolean
This complex piece of code tries to check if we can robustly mkdir_p a directory.
- .find_dir ⇒ Object
Instance Method Summary collapse
- #get(key) ⇒ Object
-
#initialize(dir: nil, max_size: nil) ⇒ FileCache
constructor
A new instance of FileCache.
- #set(key, data) ⇒ Object
Constructor Details
#initialize(dir: nil, max_size: nil) ⇒ FileCache
Returns a new instance of FileCache.
9 10 11 12 13 14 15 16 17 18 |
# File 'opal/lib/opal/cache/file_cache.rb', line 9 def initialize(dir: nil, max_size: nil) @dir = dir || self.class.find_dir # Store at most 32MB of cache - de facto this 32MB is larger, # as we don't account for inode size for instance. In fact, it's # about 50M. Also we run this check before anything runs, so things # may go up to 64M or even larger. @max_size = max_size || 32 * 1024 * 1024 tidy_up_cache end |
Class Method Details
.dir_writable?(*paths) ⇒ Boolean
This complex piece of code tries to check if we can robustly mkdir_p a directory.
82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'opal/lib/opal/cache/file_cache.rb', line 82 def self.dir_writable?(*paths) dir = nil paths = paths.reduce([]) do |a, b| [*a, dir = a.last ? File.(b, a.last) : b] end File.exist?(paths.first) && paths.reverse.all? do |i| !File.exist?(i) || (File.directory?(i) && File.writable?(i)) end dir end |
.find_dir ⇒ Object
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'opal/lib/opal/cache/file_cache.rb', line 96 def self.find_dir @find_dir ||= case # Try to write cache into a directory pointed by an environment variable if present when dir = ENV['OPAL_CACHE_DIR'] FileUtils.mkdir_p(dir) dir # Otherwise, we write to the place where Opal is installed... # I don't think it's a good location to store cache, so many things can go wrong. # when dir = dir_writable?(Opal.gem_dir, '..', 'tmp', 'cache') # FileUtils.mkdir_p(dir) # FileUtils.chmod(0o700, dir) # dir # Otherwise, ~/.cache/opal... when dir = dir_writable?(Dir.home, '.cache', 'opal') FileUtils.mkdir_p(dir) FileUtils.chmod(0o700, dir) dir # Only /tmp is writable... or isn't it? when (dir = dir_writable?('/tmp', "opal-cache-#{ENV['USER']}")) && File.sticky?('/tmp') FileUtils.mkdir_p(dir) FileUtils.chmod(0o700, dir) dir # No way... we can't write anywhere... else warn "Couldn't find a writable path to store Opal cache. " \ 'Try setting OPAL_CACHE_DIR environment variable' nil end end |
Instance Method Details
#get(key) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'opal/lib/opal/cache/file_cache.rb', line 39 def get(key) file = cache_filename_for(key) if File.exist?(file) FileUtils.touch(file) out = File.binread(file) out = Zlib.gunzip(out) Marshal.load(out) # rubocop:disable Security/MarshalLoad end rescue Zlib::GzipFile::Error nil end |
#set(key, data) ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'opal/lib/opal/cache/file_cache.rb', line 20 def set(key, data) file = cache_filename_for(key) out = Marshal.dump(data) # Sometimes `Zlib::BufError` gets raised, unsure why, makes no sense, possibly # some race condition (see https://github.com/ruby/zlib/issues/49). # Limit the number of retries to avoid infinite loops. retries = 5 begin out = Zlib.gzip(out, level: 9) rescue Zlib::BufError warn "\n[Opal]: Zlib::BufError; retrying (#{retries} retries left)" retries -= 1 retry if retries > 0 end File.binwrite(file, out) end |