Class: Opal::Cache::FileCache

Inherits:
Object
  • Object
show all
Defined in:
opal/lib/opal/cache/file_cache.rb

Class Method Summary collapse

Instance Method Summary collapse

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.

Returns:

  • (Boolean)


71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'opal/lib/opal/cache/file_cache.rb', line 71

def self.dir_writable?(*paths)
  dir = nil
  paths = paths.reduce([]) do |a, b|
    [*a, dir = a.last ? File.expand_path(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_dirObject



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'opal/lib/opal/cache/file_cache.rb', line 85

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



28
29
30
31
32
33
34
35
36
37
38
39
# File 'opal/lib/opal/cache/file_cache.rb', line 28

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
# File 'opal/lib/opal/cache/file_cache.rb', line 20

def set(key, data)
  file = cache_filename_for(key)

  out = Marshal.dump(data)
  out = Zlib.gzip(out, level: 9)
  File.binwrite(file, out)
end