Closed johnvuko closed 6 months ago
The sample code looks like a race condition between the Shrine after_commit processing used for promotion and update operation. I'm pretty sure Shrine logs under those circumstances. Do you see anything in the logs?
While the sample code demonstrates a problem, what's the business use-case for that workflow? It might be easier to help with where to plug into Shrines multitude of hooks to accomplish your goals if I understood your requirements.
The logger show:
Metadata (6ms) – {:storage=>:cache, :io=>Tempfile, :uploader=>Shrine}
Upload (0ms) – {:storage=>:cache, :location=>"54fb171c65dae520870092d5f73eca40", :io=>Tempfile, :upload_options=>{}, :uploader=>Shrine}
My use case is in a large Rails application, we find a way but finding the source of the issue took some time. I would prefer an exception than having this behavior. I thought the problem with hooks in Rails models was long time gone.
@jonathantribouharet
A couple of things:
This is a bug in Active Record. It only calls the after_create_commit
hook on the first model instance, but not the after_update_commit
hook on the second model instance, which causes promotion of the attachment to permanent storage to be skipped.
require "active_record"
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.connection.create_table(:products) { |t| t.string :name }
class Product < ActiveRecord::Base
after_create_commit { puts "after_create_commit" }
after_update_commit { puts "after_create_commit" }
end
ActiveRecord::Base.transaction do
product = Product.create!(name: "Foo")
product = Product.find(product.id)
product.update!(name: "Bar")
end
# OUTPUT:
# after_create_commit
I thought the problem with hooks in Rails models was long time gone.
Problems with Active Record's transaction callbacks will likely never entirely go away, because the way they're implemented is really messy, so it's unlikely to ever produce reliable behavior. I wrote more about it here.
In Sequel, transaction hooks are implemented cleanly, most importantly they have no knowledge of models. When I modify your example to use Sequel instead of Active Record, it produces the expected result.
So, your only option is to get it fixed in Active Record, or rewrite your code to avoid running into this edge case.
Brief Description
Hello, Inside a transaction, if a create a model then reload it with the
find
method, the file is not promoted on permanent storage (store
) and stay incache
. It doesn't happen if I callreload
on the model or without the transaction.This bug doesn't seems to be related with #366
Expected behavior
The storage should be
store
.Actual behavior
The storage is
cache
.Simplest self-contained example code to demonstrate issue
System configuration
Ruby: 3.2.2 Shrine: 3.5.0 Ruby On Rails: 7.0.7.2