class Rack::MiniProfiler::FileStore

Constants

EXPIRES_IN_SECONDS

Public Class Methods

new(args = nil) click to toggle source
# File lib/mini_profiler/storage/file_store.rb, line 42
def initialize(args = nil)
  args ||= {}
  @path = args[:path]
  @expires_in_seconds = args[:expires_in] || EXPIRES_IN_SECONDS
  raise ArgumentError.new :path unless @path
  FileUtils.mkdir_p(@path) unless ::File.exist?(@path)

  @timer_struct_cache = FileCache.new(@path, "mp_timers")
  @timer_struct_lock  = Mutex.new
  @user_view_cache    = FileCache.new(@path, "mp_views")
  @user_view_lock     = Mutex.new

  @auth_token_cache    = FileCache.new(@path, "tokens")
  @auth_token_lock     = Mutex.new

  me = self
  t = CacheCleanupThread.new do
    interval = 10
    cleanup_cache_cycle = 3600
    cycle_count = 1

    begin
      until Thread.current[:should_exit] do
        # TODO: a sane retry count before bailing

        # We don't want to hit the filesystem every 10s to clean up the cache so we need to do a bit of
        # accounting to avoid sleeping that entire time.  We don't want to sleep for the entire period because
        # it means the thread will stay live in hot deployment scenarios, keeping a potentially large memory
        # graph from being garbage collected upon undeploy.
        if cycle_count * interval >= cleanup_cache_cycle
          cycle_count = 1
          me.cleanup_cache
        end

        sleep(interval)
        cycle_count += 1
      end
    rescue
      # don't crash the thread, we can clean up next time
    end
  end

  at_exit { t[:should_exit] = true }

  t
end

Public Instance Methods

allowed_tokens() click to toggle source
# File lib/mini_profiler/storage/file_store.rb, line 138
def allowed_tokens
  @auth_token_lock.synchronize {
    token1, token2, cycle_at = @auth_token_cache[""]

    unless cycle_at && (Time === cycle_at) && (cycle_at > Time.now)
      token2 = token1
      token1 = SecureRandom.hex
      cycle_at = Time.now + Rack::MiniProfiler::AbstractStore::MAX_TOKEN_AGE
    end

    @auth_token_cache[""] = [token1, token2, cycle_at]

    [token1, token2].compact
  }
end
cleanup_cache() click to toggle source
# File lib/mini_profiler/storage/file_store.rb, line 154
def cleanup_cache
  files = Dir.entries(@path)
  @timer_struct_lock.synchronize {
    files.each do |f|
      f = @path + '/' + f
      ::File.delete f if ::File.basename(f) =~ /^mp_timers/ and (Time.now - ::File.mtime(f)) > @expires_in_seconds
    end
  }
  @user_view_lock.synchronize {
    files.each do |f|
      f = @path + '/' + f
      ::File.delete f if ::File.basename(f) =~ /^mp_views/ and (Time.now - ::File.mtime(f)) > @expires_in_seconds
    end
  }
end
flush_tokens() click to toggle source
# File lib/mini_profiler/storage/file_store.rb, line 132
def flush_tokens
  @auth_token_lock.synchronize {
    @auth_token_cache[""] = nil
  }
end
get_unviewed_ids(user) click to toggle source
# File lib/mini_profiler/storage/file_store.rb, line 126
def get_unviewed_ids(user)
  @user_view_lock.synchronize {
    @user_view_cache[user]
  }
end
load(id) click to toggle source
# File lib/mini_profiler/storage/file_store.rb, line 95
def load(id)
  @timer_struct_lock.synchronize {
    @timer_struct_cache[id]
  }
end
save(page_struct) click to toggle source
# File lib/mini_profiler/storage/file_store.rb, line 89
def save(page_struct)
  @timer_struct_lock.synchronize {
    @timer_struct_cache[page_struct[:id]] = page_struct
  }
end
set_all_unviewed(user, ids) click to toggle source
# File lib/mini_profiler/storage/file_store.rb, line 120
def set_all_unviewed(user, ids)
  @user_view_lock.synchronize {
    @user_view_cache[user] = ids.uniq
  }
end
set_unviewed(user, id) click to toggle source
# File lib/mini_profiler/storage/file_store.rb, line 101
def set_unviewed(user, id)
  @user_view_lock.synchronize {
    current = @user_view_cache[user]
    current = [] unless Array === current
    current << id
    @user_view_cache[user] = current.uniq
  }
end
set_viewed(user, id) click to toggle source
# File lib/mini_profiler/storage/file_store.rb, line 110
def set_viewed(user, id)
  @user_view_lock.synchronize {
    @user_view_cache[user] ||= []
    current = @user_view_cache[user]
    current = [] unless Array === current
    current.delete(id)
    @user_view_cache[user] = current.uniq
  }
end