Exception while trying to marshal ActiveRecord/Sequel model, with attachment & derivatives: no _dump_data is defined for class Thread::Mutex
Morozzzko opened this issue · comments
Brief Description
My app has a case when we need to cache an ActiveRecord object, which has a Shrine attachment.
The attachment's uploader works with two plugins: activerecord
and derivatives
.
This worked fine under 2.19.4, but broke after our upgrade to 3.3.0
Expected behavior
I expect Rails cache to marshal the provided object and put in the cache. I also expect the object to be functioning properly afterwards
Actual behavior
Whenever I try to marshal a newly-created object with an attachment, I get an exception: no _dump_data is defined for class Thread::Mutex (TypeError)
However, if I try to re-fetch the same object and marshal it, it works fine. #reload
doesn't work, though.
Simplest self-contained example code to demonstrate issue
Provide a self-contained example code (see the Sequel/ActiveRecord templates) to show the problem, and the full backtrace of any exception.
ActiveRecord
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'rails', '5.2.4.4'
gem 'shrine', '3.3.0'
gem 'sqlite3'
end
require 'active_record'
require 'shrine'
require 'shrine/storage/memory'
require 'down'
Shrine.storages = {
cache: Shrine::Storage::Memory.new,
store: Shrine::Storage::Memory.new
}
Shrine.plugin :activerecord
class MyUploader < Shrine
plugin :derivatives
end
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Base.connection.create_table(:posts) { |t| t.text :image_data }
class Post < ActiveRecord::Base
include MyUploader::Attachment(:image)
end
post = Post.create(image: Down.download('http://theoldreader.com/kittens/600/400/'))
Marshal.dump(post)
# Traceback (most recent call last):
# 1: from reproduce_2.rb:36:in `<main>'
# reproduce.rb:36:in `dump': no _dump_data is defined for class Thread::Mutex (TypeError)
# HOWEVER!
Marshal.dump(post.class.find(post.id)) # works just fine
Marshal.dump(post.reload) # => no _dump_data is defined for class Thread::Mutex (TypeError)
Marshal.dump(post.image) # works just fine
Sequel
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'sequel'
gem 'shrine', '3.3.0'
gem 'sqlite3'
end
require 'sequel'
require 'shrine'
require 'shrine/storage/memory'
require 'down'
Shrine.storages = {
cache: Shrine::Storage::Memory.new,
store: Shrine::Storage::Memory.new
}
Shrine.plugin :sequel
class MyUploader < Shrine
plugin :derivatives
end
DB = Sequel.sqlite # SQLite memory database
DB.create_table :posts do
primary_key :id
String :image_data
end
class Post < Sequel::Model
include MyUploader::Attachment(:image)
end
post = Post.create(image: Down.download('http://theoldreader.com/kittens/600/400/'))
Marshal.dump(post)
# Traceback (most recent call last):
# 1: from reproduce_sequel.rb:39:in `<main>'
# reproduce_sequel.rb:39:in `dump': no _dump_data is defined for class Thread::Mutex (TypeError)
System configuration
Ruby version: 2.6.5 and 2.7.2
Shrine version: 3.3.0
As it turns out, this problem also exists with Sequel models. Sorry for being so hasty and not considering it before creating the issue
Hey @Morozzzko, thanks for the report 👍
I believe this is happening because the derivatives
plugin uses a mutex internally (assigned to an instance variable), which was not the case with the versions
plugin. We should probably find a way to exclude it when marshalling.
I'm wondering whether Sequel has some inspiration, as I recall it has some logic for Marshalling, though I suppose it doesn't use mutexes on models directly.
Thanks for the quick reply!
Yes, I've been trying to find the lines which cause the error, and it is indeed the mutex
I'm looking for a solution to exclude it. Thanks for the tip about Sequel! I'll post whatever I find
Sequel hasn't really fixed it, as it turns out. I've managed to marshal ActiveRecord model, but not Sequel model.
However, if I try to marshal _attacher
separately, it works now. I think it's good enough for us, since everything works fine on Shrine's side. I'm preparing a PR