2

画像用に Amazon s3 に基づく別のリモート ストレージを使用しています。activeadmin によるレコードの更新 イメージの更新中に不明なエラーが発生しました。これは、スタックトレースの Rails エラーではありませんでしたが、ステージ環境で何らかのタイムアウトが発生しました。

config/initializers/carrierwave.rb

CarrierWave.configure do |config|
  config.storage = :fog

  config.fog_credentials = {
    :provider               => 'AWS',             
    :aws_access_key_id      => APP['s3']['key'],      
    :aws_secret_access_key  => APP['s3']['secret'],   
  }
  config.fog_directory    = 'mdfile'  
  config.fog_public       = false   
  config.fog_authenticated_url_expiration = 5

  config.cache_dir = File.join(Rails.root, 'tmp', 's3', Rails.env)  
end

app/uploaders/news_image_uploader.rb

class NewsImageUploader < Mdfile::BaseUploader
  include CarrierWave::MiniMagick

  process :resize_to_fill => [150, 112]
  process convert: 'png'

  def extension_white_list
    APP['upload']['image_white_list']
  end

  def fog_public
    true
  end

  def filename
    "image.png" if original_filename
  end
end

アプリ/アップローダー/mdfile/base_uploader.rb

module Mdfile
  class BaseUploader < CarrierWave::Uploader::Base

    before :store, :remember_cache_id
    before :cache, :remove_old_file_before_cache

    def remember_cache_id(new_file)
      @cache_id_was = cache_id
    end

    def remove_old_file_before_cache(new_file)
      remove! unless blank?
    end

    def store_dir
      "uploads/#{Rails.env}/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
    end

    def filename
      if original_filename 
        @name ||= Digest::MD5.hexdigest(File.dirname(current_path))
        "#{@name}.#{file.extension}"
      end
    end
  end
end

モデル (ニュース、記事) に割り当てられたすべての画像は、特別なパス上のリモート s3 に保存されます: uploads/stage/article/image/691/image.png

私は調査を行い、s3 とホスト間のリクエストとレスポンスを記録するために EXCON_DEBUG=true でレールを実行しました。確認したところ

新しいレコードの作成時:

Excon は、以下にダンプされた 1 つの PUT 要求を送信します

