Fix ActiveStorage FileNotFoundError with immediate variant processing (#2022)
When ActiveStorage::Record uses `connects_to` for read replica support, it creates a separate connection pool from ApplicationRecord. This causes `after_commit` callbacks to fire in non-deterministic order - the Attachment's `create_variants` callback can fire before the User model's upload callback completes, resulting in FileNotFoundError. The fix removes replica connection configuration from ActiveStorage::Record so it shares the same connection pool as application models, ensuring proper callback ordering. Also reverts test workarounds that were added to work around this issue, since the root cause is now fixed. See: https://github.com/rails/rails/issues/53694
This commit is contained in:
@@ -2,8 +2,7 @@ require "test_helper"
|
||||
|
||||
class User::AvatarTest < ActiveSupport::TestCase
|
||||
test "avatar_thumbnail returns variant for variable images" do
|
||||
blob = ActiveStorage::Blob.create_and_upload!(io: File.open(file_fixture("moon.jpg")), filename: "moon.jpg", content_type: "image/jpeg")
|
||||
users(:david).avatar.attach(blob)
|
||||
users(:david).avatar.attach(io: File.open(file_fixture("moon.jpg")), filename: "moon.jpg", content_type: "image/jpeg")
|
||||
|
||||
assert users(:david).avatar.variable?
|
||||
assert_equal users(:david).avatar.variant(:thumb).blob, users(:david).avatar_thumbnail.blob
|
||||
@@ -17,8 +16,7 @@ class User::AvatarTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
test "allows valid image content types" do
|
||||
blob = ActiveStorage::Blob.create_and_upload!(io: File.open(file_fixture("moon.jpg")), filename: "test.jpg", content_type: "image/jpeg")
|
||||
users(:david).avatar.attach(blob)
|
||||
users(:david).avatar.attach(io: File.open(file_fixture("moon.jpg")), filename: "test.jpg", content_type: "image/jpeg")
|
||||
|
||||
assert users(:david).valid?
|
||||
end
|
||||
@@ -31,19 +29,7 @@ class User::AvatarTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
test "thumb variant is processed immediately on attachment" do
|
||||
# Create blob separately to ensure file is uploaded before variant processing.
|
||||
#
|
||||
# Root cause: When ActiveStorage::Record uses `connects_to` for read replica support
|
||||
# (as in SAAS mode), it creates a separate connection pool from application models.
|
||||
# Since after_commit callbacks are tracked per connection pool, the callback order
|
||||
# between User's pool (upload) and Attachment's pool (create_variants) isn't guaranteed.
|
||||
# In MySQL/SAAS mode, the Attachment callback fires before the file is uploaded.
|
||||
blob = ActiveStorage::Blob.create_and_upload!(
|
||||
io: File.open(file_fixture("avatar.png")),
|
||||
filename: "avatar.png",
|
||||
content_type: "image/png"
|
||||
)
|
||||
users(:david).avatar.attach(blob)
|
||||
users(:david).avatar.attach(io: File.open(file_fixture("avatar.png")), filename: "avatar.png", content_type: "image/png")
|
||||
|
||||
assert users(:david).avatar.variant(:thumb).processed?
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user