Commit 1f971686 authored by Toon Claes's avatar Toon Claes

Create refresh_markdown_cache that doesn't write to database

`CacheMarkdownField#refresh_markdown_cache!` is splitted out in:
- `CacheMarkdownField#refresh_markdown_cache`: This does the same as
  before, but does never write to database.
- `CacheMarkdownField#refresh_markdown_cache!`: This calls the
  previous method, and tries to write to database, if possible.
parent 8d7e07d0
...@@ -59,7 +59,7 @@ module CacheMarkdownField ...@@ -59,7 +59,7 @@ module CacheMarkdownField
# Update every column in a row if any one is invalidated, as we only store # Update every column in a row if any one is invalidated, as we only store
# one version per row # one version per row
def refresh_markdown_cache!(do_update: false) def refresh_markdown_cache
options = { skip_project_check: skip_project_check? } options = { skip_project_check: skip_project_check? }
updates = cached_markdown_fields.markdown_fields.map do |markdown_field| updates = cached_markdown_fields.markdown_fields.map do |markdown_field|
...@@ -71,8 +71,14 @@ module CacheMarkdownField ...@@ -71,8 +71,14 @@ module CacheMarkdownField
updates['cached_markdown_version'] = CacheMarkdownField::CACHE_VERSION updates['cached_markdown_version'] = CacheMarkdownField::CACHE_VERSION
updates.each {|html_field, data| write_attribute(html_field, data) } updates.each {|html_field, data| write_attribute(html_field, data) }
end
def refresh_markdown_cache!
updates = refresh_markdown_cache
return unless persisted? && Gitlab::Database.read_write?
update_columns(updates) if persisted? && do_update update_columns(updates)
end end
def cached_html_up_to_date?(markdown_field) def cached_html_up_to_date?(markdown_field)
...@@ -124,8 +130,8 @@ module CacheMarkdownField ...@@ -124,8 +130,8 @@ module CacheMarkdownField
end end
# Using before_update here conflicts with elasticsearch-model somehow # Using before_update here conflicts with elasticsearch-model somehow
before_create :refresh_markdown_cache!, if: :invalidated_markdown_cache? before_create :refresh_markdown_cache, if: :invalidated_markdown_cache?
before_update :refresh_markdown_cache!, if: :invalidated_markdown_cache? before_update :refresh_markdown_cache, if: :invalidated_markdown_cache?
end end
class_methods do class_methods do
......
...@@ -40,7 +40,7 @@ module Banzai ...@@ -40,7 +40,7 @@ module Banzai
return cacheless_render_field(object, field) return cacheless_render_field(object, field)
end end
object.refresh_markdown_cache!(do_update: update_object?(object)) unless object.cached_html_up_to_date?(field) object.refresh_markdown_cache! unless object.cached_html_up_to_date?(field)
object.cached_html_for(field) object.cached_html_for(field)
end end
...@@ -162,10 +162,5 @@ module Banzai ...@@ -162,10 +162,5 @@ module Banzai
return unless cache_key return unless cache_key
Rails.cache.__send__(:expanded_key, full_cache_key(cache_key, pipeline_name)) # rubocop:disable GitlabSecurity/PublicSend Rails.cache.__send__(:expanded_key, full_cache_key(cache_key, pipeline_name)) # rubocop:disable GitlabSecurity/PublicSend
end end
# GitLab needs to disable updates on GET requests if database is readonly
def self.update_object?(object)
Gitlab::Database.read_write?
end
end end
end end
...@@ -31,14 +31,14 @@ describe Banzai::Renderer do ...@@ -31,14 +31,14 @@ describe Banzai::Renderer do
let(:object) { fake_object(fresh: false) } let(:object) { fake_object(fresh: false) }
it 'caches and returns the result' do it 'caches and returns the result' do
expect(object).to receive(:refresh_markdown_cache!).with(do_update: true) expect(object).to receive(:refresh_markdown_cache!)
is_expected.to eq('field_html') is_expected.to eq('field_html')
end end
it "skips database caching on a GitLab readonly instance" do it "skips database caching on a GitLab readonly instance" do
allow(Gitlab::Database).to receive(:read_only?).and_return(true) allow(Gitlab::Database).to receive(:read_only?).and_return(true)
expect(object).to receive(:refresh_markdown_cache!).with(do_update: false) expect(object).to receive(:refresh_markdown_cache!)
is_expected.to eq('field_html') is_expected.to eq('field_html')
end end
......
...@@ -178,57 +178,59 @@ describe CacheMarkdownField do ...@@ -178,57 +178,59 @@ describe CacheMarkdownField do
end end
end end
describe '#refresh_markdown_cache!' do describe '#refresh_markdown_cache' do
before do before do
thing.foo = updated_markdown thing.foo = updated_markdown
end end
context 'do_update: false' do it 'fills all html fields' do
it 'fills all html fields' do thing.refresh_markdown_cache
thing.refresh_markdown_cache!
expect(thing.foo_html).to eq(updated_html) expect(thing.foo_html).to eq(updated_html)
expect(thing.foo_html_changed?).to be_truthy expect(thing.foo_html_changed?).to be_truthy
expect(thing.baz_html_changed?).to be_truthy expect(thing.baz_html_changed?).to be_truthy
end end
it 'does not save the result' do it 'does not save the result' do
expect(thing).not_to receive(:update_columns) expect(thing).not_to receive(:update_columns)
thing.refresh_markdown_cache! thing.refresh_markdown_cache
end end
it 'updates the markdown cache version' do it 'updates the markdown cache version' do
thing.cached_markdown_version = nil thing.cached_markdown_version = nil
thing.refresh_markdown_cache! thing.refresh_markdown_cache
expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_VERSION) expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_VERSION)
end
end end
end
context 'do_update: true' do describe '#refresh_markdown_cache!' do
it 'fills all html fields' do before do
thing.refresh_markdown_cache!(do_update: true) thing.foo = updated_markdown
end
expect(thing.foo_html).to eq(updated_html) it 'fills all html fields' do
expect(thing.foo_html_changed?).to be_truthy thing.refresh_markdown_cache!
expect(thing.baz_html_changed?).to be_truthy
end
it 'skips saving if not persisted' do expect(thing.foo_html).to eq(updated_html)
expect(thing).to receive(:persisted?).and_return(false) expect(thing.foo_html_changed?).to be_truthy
expect(thing).not_to receive(:update_columns) expect(thing.baz_html_changed?).to be_truthy
end
thing.refresh_markdown_cache!(do_update: true) it 'skips saving if not persisted' do
end expect(thing).to receive(:persisted?).and_return(false)
expect(thing).not_to receive(:update_columns)
it 'saves the changes using #update_columns' do thing.refresh_markdown_cache!
expect(thing).to receive(:persisted?).and_return(true) end
expect(thing).to receive(:update_columns)
.with("foo_html" => updated_html, "baz_html" => "", "cached_markdown_version" => CacheMarkdownField::CACHE_VERSION)
thing.refresh_markdown_cache!(do_update: true) it 'saves the changes using #update_columns' do
end expect(thing).to receive(:persisted?).and_return(true)
expect(thing).to receive(:update_columns)
.with("foo_html" => updated_html, "baz_html" => "", "cached_markdown_version" => CacheMarkdownField::CACHE_VERSION)
thing.refresh_markdown_cache!
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment