I am using Mongoid and delayed_job_mongoid gems. Everything is in its latest version, including Rails (3.2.3).
I understand that if I put handle_asynchronously after any method declaration, this method will always be run async. But I get undefined method error like this:
class Item
# mongoid include stuff
def shout
puts 'a simple hi'
end
handle_asynchronously :shout
end
item = Item.create
item.shout # returns a delayed job object
j = _
# wait a moment
j.last_error
{undefined method `shout_without_delay' for #<Item:0x007f8365e62978>
/Users/nik/.rvm/gems/ruby-1.9.3-p194/gems/mongoid-2.4.9/lib/mongoid/attributes.rb:166:in `method_missing'
/Users/nik/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/performable_method.rb:26:in `perform'
/Users/nik/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/backend/base.rb:94:in `block in invoke_job'
/Users/nik/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:60:in `call'
/Users/nik/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:60:in `block in initialize'
/Users/nik/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:65:in `call'
/Users/nik/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:65:in `execute'
/Users/nik/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/lifecycle.rb:38:in `run_callbacks'
/Users/nik/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/backend/base.rb:91:in `invoke_job'
/Users/nik/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/worker.rb:178:in `block (2 levels) in run'
/Users/nik/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/timeout.rb:68:in `timeout'
/Users/nik/.rvm/gems/ruby-1.9.3-p194/gems/delayed_job-3.0.2/lib/delayed/worker.rb:178:in `block in run'
/Users/nik/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/benchmark.rb:295:in `realtime'
BUT if I had called
item.delay.shout
without the handle_asynchronously line
it will work!
Any ideas?
THANKS!
this is the author of the post. I found out what happened. Short answer: You have to restart the workers in the terminal
[control + c]
rake jobs:work
for mongoid delay jobs to be able to find the method. I do not know why. So just remember to restart the workers whenever you have added another line of handle_asynchronously :method
Happy coding!
You syntax should be
class Item
# mongoid include stuff
def shout
puts 'a simple hi'
end
handle_asynchronously :shout
end
you can get more details from here https://github.com/collectiveidea/delayed_job
Related
I have an Expenditure model:
class Expenditure < ApplicationRecord
multi_tenant :company
after_commit :related_reindex
def related_reindex
ExpenditureRelatedReindex.perform_async(id)
end
end
Here is my worker expenditure_related_reindex.rb:
class ExpenditureRelatedReindex
include Sidekiq::Worker
sidekiq_options :queue => :critical, :retry => true, :backtrace => true
def perform(record_id)
e = Expenditure.find(record_id)
MultiTenant.with(e.company) do
return unless e
e.expenditure_items.each(&:reindex)
e.children&.each(&:reindex)
end
end
end
The reindex can take some time so I want these to spin off to SideKiq. I have sime multi tenant code I should mention but I don't think it's the issue. After the record is updated I get:
NameError: uninitialized constant ExpenditureRelatedReindex
Did you mean? ExpenditureItemsHelper
from sidekiq/processor.rb:268:in `const_get'
from sidekiq/processor.rb:268:in `constantize'
from sidekiq/processor.rb:132:in `block (5 levels) in dispatch'
from sidekiq/rails.rb:43:in `block in call'
from active_support/execution_wrapper.rb:87:in `wrap'
from active_support/reloader.rb:73:in `block in wrap'
from active_support/execution_wrapper.rb:87:in `wrap'
from active_support/reloader.rb:72:in `wrap'
from sidekiq/rails.rb:42:in `call'
from sidekiq/processor.rb:131:in `block (4 levels) in dispatch'
from sidekiq/processor.rb:257:in `stats'
from sidekiq/processor.rb:126:in `block (3 levels) in dispatch'
from sidekiq/job_logger.rb:13:in `call'
from sidekiq/processor.rb:125:in `block (2 levels) in dispatch'
from sidekiq/job_retry.rb:78:in `global'
from sidekiq/processor.rb:124:in `block in dispatch'
from sidekiq/logger.rb:10:in `with'
from sidekiq/job_logger.rb:33:in `prepare'
from sidekiq/processor.rb:123:in `dispatch'
from sidekiq/processor.rb:162:in `process'
from sidekiq/processor.rb:78:in `process_one'
from sidekiq/processor.rb:68:in `run'
from sidekiq/util.rb:15:in `watchdog'
from sidekiq/util.rb:24:in `block in safe_thread'
I have even taken out the entire 'perform' block of code i.e. the worker does nothing to confirm I don't have some sort of regressive call etc. I confirm that my other workers fire and process just fine. Checked for obvious typos - banging my head against the wall at this point.
UPDATE
Ok - I have confirmed one thing - if I add any new workers with any name this triggers the same error. I even rebooted the entire production server to confirm the whole code was reloaded etc.
It ended up being Redis (or at least my fix was related). Found this post:
https://github.com/mperham/sidekiq/issues/2834#issuecomment-184800981
and it was a Redis namespace conflict. My server does have elasticsearch running also so that makes sense. I am not sure why the old workers run but the new ones failed. My fix looks like this:
config.redis = {
url: ENV['REDIS_URL'],
namespace: "some_namespace_different_for_each_app"
}
You also need the redis-namespace gem BTW
I have an Active Record model object called Event, which has many event_things. I want to be able to duplicate the event, so that it gets a new id. I'm using Rails 3.2 and in rails console am able to successfully call
event_copy = event.dup
event_copy.save
However, I also want to duplicate each of the Event's event_things.
copy = event_thing.dup
copy.event_id = event_copy.id
copy.save
But that gives me this error stack:
NoMethodError: undefined method `yaml' for nil:NilClass
from /Users/Ed/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/psych.rb:204:in `dump_stream'
from /Users/Ed/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/psych/core_ext.rb:35:in `psych_y'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:143:in `attribute_change'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:117:in `block in changes'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:117:in `map'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:117:in `changes'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/attribute_methods/dirty.rb:23:in `save'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:241:in `block (2 levels) in save'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:295:in `block in with_transaction_returning_status'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:208:in `transaction'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:293:in `with_transaction_returning_status'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:241:in `block in save'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:252:in `rollback_active_record_state!'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:240:in `save'
from (irb):18
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.6/lib/rails/commands/console.rb:47:in `start'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.6/lib/rails/commands/console.rb:8:in `start'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.6/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
I ran into the same issue as this. It turns out that there's a Kernel.y extension method that is getting in your way, based on this article. Here is what I did to fix my problem:
class Event < ActiveRecord::Base
# alias the attributes
alias_attribute :x_pos, :x
alias_attribute :y_pos, :y
after_initialize :init
# after_initialize will still work, with the aliases
def init
self.x_pos ||= 0
self.y_pos ||= 0
end
# override Kernel.y
def y; end
# override self.y_pos to read out of the :attributes, since we blew away :y
def y_pos
attribute['y']
end
end
After doing this, I was finally able to use my model without having to rename the y database column.
While I normally don't advocate using gems liberally, if you have a lot of relations that need to be preserved in the duplication, or find yourself doing these manual duplications a lot, take a look at deep_clonable.
As for your specific error, try surrounding each line of code with a nil check (one line at a time). I'm sure there's just some case where you're ending up with a nil object that you're overlooking.
The bug is many months old, here:
http://www.ruby-forum.com/topic/1094002
Two links in that which show code changes:
https://github.com/godfat/ruby/commit/f4e0e8f781b05c767ad2472a43a4ed0727a75708
https://github.com/godfat/ruby/commit/c7a6cf975d88828c2ed27d253f41c480f9b66ad6
I have Ruby 1.9.2 and rvm. I would have pasted those changes into the appropriate files, but I don't know how.
This worked a few days ago. I can't do Ruby on Rails commands like:
>> User.create :username => "a", :password => "a"
Here is the error message:
ArgumentError: wrong number of arguments(1 for 0)
from /Users/RedApple/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:48:in `method'
from /Users/RedApple/.rvm/rubies/ruby-1.9.2 p290/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:48:in `accept'
from /Users/RedApple/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:36:in `<<'
from /Users/RedApple/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/psych.rb:165:in `dump'
from /Users/RedApple/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/psych/core_ext.rb:13:in `psych_to_yaml'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.0.4/lib/delayed/backend/base.rb:57:in `payload_object='
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2918:in `block in assign_attributes'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2914:in `each'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2914:in `assign_attributes'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2787:in `attributes='
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2477:in `initialize'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:725:in `new'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:725:in `create'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/delayed_job-2.0.4/lib/delayed/message_sending.rb:9:in `method_missing'
from /Users/RedApple/S/app/models/user.rb:29:in `block in <class:User>'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-2.3.14/lib/active_support/callbacks.rb:182:in `call'
... 7 levels...
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/callbacks.rb:267:in `create_with_callbacks'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2927:in `create_or_update'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/callbacks.rb:250:in `create_or_update_with_callbacks'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:2577:in `save'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/validations.rb:1089:in `save_with_validation'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/dirty.rb:79:in `save_with_dirty'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:229:in `block in with_transaction_returning_status'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:182:in `transaction'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:228:in `with_transaction_returning_status'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:196:in `block in save_with_transactions'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:208:in `rollback_active_record_state!'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/transactions.rb:196:in `save_with_transactions'
from /Users/RedApple/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.14/lib/active_record/base.rb:727:in `create'
from (irb):1
from /Users/RedApple/.rvm/rubies/ruby-1.9.2-p290/bin/irb:16:in `<main>'>
Line 28-30 in user.rb:
after_create do |user|
user.delay( :priority => -15 ).seed
end
I am dead in the water without this. Can anyone help?
Delayed Job and the Ruby 1.9.2 YAML parser (Psych) are unfortunately not compatible.
Switch back to the previous YAML parser (Syck) by adding this to your config/application.rb, just below the call to Bundler.require:
YAML::ENGINE.yamler = "syck" if RUBY_VERSION >= "1.9.2"
You could patch your Ruby, but it's not easy and not really possible on managed hosts.
My solution was to create a monkeypatch based on the patch commit 31075.
Create an initializer file in your Rails project
config/initializers/psych_extensions.rb
and add this code:
# APPLIES RUBY PATCH REVISION 31075
module Psych
module Visitors
###
# YAMLTree builds a YAML ast given a ruby object. For example:
#
# builder = Psych::Visitors::YAMLTree.new
# builder << { :foo => 'bar' }
# builder.tree # => #<Psych::Nodes::Stream .. }
#
class YAMLTree < Psych::Visitors::Visitor
def accept target
# return any aliases we find
if node = #st[target.object_id]
node.anchor = target.object_id.to_s
return #emitter.alias target.object_id.to_s
end
if target.respond_to?(:to_yaml)
loc = target.public_method(:to_yaml).source_location.first
if loc !~ /(syck\/rubytypes.rb|psych\/core_ext.rb)/
unless target.respond_to?(:encode_with)
if $VERBOSE
warn "implementing to_yaml is deprecated, please implement \"encode_with\""
end
target.to_yaml(:nodump => true)
end
end
end
if target.respond_to?(:encode_with)
dump_coder target
else
send(#dispatch_cache[target.class], target)
end
end
private
# FIXME: remove this method once "to_yaml_properties" is removed
def find_ivars target
loc = target.public_method(:to_yaml_properties).source_location.first
unless loc.start_with?(Psych::DEPRECATED) || loc.end_with?('rubytypes.rb')
if $VERBOSE
warn "#{loc}: to_yaml_properties is deprecated, please implement \"encode_with(coder)\""
end
return target.to_yaml_properties
end
target.instance_variables
end
end
end
end
I am trying to use DelayedJob and the job is failing, giving the following error in the database:
{Delayed::DeserializationError
/Library/Ruby/Gems/1.8/gems/delayed_job-2.1.3/lib/delayed/serialization/active_record.rb:7:in `yaml_new'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/yaml.rb:133:in `transfer'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/yaml.rb:133:in `node_import'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/yaml.rb:133:in `load'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/yaml.rb:133:in `load'
/Library/Ruby/Gems/1.8/gems/delayed_job-2.1.3/lib/delayed/backend/base.rb:79:in `payload_object'
/Library/Ruby/Gems/1.8/gems/delayed_job-2.1.3/lib/delayed/backend/base.rb:87:in `invoke_job_without_newrelic_transaction_trace'
(eval):3:in `invoke_job'
/Library/Ruby/Gems/1.8/gems/newrelic_rpm-2.13.4/lib/new_relic/agent/instrumentation/controller_instrumentation.rb:252:in `perform_action_with_newrelic_trace'
/Library/Ruby/Gems/1.8/gems/newrelic_rpm-2.13.4/lib/new_relic/agent/method_tracer.rb:141:in `trace_execution_scoped'
/Library/Ruby/Gems/1.8/gems/newrelic_rpm-2.13.4/lib/new_relic/agent/instrumentation/controller_instrumentation.rb:247:in `perform_action_with_newrelic_trace'
(eval):2:in `invoke_job'
/Library/Ruby/Gems/1.8/gems/delayed_job-2.1.3/lib/delayed/worker.rb:120:in `run'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/timeout.rb:62:in `timeout'
/Library/Ruby/Gems/1.8/gems/delayed_job-2.1.3/lib/delayed/worker.rb:120:in `run'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/benchmark.rb:308:in `realtime'
/Library/Ruby/Gems/1.8/gems/delayed_job-2.1.3/lib/delayed/worker.rb:119:in `run'
/Library/Ruby/Gems/1.8/gems/delayed_job-2.1.3/lib/delayed/worker.rb:177:in `reserve_and_run_one_job'
/Library/Ruby/Gems/1.8/gems/delayed_job-2.1.3/lib/delayed/worker.rb:104:in `work_off'
/Library/Ruby/Gems/1.8/gems/delayed_job-2.1.3/lib/delayed/worker.rb:103:in `times'
/Library/Ruby/Gems/1.8/gems/delayed_job-2.1.3/lib/delayed/worker.rb:103:in `work_off'
/Library/Ruby/Gems/1.8/gems/delayed_job-2.1.3/lib/delayed/worker.rb:78:in `start'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/benchmark.rb:308:in `realtime'
/Library/Ruby/Gems/1.8/gems/delayed_job-2.1.3/lib/delayed/worker.rb:77:in `start'
/Library/Ruby/Gems/1.8/gems/delayed_job-2.1.3/lib/delayed/worker.rb:74:in `loop'
/Library/Ruby/Gems/1.8/gems/delayed_job-2.1.3/lib/delayed/worker.rb:74:in `start'
/Library/Ruby/Gems/1.8/gems/delayed_job-2.1.3/lib/delayed/tasks.rb:9
/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake.rb:636:in `call'
/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake.rb:636:in `execute'
/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake.rb:631:in `each'
/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake.rb:631:in `execute'
/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake.rb:597:in `invoke_with_call_chain'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/monitor.rb:242:in `synchronize'
/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake.rb:590:in `invoke_with_call_chain'
/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake.rb:583:in `invoke'
/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake.rb:2051:in `invoke_task'
/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake.rb:2029:in `top_level'
/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake.rb:2029:in `each'
/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake.rb:2029:in `top_level'
/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake.rb:2068:in `standard_exception_handling'
/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake.rb:2023:in `top_level'
/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake.rb:2001:in `run'
/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake.rb:2068:in `standard_exception_handling'
/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake.rb:1998:in `run'
/Library/Ruby/Gems/1.8/gems/rake-0.8.7/bin/rake:31
/usr/bin/rake:19:in `load'
/usr/bin/rake:19
Not sure where to start in diagnosing this. This has never happened before and I have used delayed job before to serialize model objects without any issues. Why this time?
Thanks in advance!
It's not really a deserialization error, it's an ActiveRecord record-not-found error on a simple Model.find(id) query.
If you want to know the details, log them in the delayed_job-2.1.3/lib/delayed/serialization/active_record.rb file, in the rescue statement, just before delayed-job stupidly raises the DeserializationError and throws the useful information away.
Michiel is right. Look at your handler field for objects like "!ruby/ActiveRecord:YourClassName"
Then check if objects can be retrieved via the primary key
From the console you can also test this out by doing something like:
# first job in your delayed queue
YAML.load(Delayed::Backend::ActiveRecord::Job.first.handler)
I believe this occurs when you run a job against an unsaved or deleted AR object since the deserialization for AR loads the record by id. An exception should probably be thrown if you attempt to delay a method on an unsaved AR object.
There's also a documented bug with DJ when the params passed into the handler field in the DB are longer than a standard TEXT column:
https://github.com/collectiveidea/delayed_job/issues/491
If this happens to be your problem, changing the column to a MEDIUMINT should fix the issue.
I did this in a migration like so:
change_column :delayed_jobs, :handler, :text, :limit => 16777215
ActiveRecord::Base.connection.execute("DELETE FROM delayed_jobs WHERE LENGTH(handler) >= 65535")
You can check to see if it's an issue with a simple DB query:
SELECT * FROM delayed_jobs WHERE LENGTH(handler) >= 65535
If anyone wants to make delayed_job just finish the job as a no-op you can monkey patch with this code in the initializer:
https://gist.github.com/spilliton/8494752
Today, I also suffered through this error and after doing hectic analysis found:
delayed_job converts methods & parameters to YAML format and stores it into database
It can be found using select * from delayed_jobs;
deserialization error occurs when delayed_job is not able to deserialize it.
Probable causes can be:
args["xyz"] used before calling delayed_job & inside worker using it as args[:xyz]
Sometimes extra arguments passed along with object to delayed_job that time delayed_job fails to build object as it is indifferent access.
I Hope this will help!
Sometimes when we upgrade libs delayed jobs still keep old references.
Try to find the id of delayed_job in logs and play to parse its handler to ruby to find the wrong reference
j = DelayedJob.find(XXX)
data = YAML.load_dj(j.handler)
data.to_ruby
I made a pull request to help with this problem.
Meanwhile you can use this lines
# config/initializers/delayed_job.rb
# Monkey patch to use old class references
module Psych
class << self; attr_accessor :old_class_references end
#old_class_references = {}
class ClassLoader
private
def find klassname
klassname = ::Psych.old_class_references[klassname] || klassname
#cache[klassname] ||= resolve(klassname)
end
end
module Visitors
class ToRuby < Psych::Visitors::Visitor
def revive klass, node
if klass.is_a? String
klassname = ::Psych.old_class_references[klass] || klass
klass = Kernel.const_get(klassname) rescue klassname
end
s = register(node, klass.allocate)
init_with(s, revive_hash({}, node), node)
end
end
end
end
# Add all old dependencies (hash keys) pointing to new references (hash values)
Psych.old_class_references = {
'ActiveRecord::AttributeSet' => 'ActiveModel::AttributeSet'
# ...
}
I'm maintaining a rails 2.1 application that has some unfortunate choices for column names. For instance, an Event has a start and an end date. Instead of using start_at and end_at the original design uses start and end. Of course this leads to
def end
read_attribute(:end) || 1.hour.from_now
end
I'm surprised this even parses. Is this legal ruby? The real issue is that erb is blowing up with 'stack level too deep' when running a backgroundrb job to send the reminder emails. The template is
<%= [#event.name, #event.when_pretty, #event.location, #event.association,
#event.notes].reject(&:blank?) * "\n" %>
If I deliver_reminder in the console there is no error, but when deliver_reminder is called during the background job, the error occurs.
Question: should I refactor to remove the end method, or is the stack error being caused by something else?
On line #1 of foo/mailer/reminder.rhtml
1: <%= [#event.name, #event.when_pretty, #event.location, #event.association, #event.notes].reject(&:blank?) * "\n" %>
lib/virtual_attributes_and_associations.rb:59:in `virtual_attribute_names'
lib/virtual_attributes_and_associations.rb:83:in `read_attribute_without_virtual'
lib/virtual_attributes_and_associations.rb:86:in `read_attribute'
vendor/rails/activerecord/lib/active_record/base.rb:2720:in `send'
vendor/rails/activerecord/lib/active_record/base.rb:2720:in `clone_attribute_value'
vendor/rails/activerecord/lib/active_record/dirty.rb:127:in `write_attribute'
vendor/rails/activerecord/lib/active_record/attribute_methods.rb:211:in `data='
lib/virtual_attributes_and_associations.rb:9:in `included'
vendor/rails/activesupport/lib/active_support/callbacks.rb:177:in `call'
vendor/rails/activesupport/lib/active_support/callbacks.rb:177:in `evaluate_method'
vendor/rails/activesupport/lib/active_support/callbacks.rb:161:in `call'
vendor/rails/activesupport/lib/active_support/callbacks.rb:93:in `run'
vendor/rails/activesupport/lib/active_support/callbacks.rb:92:in `each'
vendor/rails/activesupport/lib/active_support/callbacks.rb:92:in `send'
vendor/rails/activesupport/lib/active_support/callbacks.rb:92:in `run'
vendor/rails/activesupport/lib/active_support/callbacks.rb:272:in `run_callbacks'
vendor/rails/activerecord/lib/active_record/callbacks.rb:298:in `callback'
vendor/rails/activerecord/lib/active_record/base.rb:1450:in `send'
vendor/rails/activerecord/lib/active_record/base.rb:1450:in `instantiate'
vendor/rails/activerecord/lib/active_record/base.rb:582:in `find_by_sql'
vendor/rails/activerecord/lib/active_record/base.rb:582:in `collect!'
vendor/rails/activerecord/lib/active_record/base.rb:582:in `find_by_sql'
vendor/rails/activerecord/lib/active_record/base.rb:1341:in `find_every'
vendor/rails/activerecord/lib/active_record/base.rb:1376:in `find_one'
vendor/rails/activerecord/lib/active_record/base.rb:1362:in `find_from_ids'
vendor/rails/activerecord/lib/active_record/base.rb:537:in `find'
vendor/rails/activerecord/lib/active_record/associations/belongs_to_association.rb:44:in `find_target'
vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:196:in `load_target'
vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:99:in `reload'
vendor/rails/activerecord/lib/active_record/associations.rb:1084:in `contact'
lib/association.rb:52:in `associated_object'
lib/association.rb:48:in `association'
vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:177:in `send'
vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:177:in `method_missing'
app/views/foo/mailer/reminder.rhtml:1:in `_run_erb_47app47views47foo47mailer47reminder46rhtml'
Turns out the issue was with a library method called association, when I changed that to call associated_object (which was called by Association#association), the stack error no longer occurred.