chikaram
chikaram

Reputation: 740

How to set timeout for a particular URL in rails

I use rack-timeout and it works fine. But I couldn't figure out how to set time for a particular URL.

Even if I do like:

map '/foo/bar' do
  Rack::Timeout.timeout = 10
end

not only /foo/bar action but every action dies after 10 second.

Is it possible to set timeout for a particular URL? Or should I use another solution other than rack-timeout?

Upvotes: 5

Views: 5105

Answers (3)

lion.vollnhals
lion.vollnhals

Reputation: 1802

Updated version of Jiten Kothari's answer:

module Rack
  class Timeout
    @excludes = [
      '/statistics',
    ]

    class << self
      attr_accessor :excludes
    end

    def call_with_excludes(env)
      #puts 'BEGIN CALL'
      #puts  env['REQUEST_URI']
      #puts 'END CALL'

      if self.class.excludes.any? {|exclude_uri| /\A#{exclude_uri}/ =~ env['REQUEST_URI']}
        @app.call(env)
      else
        call_without_excludes(env)
      end
    end

    alias_method_chain :call, :excludes

  end
end

Upvotes: 2

jimagic
jimagic

Reputation: 4065

put this code as timeout.rb under config/initializers folder and put your particular url on excludes array

require RUBY_VERSION < '1.9' && RUBY_PLATFORM != "java" ? 'system_timer' : 'timeout'
SystemTimer ||= Timeout

module Rack
  class Timeout
    @timeout = 30
    @excludes = ['your url here',
                 'your url here'
    ]

    class << self
      attr_accessor :timeout, :excludes
    end

    def initialize(app)
      @app = app
    end

    def call(env)
      #puts 'BEGIN CALL'
      #puts  env['REQUEST_URI']
      #puts 'END CALL'

      if self.class.excludes.any? {|exclude_uri| /#{exclude_uri}/ =~ env['REQUEST_URI']}
        @app.call(env)
      else
        SystemTimer.timeout(self.class.timeout, ::Timeout::Error) { @app.call(env) }
      end
    end

  end
end

Upvotes: 1

Lawson Kurtz
Lawson Kurtz

Reputation: 636

If you're worried about particular actions running too long, I would wrap the code of concern in a Timeout block instead of trying to enforce timeouts on a URL level. You could easily wrap up the below into a helper method and use it with a variable timeout throughout your controllers.

require "timeout'"
begin
  status = Timeout::timeout(10) {
  # Potentially long process here...
}
rescue Timeout::Error
  puts 'This is taking way too long.'
end

Upvotes: 7

Related Questions