FIX: Rescue `ActiveRecord::ReadOnlyError` when baking theme field (#29776)
Firstly, we need to understand that ActiveRecord can be connected to a role which prevent writes and this happens in Discourse when a replica database has been setup for failover purposes. When a role prevent writes from happening, ActiveRecord will raise the `ActiveRecord::ReadOnlyError` if a write query is attempted. Secondly, theme fields are baked at runtime within GET requests. The baking process involves writing the baked value to the `ThemeField#baked_value` column in the database. If we combine the two points above, we can see how the writing of the baked value to the database will trigger a `ActiveRecord::ReadOnlyError` in a GET requests when the database is connected to a role preventing writes. However, failing to bake a theme is not the end of the world and should not cause GET requests to fail. Therefore, this commit adds a rescue for `ActiveRecord::ReadOnlyError` in the `ThemeField#ensure_baked!` method.
This commit is contained in:
parent
4e5de17e7c
commit
6bf0ac730f
|
@ -475,6 +475,9 @@ class ThemeField < ActiveRecord::Base
|
|||
error: error,
|
||||
)
|
||||
end
|
||||
rescue ActiveRecord::ReadOnlyError
|
||||
# Just noop if ActiveRecord is preventing writes for now. In an ideal world, this method will not be called in GET
|
||||
# requests.
|
||||
end
|
||||
|
||||
def compile_scss(prepended_scss = nil)
|
||||
|
|
|
@ -6,6 +6,8 @@ module Scheduler
|
|||
DEFAULT_TIMEOUT = 90
|
||||
STATS_CACHE_SIZE = 100
|
||||
|
||||
attr_reader :async
|
||||
|
||||
def initialize
|
||||
@async = !Rails.env.test?
|
||||
@queue =
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe "When ActiveRecord is preventing writes" do
|
||||
before do
|
||||
@original_async = Scheduler::Defer.async
|
||||
Scheduler::Defer.async = true
|
||||
end
|
||||
|
||||
after { Scheduler::Defer.async = @original_async }
|
||||
|
||||
it "should not result in an error response when there is a theme field that needs to be baked" do
|
||||
theme_field =
|
||||
Fabricate(
|
||||
:theme_field,
|
||||
type_id: ThemeField.types[:html],
|
||||
target_id: Theme.targets[:common],
|
||||
name: "head_tag",
|
||||
value: <<~HTML,
|
||||
<script type="text/discourse-plugin" version="0.1">
|
||||
console.log(settings.uploads.imajee);
|
||||
</script>
|
||||
HTML
|
||||
)
|
||||
|
||||
SiteSetting.default_theme_id = theme_field.theme_id
|
||||
|
||||
ActiveRecord::Base.connected_to(role: ActiveRecord.writing_role, prevent_writes: true) do
|
||||
get "/latest"
|
||||
|
||||
expect(request.env[:resolved_theme_id]).to eq(theme_field.theme_id)
|
||||
expect(response.status).to eq(200)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -713,6 +713,7 @@ RSpec.configure do |config|
|
|||
unfreeze_time
|
||||
ActionMailer::Base.deliveries.clear
|
||||
Discourse.redis.flushdb
|
||||
Scheduler::Defer.do_all_work
|
||||
end
|
||||
|
||||
config.after(:each, type: :system) do |example|
|
||||
|
|
Loading…
Reference in New Issue