diff options
author | Patrick Bajao <ebajao@gitlab.com> | 2019-06-05 07:59:48 +0300 |
---|---|---|
committer | Patrick Bajao <ebajao@gitlab.com> | 2019-06-05 08:19:59 +0300 |
commit | 2eecfd8f9d111c6518930b818a16daea8263b37f (patch) | |
tree | 12234d26e6e5a950ad69741e761ef7d3d079fdd1 /spec/lib/gitlab/markdown_cache/redis | |
parent | b560ce1e666733f12c65e8b9f659c89256c1775b (diff) |
Use Redis for CacheMarkDownField on non AR models
This allows using `CacheMarkdownField` for models that are not backed
by ActiveRecord.
When the including class inherits `ActiveRecord::Base` we include
`Gitlab::MarkdownCache::ActiveRecord::Extension`. This will cause the
markdown fields to be rendered and the generated HTML stored in a
`<field>_html` attribute on the record. We also store the version
used for generating the markdown.
All other classes that include this model will include the
`Gitlab::MarkdownCache::Redis::Extension`. This add the `<field>_html`
attributes to that model and will generate the html in them. The
generated HTML will be cached in redis under the key
`markdown_cache:<class>:<id>`. The class this included in must
therefore respond to `id`.
Diffstat (limited to 'spec/lib/gitlab/markdown_cache/redis')
-rw-r--r-- | spec/lib/gitlab/markdown_cache/redis/extension_spec.rb | 76 | ||||
-rw-r--r-- | spec/lib/gitlab/markdown_cache/redis/store_spec.rb | 68 |
2 files changed, 144 insertions, 0 deletions
diff --git a/spec/lib/gitlab/markdown_cache/redis/extension_spec.rb b/spec/lib/gitlab/markdown_cache/redis/extension_spec.rb new file mode 100644 index 00000000000..d3d3cd6f03c --- /dev/null +++ b/spec/lib/gitlab/markdown_cache/redis/extension_spec.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true +require 'spec_helper' + +describe Gitlab::MarkdownCache::Redis::Extension, :clean_gitlab_redis_cache do + class ThingWithMarkdownFields + include CacheMarkdownField + + def initialize(title: nil, description: nil) + @title, @description = title, description + end + + attr_reader :title, :description + + cache_markdown_field :title, pipeline: :single_line + cache_markdown_field :description + + def id + "test-markdown-cache" + end + end + + let(:cache_version) { Gitlab::MarkdownCache::CACHE_COMMONMARK_VERSION << 16 } + let(:thing) { ThingWithMarkdownFields.new(title: "`Hello`", description: "`World`") } + let(:expected_cache_key) { "markdown_cache:ThingWithMarkdownFields:test-markdown-cache" } + + it 'defines the html attributes' do + thing = ThingWithMarkdownFields.new + + expect(thing).to respond_to(:title_html, :description_html, :cached_markdown_version) + end + + it 'loads the markdown from the cache only once' do + expect(thing).to receive(:load_cached_markdown).once.and_call_original + + thing.title_html + thing.description_html + end + + it 'correctly loads the markdown if it was stored in redis' do + Gitlab::Redis::Cache.with do |r| + r.mapped_hmset(expected_cache_key, + title_html: 'hello', + description_html: 'world', + cached_markdown_version: cache_version) + end + + expect(thing.title_html).to eq('hello') + expect(thing.description_html).to eq('world') + expect(thing.cached_markdown_version).to eq(cache_version) + end + + describe "#refresh_markdown_cache!" do + it "stores the value in redis" do + expected_results = { "title_html" => "`Hello`", + "description_html" => "<p data-sourcepos=\"1:1-1:7\" dir=\"auto\"><code>World</code></p>", + "cached_markdown_version" => cache_version.to_s } + + thing.refresh_markdown_cache! + + results = Gitlab::Redis::Cache.with do |r| + r.mapped_hmget(expected_cache_key, + "title_html", "description_html", "cached_markdown_version") + end + + expect(results).to eq(expected_results) + end + + it "assigns the values" do + thing.refresh_markdown_cache! + + expect(thing.title_html).to eq('`Hello`') + expect(thing.description_html).to eq("<p data-sourcepos=\"1:1-1:7\" dir=\"auto\"><code>World</code></p>") + expect(thing.cached_markdown_version).to eq(cache_version) + end + end +end diff --git a/spec/lib/gitlab/markdown_cache/redis/store_spec.rb b/spec/lib/gitlab/markdown_cache/redis/store_spec.rb new file mode 100644 index 00000000000..59c038cfb2f --- /dev/null +++ b/spec/lib/gitlab/markdown_cache/redis/store_spec.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true +require 'spec_helper' + +describe Gitlab::MarkdownCache::Redis::Store, :clean_gitlab_redis_cache do + let(:storable_class) do + Class.new do + cattr_reader :cached_markdown_fields do + Gitlab::MarkdownCache::FieldData.new.tap do |field_data| + field_data[:field_1] = {} + field_data[:field_2] = {} + end + end + + attr_accessor :field_1, :field_2, :field_1_html, :field_2_html, :cached_markdown_version + + def id + 'test-redisbacked-store' + end + end + end + let(:storable) { storable_class.new } + let(:cache_key) { "markdown_cache:#{storable_class}:#{storable.id}" } + + subject(:store) { described_class.new(storable) } + + def read_values + Gitlab::Redis::Cache.with do |r| + r.mapped_hmget(cache_key, + :field_1_html, :field_2_html, :cached_markdown_version) + end + end + + def store_values(values) + Gitlab::Redis::Cache.with do |r| + r.mapped_hmset(cache_key, + values) + end + end + + describe '#save' do + it 'stores updates to html fields and version' do + values_to_store = { field_1_html: "hello", field_2_html: "world", cached_markdown_version: 1 } + + store.save(values_to_store) + + expect(read_values) + .to eq({ field_1_html: "hello", field_2_html: "world", cached_markdown_version: "1" }) + end + end + + describe '#read' do + it 'reads the html fields and version from redis if they were stored' do + stored_values = { field_1_html: "hello", field_2_html: "world", cached_markdown_version: 1 } + + store_values(stored_values) + + expect(store.read.symbolize_keys).to eq(stored_values) + end + + it 'is mared loaded after reading' do + expect(store).not_to be_loaded + + store.read + + expect(store).to be_loaded + end + end +end |