clemens / delocalize

Date/time and number parsing for Rails.

Home Page:http://www.railway.at

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

is localized_date_time_parser.rb thread safe?

shware opened this issue · comments

Hi,

From localized_date_time_parser.rb - line 64:

(@input_formats ||= {})[type] ||= I18n.t(:"#{type}.formats").slice(*I18n.t(:"#{type}.input.formats")).values

Is the use of a class variable (@input_formats) thread safe in Rails?

We've been using the plugin version of delocalize and when we released the app to production (Apache with Phusion Passenger) targeting a diverse user base (multiple cultures / locales) we immediately started getting reports dates being rejected.

If the user's locale used mm/dd/yyyy then occasionally 12/01/2011 (Dec 12 2011) was rejected. Same for dd/mm/yyyy - 01/12/2011 (Dec 01 2011 in UK).

I think the issue is Phusion Passenger "reuses" threads so the class variable @input_formats is sometimes already set from the last user thus treating a US user like a UK user.

After debugging we modified localized_date_time_parser to simply return the formats each time:

I18n.t(:"#{type}.formats", :locale => Thread.current[:current_locale]).slice(*I18n.t(:"#{type}.input.formats", :locale => Thread.current[:current_locale])).values

The Thread.current[:current_locale] is set in our application_controller for each request. This stopped the issue.

I'm not a Rails / Phusion Passenger threading expert so thought I'd pass along in case there's an issue in the gem / plugin or I'm going about things the wrong way.

Thanks for the great software and hope this helps.

Shawn

I think the problem is the use of a hash to memoize, I think the Hash class isn't thread-safe.
Why the need to pass the current locale?
Only removing the hash memoization didn't solve the problem?

I'm by no means an expert on multi threading, so I'm not sure if this is an issue with delocalize or something else.

However, to the best of my knowledge, i18n is thread safe. The current locale is part of the config which, according to the code, is put in Thread.current (see https://github.com/svenfuchs/i18n/blob/master/lib/i18n.rb#L17-38). If you don't explicitly supply a :locale, it automatically uses the one from Thread.current (see https://github.com/svenfuchs/i18n/blob/master/lib/i18n.rb#L147).

Can you give us information about your Rails and i18n gem versions?

Plain Ruby hashes are not thread-safe on VMs with real threads (Rubinius 2.0+ and JRuby) see https://rails.lighthouseapp.com/projects/8994/tickets/5340-rails-3-actionview-is-not-thread-safe and ruby-i18n/i18n#51. But can be considered thread safe on MRI 1.8/1.9, so my guess would be that the issue lies elsewhere.

I'm closing this as I'm assuming that it's fixed by @ralph's merged pull request.