mhfs/devise-async

failure in jruby

Closed this issue · 7 comments

jjb commented

I'm using sidekiq, rails 4.

Everything works well under MRI 2.1. In JRuby 1.7.6, I get this:

NoMethodError: undefined method `devise_mailer' for #<User:0x1e077d66>

I'm exploring what the problem could be. The full stack trace is below.

2013-11-20T21:11:17Z 51784 TID-6gc ERROR: Sidekiq::Processor crashed!
NoMethodError: undefined method `devise_mailer' for #<User:0x1e077d66>

org/jruby/RubyBasicObject.java:1497:in `method_missing'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/activemodel-4.0.1/lib/active_model/attribute_methods.rb:436:in `method_missing'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/activerecord-4.0.1/lib/active_record/attribute_methods.rb:155:in `method_missing'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/rolify-3.2.0/lib/rolify/role.rb:73:in `method_missing'
org/jruby/RubyKernel.java:1958:in `public_send'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/activesupport-4.0.1/lib/active_support/core_ext/object/try.rb:45:in `try'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/devise-async-0.9.0/lib/devise/async/backend/base.rb:22:in `mailer_class'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/devise-async-0.9.0/lib/devise/async/backend/base.rb:16:in `perform'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/processor.rb:48:in `process'
org/jruby/RubyProc.java:271:in `call'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/middleware/chain.rb:119:in `invoke'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/rollbar-0.11.8/lib/rollbar/sidekiq.rb:7:in `call'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/middleware/chain.rb:121:in `invoke'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/newrelic_rpm-3.6.9.171/lib/new_relic/agent/instrumentation/sidekiq.rb:30:in `call'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/newrelic_rpm-3.6.9.171/lib/new_relic/agent/instrumentation/controller_instrumentation.rb:339:in `perform_action_with_newrelic_trace'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/newrelic_rpm-3.6.9.171/lib/new_relic/agent/instrumentation/sidekiq.rb:21:in `call'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/middleware/chain.rb:121:in `invoke'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/middleware/server/active_record.rb:6:in `call'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/middleware/chain.rb:121:in `invoke'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/middleware/server/retry_jobs.rb:62:in `call'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/middleware/chain.rb:121:in `invoke'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/middleware/server/logging.rb:11:in `call'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/logging.rb:22:in `with_context'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/middleware/server/logging.rb:7:in `call'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/middleware/chain.rb:121:in `invoke'
org/jruby/RubyProc.java:271:in `call'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/middleware/chain.rb:124:in `invoke'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/processor.rb:47:in `process'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/processor.rb:102:in `stats'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/processor.rb:46:in `process'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/processor.rb:83:in `do_defer'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/sidekiq-2.16.1/lib/sidekiq/processor.rb:37:in `process'
org/jruby/RubyKernel.java:1961:in `public_send'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/celluloid-0.15.2/lib/celluloid/calls.rb:25:in `dispatch'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/celluloid-0.15.2/lib/celluloid/calls.rb:122:in `dispatch'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/celluloid-0.15.2/lib/celluloid/actor.rb:322:in `handle_message'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/celluloid-0.15.2/lib/celluloid/actor.rb:416:in `task'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/celluloid-0.15.2/lib/celluloid/tasks.rb:55:in `initialize'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/celluloid-0.15.2/lib/celluloid/tasks.rb:47:in `initialize'
/Users/john/.rbenv/versions/jruby-1.7.6/lib/ruby/gems/shared/gems/celluloid-0.15.2/lib/celluloid/tasks/task_fiber.rb:13:in `create'
jjb commented

Seems to be a devise issue. I'll update this ticket shortly.

jjb commented

I am running jruby in 1.9 mode, and MRI is 2.1. This issue seems to be in the difference between how 1.9 and 2.1 treat protected methods.

jjb commented

okay, I figured it out: https://gist.github.com/jjb/7571621

I'm talking to jruby folks to see what they think. I'll submit a pull request shortly.

@jjb This approach will break #39. However, if you do not need multiple mailers this should work.

That the mailer selection works on MRI 1.9.3 seems to be due to :public_send not doing what it is advertising.
Since try uses :public_send to do its magic this leads to different results on different rubies:

As a simple test i used this:

require 'active_support/core_ext/object/try'

class User
  protected
  def test_method
    puts "Hello World"
  end
end
puts User.new.respond_to?(:test_method)
User.new.try(:test_method)

For MRI 1.9.3 I get this:

true
Hello World

Shouldn't be since test_method is a protected method

For MRI 2.0.0 I get:

false

Which is due to :respond_to? no longer returning true for protected methods. Thus :try never uses :public_send

For JRuby in 1.9 Mode I get

true
NoMethodError: protected method `test_method' called for #<User:0x6d430f4e>

Which is expected since we are calling on a protected method.

So the whole devise_mailer thing works because 1.9.3 ignores the protected attribute of the default devise_mailer implementation included with Devise Authenticable.

Since the examples work with a public devise_mailer method I guess the correct way would be to not use :try and resort to checking with :public_method_defined?.

jjb commented

looks like issue is fixed by this commit:

52c483b

image

@jjb Great!

Could somebody else confirm this?