Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

models are not loaded in migrations when config.threadsafe! is set

#2506
  • Make a new rails project
  • Make a new model, and refer to the model somewhere in the migration
  • Enable config.threadsafe! in production mode, and migrate in production mode

ex ruby script/generate resource Test


class CreateTests < ActiveRecord::Migration
  def self.up
    Test

    create_table :tests do |t|

      t.timestamps
    end
  end

  def self.down
    drop_table :tests
  end
end

and config/environments/production.rb has


# Enable threaded mode
config.threadsafe!

rake db:migrate RAILS_ENV=production produces


(in /Users/andrewroth/Development/test_models_in_migration)
==  CreateTests: migrating ====================================================
rake aborted!
An error has occurred, this and all later migrations canceled:

uninitialized constant CreateTests::Test

(See full trace by running task with --trace)

without threadsafe! it loads Test correctly.

Reported by Andrew Roth · April 16th, 2009 @ 04:14 AM

State: wontfix
Milestone: 2.x
Assigned to: josh josh
Importance: none

Activity

  1. calavera
    calavera

    the threadsafe option in production doesn't load the dependencies, you can configure it to load them with this option in your production.rb just after config.threadsafe!

    config.dependency_loading = true
    

    but I don't know how rails can behave with both options enabled in production

    May 28th, 2009 @ 05:00 PM

  2. thedarkone
    thedarkone

    I'm pretty sure config.threadsafe! auto-requires all *.rb files it can find in your app on start up.

    May 29th, 2009 @ 09:19 AM

  3. calavera
    calavera

    @thedarkone take a look at the threadsafe! source code:

    # Enable threaded mode. Allows concurrent requests to controller actions and
    # multiple database connections. Also disables automatic dependency loading
    # after boot, and disables reloading code on every request, as these are
    # fundamentally incompatible with thread safety.
        def threadsafe!
          self.preload_frameworks = true
          self.cache_classes = true
          self.dependency_loading = false
          self.action_controller.allow_concurrency = true
          self
        end
    

    with dependency_loading = false rails doesn't autoload dependencies and models are a dependency of migrations

    May 29th, 2009 @ 09:42 AM

  4. thedarkone
    thedarkone

    Automatic dependency loading is not thread safe, that's why it is being disabled.

    Also checkout what happens in load_application_classes method if cache_classes is set to true.

    May 30th, 2009 @ 04:48 PM

  5. Pratik
    Pratik
    • Assigned user set to josh

    May 30th, 2009 @ 05:38 PM

  6. josh
    josh
    • State changed from new to wontfix

    I don't think there is a good fix here. The real issue is that turning off dependency_loading doesn't allow "magic" loading after boot. I would suggest requiring the models the you need in the migration, or better including the model definition again so the migration doesn't depend on its existence.

    June 9th, 2009 @ 03:07 PM

  7. Reto
    Reto
    • Tag changed from 2.3.2, migrations to 2.3.4, migrations

    Could we add a warning about that problem somewhere near the config in environments/production.rb? Or perhaps even in the actual 'const missing' error message? 'This might be caused by the fact that you running your application in threadsafe! mode. Please require all dependencies explictily.

    I could set up a proposel version on github, if you guys would support one of these measures.

    July 27th, 2009 @ 01:30 PM

  8. Andrew Roth
    Andrew Roth

    Wouldn't that break lots of existing migrations?

    What about making threadsafe! not be applied when doing migrations? Even if it's set in the config file. It really only benefits long-running apps, no?

    July 28th, 2009 @ 08:19 PM

  9. Reto
    Reto

    Or could we even force a non-threadsafe environment for rake tasks? It doesn't make sense to be threadsafe there anyway.

    July 28th, 2009 @ 08:19 PM

  10. Andrew Roth
  11. Reto
    Reto

    lol, what a coincidence :).

    "Wouldn't that break lots of existing migrations": No, why? I would only extend the text message of the 'no such constant' exception, of course only when the threadsafe option has been set. And perhaps only the first time.

    July 28th, 2009 @ 08:30 PM

  12. Andrew Roth
    Andrew Roth

    Regardless, you said yourself it at least doesn't make sense. But it would make every migration that accesses a model invalid for any application that uses threadsafe!

    July 28th, 2009 @ 09:42 PM

  13. Reto
    Reto

    hmm, I think I can't follow you? What exactly would make these migrations invalid? If they used to avoid that problem by explicitly require models then they shouldn't notice the difference. Or what do you mean?

    July 29th, 2009 @ 10:30 AM

  14. Andrew Roth
    Andrew Roth

    What I mean is that right now, people are writing migrations that access models. I've done it myself when using a legacy database to get a table name, ex. add_column Person.table_name, ... or maybe to repair some inconsistent data put in by a bug, like orphaned or duplicate rows.

    What it comes down to is whether the solution is to make people require models in migrations, or make migration loading work in migrations (when threadsafe! is on). I would say that being able to access models in migration is reasonable, and being widely used right now, so the proper way to fix this is to make model accesses work in migrations. The simplest way I can think of to do that is to disable threadsafe mode when migrating somehow.

    Of course, an explanation in the error message is better than nothing though.

    August 18th, 2009 @ 03:45 AM

  15. Ryan Daigle
    Ryan Daigle

    I'm experiencing this behavior with rake tasks as well. This would seem to be more problematic since there's no philosophical opposition to referencing models within rake tasks?

    My specific scenario is that I have a rake bootstrap task that sets up some default system data. Even when depending on the :environment task to load everything up for me, my models aren't found within the rake task unless explicitly required. Disabling config.threadsafe! fixes the reference issues.

    October 21st, 2009 @ 04:35 PM