excon.request  {:chunk_size=>1048576, :connect_timeout=>60, :headers=>{"User-Agent"=>"fog/1.9.0", "Content-Length"=>37593, "Content-Type"=>"image/jpeg", "x-amz-acl"=>"public-read", "Date"=>"Wed, 14 Aug 2013 08:49:52 +0000", "Authorization"=>"REDACTED", "Host"=>"mdfile.s3.amazonaws.com:443"}, :idempotent=>true, :instrumentor_name=>"excon", :nonblock=>true, :read_timeout=>60, :retry_limit=>4, :ssl_verify_peer=>true, :uri_parser=>URI, :write_timeout=>60, :host=>"mdfile.s3.amazonaws.com", :path=>"/uploads%2Fdevelopment%2Fnews%2Fimage%2F692%2Fimage.png", :port=>"443", :query=>nil, :scheme=>"https", :user=>nil, :password=>"REDACTED", :instrumentor=>Excon::StandardInstrumentor, :body=>#<File:/local/path/to/cached/file/20130814-1249-6113-6726/Reaktor.jpg>, :expects=>200, :method=>"PUT", :retries_remaining=>4 }

excon.response  {:body=>"", :headers=>{ "Date"=>"Wed, 14 Aug 2013 08:49:53 GMT", "Content-Length"=>"0", "Server"=>"AmazonS3"}, :status=>200, :remote_ip=>"[XXX.XXX.XXX.XXX]"}

私はいくつかのプライベートで役に立たないフィールドをカットしました。

既存のレコードの更新時:

Excon は、古いイメージを消去するために 1 つの DELETE 要求を送信し、次に path="/" (wtf!! ) の GET 要求を送信し、GET 要求と成功応答の無限ループに陥ります。

excon.request  {:chunk_size=>1048576, :connect_timeout=>60, :headers=>{"User-Agent"=>"fog/1.9.0", "Date"=>"Wed, 14 Aug 2013 08:56:47 +0000", "Authorization"=>"REDACTED", "Host"=>"mdfile.s3.amazonaws.com:443"}, :idempotent=>true, :instrumentor_name=>"excon", :mock=>false, :nonblock=>true, :read_timeout=>60, :retry_limit=>4, :ssl_verify_peer=>true, :uri_parser=>URI, :write_timeout=>60, :host=>"mdfile.s3.amazonaws.com", :path=>"/uploads%2Fdevelopment%2Fnews%2Fimage%2F692%2Fimage.png", :port=>"443", :query=>nil, :scheme=>"https", :user=>nil, :password=>"REDACTED", :family=>0, :expects=>204, :method=>"DELETE", :retries_remaining=>4, :connection=>#<Excon::Connection:b2ee900 @data={:chunk_size=>1048576, :connect_timeout=>60, :headers=>{"User-Agent"=>"fog/1.9.0"}, :idempotent=>false, :instrumentor_name=>"excon", :mock=>false, :nonblock=>true, :read_timeout=>60, :retry_limit=>4, :ssl_verify_peer=>true, :uri_parser=>URI, :write_timeout=>60, :host=>"s3.amazonaws.com", :path=>"/", :port=>"443", :query=>nil, :scheme=>"https", :user=>nil, :password=>nil, :instrumentor=>Excon::StandardInstrumentor, :family=>0} @socket_key="s3.amazonaws.com:443">, :mock=>false, :nonblock=>true, :read_timeout=>60, :retry_limit=>4, :ssl_verify_peer=>true, :uri_parser=>URI, :write_timeout=>60, :host=>"s3.amazonaws.com", :path=>"/", :port=>"443", :query=>nil, :scheme=>"https", :user=>nil, :password=>nil, :instrumentor=>Excon::StandardInstrumentor, :family=>0} @socket_key="s3.amazonaws.com:443">>>>>}

excon.response  {:body=>"", :headers=>{"Date"=>"Wed, 14 Aug 2013 08:56:48 GMT", "Server"=>"AmazonS3"}, :status=>204, :remote_ip=>"[XXX.XXX.XXX.XXX]"}

excon.request  {:chunk_size=>1048576, :connect_timeout=>60, :headers=>{"User-Agent"=>"fog/1.9.0", "Date"=>"Wed, 14 Aug 2013 08:56:48 +0000", "Authorization"=>"REDACTED", "Host"=>"s3.amazonaws.com:443"}, :idempotent=>true, :instrumentor_name=>"excon", :mock=>false, :nonblock=>true, :read_timeout=>60, :retry_limit=>4, :ssl_verify_peer=>true, :uri_parser=>URI, :write_timeout=>60, :host=>"s3.amazonaws.com", :path=>"/", :port=>"443", :query=>nil, :scheme=>"https", :user=>nil, :password=>"REDACTED", :instrumentor=>Excon::StandardInstrumentor, :family=>0, :expects=>200, :method=>"GET", :url=>"s3.amazonaws.com", :ssl_verify_peer=>true, :uri_parser=>URI, :write_timeout=>60, :host=>"s3.amazonaws.com", :path=>"/", :port=>"443", :query=>nil, :scheme=>"https", :user=>nil, :password=>nil, :instrumentor=>Excon::StandardInstrumentor, :family=>0} @socket_key="s3.amazonaws.com:443">}

excon.response  {:body=>"", :headers=>{"Date"=>"Wed, 14 Aug 2013 08:56:50 GMT", "Content-Type"=>"application/xml", "Transfer-Encoding"=>"chunked", "Server"=>"AmazonS3"}, :status=>200, :remote_ip=>"[XXX.XXX.XXX.XXX]"}

したがって、kill -9 を使用して localhost で Rails プロセスを停止できます。

次に、CarrierWave ロジックを呼び出すモデル (News,Articles...) の update_attribute(s) メソッドで、このような動作が発生することを明らかにしました。

質問:carrierwave/fog が奇妙な GET リクエストを作成し、エンドレス ループにロールダウンするのはなぜですか?

  • レール3.2.14
  • アクティブアドミン 0.5.1
  • inherited_resources 1.4.1
  • 搬送波 0.8.0
  • 霧 1.9.0
  • エクスコン 0.20.1

更新:アップローダーの列 (私の場合は「画像」) を update 属性の前に nil 値で更新すると、正しい PUT 要求が s3 に送信されることがわかりました。したがって、activeadmin コントローラーのバグ修正コードは次のとおりです。

controller do

  def update
    resource_object = resource_class
    @object = resource_object.find(params[:id])
    object_sym = resource_class.to_s.downcase.to_sym
    @object.update_column(:image, nil) if @object.respond_to?(:image) && params[object_sym][:image].present?
    update!
  end

end 

しかし、質問はまだ話題です。

4

0 に答える 0