Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jruby 1.7.16 and 4.2.0.beta2 ActiveSupport::Duration issue #2041

Closed
petergoldstein opened this issue Oct 12, 2014 · 10 comments
Closed

jruby 1.7.16 and 4.2.0.beta2 ActiveSupport::Duration issue #2041

petergoldstein opened this issue Oct 12, 2014 · 10 comments

Comments

@petergoldstein
Copy link

In Rails 4.2 a new class, ActiveSupport::Duration was introduced. So where previously an expression like:

`7.days`

would have type Fixnum, it now has type ActiveSupport::Duration. As you'd expect, calling to_i on the ActiveSupport::Duration object gives you the old Fixnum value.

With JRuby 1.7.16 I'm seeing an issue using pack with arrays containing ActiveSupport::Duration objects. Specifically, if I do the following:

require 'active_support/core_ext/numeric/time'
[7.days].pack('N')

I get an error that looks like this:

TypeError: can't convert ActiveSupport::Duration into Integer
  from org/jruby/RubyArray.java:4125:in `pack'
  from (irb):2:in `evaluate'
  from org/jruby/RubyKernel.java:1101:in `eval'
  from org/jruby/RubyKernel.java:1501:in `loop'
  from org/jruby/RubyKernel.java:1264:in `catch'
  from org/jruby/RubyKernel.java:1264:in `catch'

Now one can certainly argue that this isn't a JRuby problem, it's a Rails issue. But:

  1. MRI handles this transparently
  2. This has a wide impact as it comes up whenever code sends a value like 7.days to be serialized. So it impacts ActiveRecord, Dalli, etc.

So ideally it would be nice if JRuby handled this transparently. Any thoughts?

@chrisseaton
Copy link
Contributor

JRuby should handle this - I think it's a bug in packing rather than a JRuby limitation.

Specifically it might be related to how Duration defers a lot to its @value - see https://github.com/rails/rails/blob/51278579477eb7ee20fe2aba53b4b13203791b22/activesupport/lib/active_support/duration.rb#L37-L44 and https://github.com/rails/rails/blob/51278579477eb7ee20fe2aba53b4b13203791b22/activesupport/lib/active_support/duration.rb#L102-L104.

The JRuby pack code isn't something I know well and it's quite complicated, but I would guess that MRI is using a more general type check and method lookup in converting the object to a Fixnum and maybe JRuby is doing something a little more rigid.

I couldn't immediately reduce the Duration class to reproduce in a simpler test case.

Thanks very much for the bug report.

@chrisseaton
Copy link
Contributor

Minimal test case:

class Test
  def method_missing(method, *args, &block)
    14.send(method, *args, &block)
  end
end

p [Test.new].pack('N')

@chrisseaton
Copy link
Contributor

Duration doesn't defer respond_to to @value like it does method_missing.

It looks like JRuby checks respond_to before calling to_i https://github.com/jruby/jruby/blob/master/core/src/main/java/org/jruby/util/TypeConverter.java#L60, which also seems to be what MRI does (via rb_check_funcall), so I'm not sure how it works in MRI.

@petergoldstein
Copy link
Author

@chrisseaton It looks like that issue may have been fixed since Rails 4.2.0 beta 2. See this commit - rails/rails@f976751 . Let me run the same tests against Rails master and see if the problem is resolved.

@chrisseaton
Copy link
Contributor

Ok - we still have a different in behaviour for my test case though - so whether or not that Rails class works there is still a bug here.

@petergoldstein
Copy link
Author

So it doesn't work with master rails, even though the respond_to? call is properly deferred. From my tests:

irb(main):019:0> require 'active_support/core_ext/numeric/time'
=> false
irb(main):020:0> [7.days].pack('N')
TypeError: can't convert ActiveSupport::Duration into Integer
   from org/jruby/RubyArray.java:4125:in `pack'
   ...
irb(main):022:0* 7.days.respond_to?(:to_i)
=> true
irb(main):023:0* 7.days.respond_to?(:to_int)
=> true

@chrisseaton
Copy link
Contributor

I'll wait for someone from the core team to weigh in on this - they will probably understand quicker than I how this conversion to integer is supposed to work and what the problem is likely to be.

@petergoldstein
Copy link
Author

@chrisseaton Sounds good. Thanks for investigating.

@rtyler
Copy link

rtyler commented Aug 7, 2015

This smells like it might be related to #1856

@kares
Copy link
Member

kares commented Mar 2, 2018

this bug has been fixed, somewhere along the line of JRuby 1.7.x releases :

jruby-1.7.25 :001 > require 'active_support/core_ext/numeric/time'
 => true 
jruby-1.7.25 :002 > ActiveSupport::VERSION::STRING
 => "4.2.8" 
jruby-1.7.25 :005 > 7.days.class
 => ActiveSupport::Duration 
jruby-1.7.25 :006 > [7.days].pack('N')
 => "\x00\t:\x80" 

@kares kares closed this as completed Mar 2, 2018
@kares kares added this to the JRuby 1.7.26 milestone Mar 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants