2015-10-18 18 views
9

Tôi muốn đạt được các hành vi sau đây trong hành động điều khiển của tôi mà không có việc sử dụng mô-đun Timeout:Làm thế nào để đáp ứng yêu cầu Rails trong vòng một thời gian chờ có thể cấu hình

class AdminController < ApplicationController 
    def example 
    Timeout.timeout(params[:timeout].to_i) do 
     ... # try to process the request within params[:timeout] seconds 
    end 
    rescue Timeout::Error 
    render nothing: true, status: :gateway_timeout 
    end 
end 

Tôi muốn tránh việc sử dụng Timeout bởi vì nó gây ra nhiều lỗi trong ứng dụng của tôi, bao gồm rò rỉ kết nối cơ sở dữ liệu. Một số vấn đề khác được báo cáo tại: http://www.mikeperham.com/2015/05/08/timeout-rubys-most-dangerous-api/

+0

bạn đang thực sự làm gì trong yêu cầu này? Thời gian chờ là giải pháp kém cho vấn đề lớn hơn - bạn có thể tiền xử lý hoặc chuyển đổi một số mã đó thành công việc hoặc thậm chí tách một yêu cầu thành nhiều giai đoạn với máy trạng thái. – court3nay

+0

@ court3nay Đó là một dịch vụ web chạy các công việc có thể mất từ ​​100ms đến 30 giây để được xử lý. Mỗi khách hàng có thể chỉ định thời gian chờ có thể chấp nhận của riêng họ cho các công việc được yêu cầu. – barbolo

+0

@barbolo mã hiện tại của bạn có lỗi. Tốt nhất là hãy kết thúc thời gian chờ bên trong một khối 'bắt đầu', tiếp theo là' rescue => e'. Những gì bạn đang cố gắng để đạt được? Dừng yêu cầu nếu truy vấn mất quá nhiều thời gian? – onebree

Trả lời

4

Không sử dụng ruby ​​cho việc này. Vấn đề là mô-đun thời gian chờ sẽ hủy bỏ mã ở đâu đó, bất kỳ nơi nào trong mã thực thi của bạn, điều này sẽ dẫn đến các ổ cắm, kết nối và tệp đang mở và lủng lẳng hoặc tệ hơn. (Điều này không thực sự là vấn đề nếu bạn đang bắn lên một kịch bản bên ngoài hoặc bắn phá cho mỗi công việc, tôi đoán, nhưng trong những trường hợp đó chỉ cần sử dụng thời gian chờ io gốc Unix/Unix)

Đây là lý do tại sao máy chủ CI ruby ​​không bao giờ bị tắt (Jenkins là java). Tôi sẽ thiết kế điều này bằng một dịch vụ riêng biệt xử lý các công việc đang chạy mà bạn có thể ping bằng API; sau đó, theo quan điểm của bạn, hãy ping nó sau mỗi vài giây để họ có thể xem các cập nhật liên tục. Ứng dụng đường ray trong trường hợp này sẽ không cần phải có bất kỳ mã hết thời gian gây ô nhiễm nào trong đó.

chỉnh sửa: kể từ khi bạn đang làm các yêu cầu HTTP trong khối đó, chỉ cần sử dụng các thiết lập thời gian chờ xây dựng vào thư viện http (ví dụ https://github.com/lostisland/faraday)

+0

Cảm ơn bạn, @ court3nay. Tôi hy vọng sẽ chấp nhận một câu trả lời với một giải pháp trong Ruby thuần khiết. Hãy xem những gì tôi nhận được. – barbolo

+0

mã bên trong khối trông như thế nào? – court3nay

+0

Nó gửi một trình duyệt web. – barbolo

3

Bạn có thể sử dụng gem "rack-timeout"https://github.com/heroku/rack-timeout cho điền đầy đủ yêu cầu của bạn.

# Gemfile 

gem "rack-timeout" 

# config/initializers/rack_timeout.rb 
Rack::Timeout.timeout = 5 # seconds 

Hy vọng điều này sẽ giúp bạn.

+0

Đó thực sự là một viên ngọc khá tốt, nhưng không giải quyết được vấn đề của tôi. Nó không cho phép tôi chỉ định thời gian chờ cho mỗi yêu cầu. Nó hy vọng một giá trị cố định cho thời gian chờ được chỉ định trong quá trình khởi tạo ứng dụng. – barbolo

Các vấn đề liên quan