diff options
Diffstat (limited to 'lib/gitlab/markdown_cache/redis')
-rw-r--r-- | lib/gitlab/markdown_cache/redis/extension.rb | 63 | ||||
-rw-r--r-- | lib/gitlab/markdown_cache/redis/store.rb | 56 |
2 files changed, 119 insertions, 0 deletions
diff --git a/lib/gitlab/markdown_cache/redis/extension.rb b/lib/gitlab/markdown_cache/redis/extension.rb new file mode 100644 index 00000000000..97fc23343b4 --- /dev/null +++ b/lib/gitlab/markdown_cache/redis/extension.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +module Gitlab + module MarkdownCache + module Redis + module Extension + extend ActiveSupport::Concern + + attr_reader :cached_markdown_version + + class_methods do + def cache_markdown_field(markdown_field, context = {}) + super + + # define the `[field]_html` accessor + html_field = cached_markdown_fields.html_field(markdown_field) + define_method(html_field) do + load_cached_markdown unless markdown_data_loaded? + + instance_variable_get("@#{html_field}") + end + end + end + + private + + def save_markdown(updates) + markdown_store.save(updates) + end + + def write_markdown_field(field_name, value) + instance_variable_set("@#{field_name}", value) + end + + def markdown_field_changed?(field_name) + false + end + + def changed_markdown_fields + [] + end + + def cached_markdown + @cached_data ||= markdown_store.read + end + + def load_cached_markdown + cached_markdown.each do |field_name, value| + write_markdown_field(field_name, value) + end + end + + def markdown_data_loaded? + cached_markdown_version.present? || markdown_store.loaded? + end + + def markdown_store + @store ||= Gitlab::MarkdownCache::Redis::Store.new(self) + end + end + end + end +end diff --git a/lib/gitlab/markdown_cache/redis/store.rb b/lib/gitlab/markdown_cache/redis/store.rb new file mode 100644 index 00000000000..0f954404808 --- /dev/null +++ b/lib/gitlab/markdown_cache/redis/store.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +module Gitlab + module MarkdownCache + module Redis + class Store + EXPIRES_IN = 1.day + + def initialize(subject) + @subject = subject + @loaded = false + end + + def save(updates) + @loaded = false + + Gitlab::Redis::Cache.with do |r| + r.mapped_hmset(markdown_cache_key, updates) + r.expire(markdown_cache_key, EXPIRES_IN) + end + end + + def read + @loaded = true + + results = Gitlab::Redis::Cache.with do |r| + r.mapped_hmget(markdown_cache_key, *fields) + end + # The value read from redis is a string, so we're converting it back + # to an int. + results[:cached_markdown_version] = results[:cached_markdown_version].to_i + results + end + + def loaded? + @loaded + end + + private + + def fields + @fields ||= @subject.cached_markdown_fields.html_fields + [:cached_markdown_version] + end + + def markdown_cache_key + unless @subject.respond_to?(:cache_key) + raise Gitlab::MarkdownCache::UnsupportedClassError, + "This class has no cache_key to use for caching" + end + + "markdown_cache:#{@subject.cache_key}" + end + end + end + end +end |