Есть ли в Rails способ обойти спасение_от?

Я пытаюсь сделать удобное и безопасное восстановление для Redis в Rails. Я использую встроенный redis_cache_store и установил reconnect_attempts, но я хотел бы отправить пользователя на настраиваемую страницу ошибок в случае, если Redis остается недоступным, а не застревать на неотвечающей странице, не зная, что происходит на.

То, что я пытался, состояло в том, чтобы обезобразить метод failsafe в RedisCacheStore, повторно вызвав новый тип ошибки, RedisUnavailableError, который затем получил мой application_controller catch и redirect_to статическую страницу 500.

Где это ломается, так это в том, что я хотел бы, чтобы мое приложение просто останавливалось после перенаправления. На приведенной ниже трассировке byebug видно, что перед вторым последним блоком, который я включил, достигается строка redirect.

Но это не останавливается; Я включил только первый из длинной последовательности дополнительных вызываемых методов, которые в конечном итоге приводят к еще одной попытке записи в Redis, которая все еще не работает, которая затем повторно вызывает ту же самую последовательность исключений, которую Rails затем не поймает. время (на самом деле, даже если бы это было так, это был бы бесконечный цикл).

Итак, мой вопрос: есть ли способ заставить блок rescue_from просто остановиться и не продолжать запускать что-либо еще после достижения определенной строки?

В качестве альтернативы, есть ли способ на лету «отключить» Redis или изменить хранилище/настройки кеша на какое-то нулевое значение в блоке rescue_from, чтобы что-либо, что в дальнейшем запускалось, не пыталось связаться с Redis?

    [40, 49] in (DELETED)/redis_failsafe.rb
       40:   rescue ::Redis::BaseConnectionError => e
       41:     byebug
       42:     handle_exception(exception: e, method: method, returning: returning)
       43:     returning
       44:     byebug
    => 45:     raise RedisUnavailableError
       46:     # Re-raise the exception when reconnect attempt fails, so our application controller can handle it.
       47:   end
       48: end
       49: 
    (byebug) c

    [INFO][15:50:51] [3cf7] [GET] [(DELETED):3000] [/suppliers] 
    ∙ Redirecting to 500 page due to: RedisUnavailableError

    [30, 39] in /(DELETED)/application_controller.rb
       30:   authorize_resource class: false
       31: 
       32:   rescue_from RedisUnavailableError do |exception|
       33:     byebug
       34:     Rails.logger.info "Redirecting to 500 page due to: #{exception.message}"
    => 35:     redirect_to '/500.html'
       36:     byebug
       37:   end
       38: 
       39:   rescue_from ActiveRecord::RecordNotFound do
    (byebug) n
    ∙ Redirected to http://(DELETED)/500.html
    Return value is: nil

    [32, 41] in /(DELETED)/application_controller.rb
       32:   rescue_from RedisUnavailableError do |exception|
       33:     byebug
       34:     Rails.logger.info "Redirecting to 500 page due to: #{exception.message}"
       35:     redirect_to '/500.html'
       36:     byebug
    => 37:   end
       38: 
       39:   rescue_from ActiveRecord::RecordNotFound do
       40:     render status: :not_found, plain: 'Not found'
       41:   end
    (byebug) n

    [51, 60] in /(DELETED)/rescuable.rb
       51:   def rescue_with_handler(exception, object: self, visited_exceptions: [])
       52:     visited_exceptions << exception
       53: 
       54:     if handler = handler_for_rescue(exception, object: object)
       55:       handler.call exception
    => 56:       exception
       57:     elsif exception
       58:       if visited_exceptions.include?(exception.cause)
       59:         nil
       60:       else
    (byebug) 

person Omnivium    schedule 17.09.2019    source источник


Ответы (1)


Итак, мой вопрос: есть ли способ заставить блок escape_from просто остановиться и не продолжать запускать что-либо еще после достижения определенной строки?

Да, просто назовите ключевое слово ruby ​​break.

break предназначен для полного выхода из блока. next предназначен для выхода из блока и перехода к следующей итерации (как в цикле while). Они очень полезны.

person sevensidedmarble    schedule 18.09.2019
comment
Я пробовал и break, и return безрезультатно :(. Кажется, что-то большее, чем кажется на первый взгляд, неявно скрыто под капотом с rescue_from. - person Omnivium; 18.09.2019
comment
Можете ли вы опубликовать весь исходный код? Немного сложно следить за следом byebug - person sevensidedmarble; 18.09.2019