discourse/spec/integration/activerecord_preventing_writes_spec.rb
Alan Guo Xiang Tan 6bf0ac730f
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.
2024-11-15 10:19:10 +08:00

35 lines
985 B
Ruby

# 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