Hatena::ブログ(Diary)

akimatter このページをアンテナに追加 RSSフィード

2012-01-13

developmentを実現したいのでコードを読んでみる#5

| 13:19 |  developmentを実現したいのでコードを読んでみる#5を含むブックマーク  developmentを実現したいのでコードを読んでみる#5のブックマークコメント

昨日ログを出力するように変更したrailsを使って、ほとんど素のrails3のアプリサーバの起動、GETリクエストx3サーバの停止までにActionDispatch::Reloaderの各メソッドがどのように呼びだされるのか、developmentとproductionの場合それぞれについて出力してみました。

https://github.com/akm/rails3_reloader_study/blob/master/actiondispatch_reloader_method_invocations_development.log

https://github.com/akm/rails3_reloader_study/blob/master/actiondispatch_reloader_method_invocations_production.log

production

起動時

ActionDispatch::Reloader.to_cleanup(&#<Proc:0x00000100e78410@/Users/akima/workspace/rails/railties/lib/rails/application/bootstrap.rb:55>)

module Rails
  class Application
    module Bootstrap
      include Initializable

    # (中略)

      initializer :set_clear_dependencies_hook, :group => :all do
        ActionDispatch::Reloader.to_cleanup do
          ActiveSupport::DescendantsTracker.clear
          ActiveSupport::Dependencies.clear
        end
      end

ActionDispatch::Reloader.to_prepare(&#<Proc:0x00000100e4e250@/Users/akima/workspace/rails/activesupport/lib/active_support/i18n_railtie.rb:21>)

module I18n
  class Railtie < Rails::Railtie

    # (中略)

    initializer "i18n.callbacks" do
      ActionDispatch::Reloader.to_prepare do
        I18n::Railtie.reloader.execute_if_updated
      end
    end

ActionDispatch::Reloader.prepare!

ActionDispatch::Reloader#initialize(nil)

module Rails
  class Application
    module Finisher
      include Initializable

      # (中略)

      initializer :run_prepare_callbacks do
        ActionDispatch::Reloader.prepare!
      end
module ActionDispatch
  class Reloader
    include ActiveSupport::Callbacks

    # (中略)

    # Execute all prepare callbacks.
    def self.prepare!
      self.trace_log(:prepare!)
      new(nil).run_callbacks :prepare
    end


GET /tests/foo?idx=1

ActionDispatch::Reloader.to_prepare(&#<Proc:0x00000102279838@/Users/akima/workspace/rails/railties/lib/rails/application/finisher.rb:63 (lambda)>)

module Rails
  class Application
    module Finisher
      include Initializable

      # (中略)

      initializer :set_routes_reloader do |app|
        reloader = lambda { app.routes_reloader.execute_if_updated }
        reloader.call
        ActionDispatch::Reloader.to_prepare(&reloader)
      end

ActionDispatch::Reloader.to_cleanup(&#<Proc:0x00000100e0ceb8@/Users/akima/workspace/rails/activerecord/lib/active_record/railtie.rb:83>)

ActionDispatch::Reloader.to_prepare(&#<Proc:0x00000100d3ccb8@/Users/akima/workspace/rails/activerecord/lib/active_record/railtie.rb:94>)

module ActiveRecord
  # = Active Record Railtie
  class Railtie < Rails::Railtie

    # (中略)

    initializer "active_record.set_dispatch_hooks", :before => :set_clear_dependencies_hook do |app|
      ActiveSupport.on_load(:active_record) do
        ActionDispatch::Reloader.to_cleanup do
          ActiveRecord::Base.clear_reloadable_connections!
          ActiveRecord::Base.clear_cache!
        end
      end
    end

    config.after_initialize do
      ActiveSupport.on_load(:active_record) do
        instantiate_observers

        ActionDispatch::Reloader.to_prepare do
          ActiveRecord::Base.instantiate_observers
        end
      end
    end

GET /tests/foo?idx=2

なし

GET /tests/foo?idx=3

なし

サーバを停止

なし

まとめ


development

起動時

ActionDispatch::Reloader.to_cleanup(&#<Proc:0x000001023916a8@/Users/akima/workspace/rails/railties/lib/rails/application/bootstrap.rb:55>)

ActionDispatch::Reloader.to_prepare(&#<Proc:0x00000100f58150@/Users/akima/workspace/rails/activesupport/lib/active_support/i18n_railtie.rb:21>)

これらはproductionと同じ。

ActionDispatch::Reloader#initialize(#<ActionDispatch::Callbacks:0x0000010421f318 @app=#<ActiveRecord::ConnectionAdapters::ConnectionManagement:0x0000010421f340 @app=.... )

  /Users/akima/workspace/rails/actionpack/lib/action_dispatch/middleware/stack.rb:112:in `build'
  /Users/akima/workspace/rails/railties/lib/rails/engine.rb:447:in `app'
module ActionDispatch
  class MiddlewareStack

    # (中略)

    def build(app = nil, &block)
      app ||= block
      raise "MiddlewareStack#build requires an app" unless app
      middlewares.reverse.inject(app) { |a, e| e.build(a) }
    end
module Rails
  class Engine < Railtie

    # (中略)

    def app
      @app ||= begin
        config.middleware = config.middleware.merge_into(default_middleware_stack)
        config.middleware.build(endpoint)
      end
    end

GET /tests/foo?idx=1

ActionDispatch::Reloader.prepare!

ActionDispatch::Reloader#initialize(nil)

これらはproductionの起動時に実行されるものと同じ

ActionDispatch::Reloader.to_prepare(&#<Proc:0x000001027b3358@/Users/akima/workspace/rails/railties/lib/rails/application/finisher.rb:63 (lambda)>)

productionのGET /tests/foo?idx=1で実行されるものと同じ


ActionDispatch::Reloader#call({"GATEWAY_INTERFACE"=>"CGI/1.1", "PATH_INFO"=>"/tests/foo", "QUERY_STRING"=>"idx=1", ...)

module Rack

  class Sendfile

    # (中略)

    def call(env)
      status, headers, body = @app.call(env)
      if body.respond_to?(:to_path)
        case type = variation(env)

ActionDispatch::Reloader.to_cleanup(&#<Proc:0x00000103355328@/Users/akima/workspace/rails/activerecord/lib/active_record/railtie.rb:83>)

ActionDispatch::Reloader.to_prepare(&#<Proc:0x0000010334c890@/Users/akima/workspace/rails/activerecord/lib/active_record/railtie.rb:94>)

productionのGET /tests/foo?idx=1で実行されるものと同じ


ActiveRecord::ConnectionAdapters::ConnectionManagement::Proxy#close

ActionDispatch::Reloader.cleanup!

ActionDispatch::Reloader#initialize(nil)

module Rack
  module Handler
      def service(req, res)

        # (中略)

        status, headers, body = @app.call(env)
        begin
          res.status = status.to_i
          headers.each { |k, vs|
            if k.downcase == "set-cookie"
              res.cookies.concat vs.split("\n")
            else
              # Since WEBrick won't accept repeated headers,
              # merge the values per RFC 1945 section 4.2.
              res[k] = vs.split("\n").join(", ")
            end
          }
          body.each { |part|
            res.body << part
          }
        ensure
          body.close  if body.respond_to? :close
        end
      end
module ActionDispatch
  class Reloader

    # (中略)

    # Execute all cleanup callbacks.
    def self.cleanup!
      self.trace_log(:cleanup!)
      new(nil).run_callbacks :cleanup
    end

    # (中略)

    module CleanupOnClose
      def close
        ActionDispatch::Reloader.trace_log_impl("#{self.class.name}#close")
        super if defined?(super)
      ensure
        ActionDispatch::Reloader.cleanup!
      end
    end


GET /tests/foo?idx=2

ActionDispatch::Reloader#call({"GATEWAY_INTERFACE"=>"CGI/1.1", "PATH_INFO"=>"/tests/foo", "QUERY_STRING"=>"idx=2", ...)

GET /tests/foo?idx=3

ActiveRecord::ConnectionAdapters::ConnectionManagement::Proxy#close

ActionDispatch::Reloader.cleanup!

ActionDispatch::Reloader#initialize(nil)

ActionDispatch::Reloader#call({"GATEWAY_INTERFACE"=>"CGI/1.1", "PATH_INFO"=>"/tests/foo", "QUERY_STRING"=>"idx=3", ...)


サーバを停止

ActiveRecord::ConnectionAdapters::ConnectionManagement::Proxy#close

ActionDispatch::Reloader.cleanup!

ActionDispatch::Reloader#initialize(nil)

トラックバック - http://d.hatena.ne.jp/akm/20120113
最近読んだ本
  • 情熱プログラマー ソフトウェア開発者の幸せな生き方
  • 禁煙セラピー[セラピーシリーズ]
  • 入門git
  • 入門Git
  • もやしもん(8) (イブニングKC)
  • JRuby 徹底入門
  • 入門Subversion―Windows/Linux対応
  • Ship It! ソフトウェアプロジェクト 成功のための達人式ガイドブック
  • プログラミングRuby 第2版 言語編
  • プログラミングRuby 第2版 ライブラリ編