Я пытаюсь сделать удобное и безопасное восстановление для 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)