2012-01-26 36 views
7

Tôi có một ứng dụng chạy trên Heroku, thỉnh thoảng, báo cáo Hết thời gian :: Lỗi(ActionView :: Template :: Error) "thực thi hết hạn".Xử lý TimeOut :: Lỗi khi thử lại

Điều này xảy ra trên toàn bộ trang web (nghĩa là không có trong một bộ điều khiển cụ thể) nên tôi muốn tạo một hàm sẽ xử lý hai lỗi này, trước tiên bằng cách thử lại hai lần và chuyển hướng người dùng đến trang sẽ cho họ biết máy chủ bận.

kế hoạch hiện tại của tôi là sử dụng sau trong ApplicationController:

rescue_from Timeout::Error, :with => :rescue_from_timeout 

    def rescue_from_timeout 
    sleep 2 
    retry 
    end 

nhưng điều này sẽ chỉ lặp và vòng lặp. Tôi muốn nó phá vỡ sau hai lần thử. Làm thế nào tôi có thể làm điều đó?

Ngoài ra, Làm cách nào để xử lý ActionView :: Mẫu :: Lỗi cho "thực thi đã hết hạn"? Tôi không muốn giải cứu tất cả các ActionView :: Template :: Lỗi với retries, chỉ có những người khiêu khích "thực hiện hết hạn".

Đây là những gì ngoại trừ tôi nói:

[Exception] home#index (ActionView::Template::Error) "execution expired" 

hoặc

[Exception] calculations#result (ActionView::Template::Error) "Timeout::Error: execution expired 

Câu hỏi của tôi, như sau: Làm thế nào tôi có thể xử lý hai loại lỗi bằng cách thử lại lần đầu tiên hai lần và sau đó ném một ngoại lệ/chuyển hướng đến trang lỗi?

+1

Tại sao ngoại lệ này được nâng lên? Bạn đã triển khai một số tác vụ dài hạn, ứng dụng của bạn có phụ thuộc vào dịch vụ web bên ngoài không? – Jef

Trả lời

15

Xác định phương pháp này:

def retryable(options = {}) 
    opts = { :tries => 1, :on => Exception }.merge(options) 

    retry_exception, retries = opts[:on], opts[:tries] 

    begin 
    return yield 
    rescue retry_exception 
    if (retries -= 1) > 0 
     sleep 2 
     retry 
    else 
     raise 
    end 
    end 
end 

Và gọi với điều này:

retryable(:tries => 10, :on => Timeout::Error) do 
    your_code_here 
end 

Bạn có thể đặt điều này trong một around_filter trong bộ điều khiển ứng dụng, đó là lớp cơ sở cho tất cả các bộ điều khiển trong một đường ray ứng dụng:

class ApplicationController < ActionController::Base 

    around_filter :retry_on_timeout 

    def retry_on_timeout 
    retryable(:tries => 10, :on => Timeout::Error) do 
     yield 
    end 
    end 
end 
+1

Cảm ơn, Douglas. Tôi, tuy nhiên không chắc chắn nơi/làm thế nào để sử dụng mã gọi. Nếu tôi muốn sử dụng nó để nó bắt lỗi này trên tất cả các trang web tôi sẽ đoán tôi sẽ có một cái gì đó gọi là trong ứng dụng điều khiển như một before_filter hoặc một cái gì đó. Tôi có cần phải quấn từng bộ điều khiển với chức năng có thể thử lại không? Bạn có thể vui lòng xây dựng trên làm thế nào tôi có thể sử dụng này để bắt lỗi trên tất cả các trang web (tất cả các bộ điều khiển/xem). – Christoffer

+0

Tôi đã chỉnh sửa câu trả lời bằng cách sử dụng bộ lọc xung quanh trong ApplicationController. Điều này có áp dụng cho bạn không? –

+0

Tôi không thể kiểm tra nó khác hơn bằng cách giữ nó trực tuyến trong một vài ngày và xem nếu nó loại bỏ các thông báo lỗi, nhưng nó có vẻ là làm việc. Hoặc, có cách nào để kích động một TimeoutError để tôi có thể kiểm tra nó? – Christoffer

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