diff options
author | Douglas Barbosa Alexandre <dbalexandre@gmail.com> | 2018-12-19 16:47:27 +0300 |
---|---|---|
committer | Douglas Barbosa Alexandre <dbalexandre@gmail.com> | 2018-12-19 20:15:05 +0300 |
commit | 156788bae934c811f1efc370a7e6109f231ede18 (patch) | |
tree | bd2a0ea2dd659c534c31950d04f457949be1d161 /lib/gitlab/json_cache.rb | |
parent | 806ea5762baec558a85cd3edd36f82839bb1c904 (diff) |
Port Gitlab::JsonCache to CE
Diffstat (limited to 'lib/gitlab/json_cache.rb')
-rw-r--r-- | lib/gitlab/json_cache.rb | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/lib/gitlab/json_cache.rb b/lib/gitlab/json_cache.rb new file mode 100644 index 00000000000..1adf83739ad --- /dev/null +++ b/lib/gitlab/json_cache.rb @@ -0,0 +1,87 @@ +# frozen_string_literal: true + +module Gitlab + class JsonCache + attr_reader :backend, :cache_key_with_version, :namespace + + def initialize(options = {}) + @backend = options.fetch(:backend, Rails.cache) + @namespace = options.fetch(:namespace, nil) + @cache_key_with_version = options.fetch(:cache_key_with_version, true) + end + + def active? + if backend.respond_to?(:active?) + backend.active? + else + true + end + end + + def cache_key(key) + expanded_cache_key = [namespace, key].compact + + if cache_key_with_version + expanded_cache_key << Rails.version + end + + expanded_cache_key.join(':') + end + + def expire(key) + backend.delete(cache_key(key)) + end + + def read(key, klass = nil) + value = backend.read(cache_key(key)) + value = parse_value(value, klass) if value + value + end + + def write(key, value, options = nil) + backend.write(cache_key(key), value.to_json, options) + end + + def fetch(key, options = {}, &block) + klass = options.delete(:as) + value = read(key, klass) + + return value unless value.nil? + + value = yield + + write(key, value, options) + + value + end + + private + + def parse_value(raw, klass) + value = ActiveSupport::JSON.decode(raw) + + case value + when Hash then parse_entry(value, klass) + when Array then parse_entries(value, klass) + else + value + end + rescue ActiveSupport::JSON.parse_error + nil + end + + def parse_entry(raw, klass) + klass.new(raw) if valid_entry?(raw, klass) + end + + def valid_entry?(raw, klass) + return false unless klass && raw.is_a?(Hash) + + (raw.keys - klass.attribute_names).empty? + end + + def parse_entries(values, klass) + values.map { |value| parse_entry(value, klass) }.compact + end + end +end |