ruby-on-rails - 在 Rails 中,有没有办法从rescue_from 中“短路”?
问题描述
我正在尝试为 Rails 中的 Redis 进行用户友好的故障安全恢复。我正在使用内置redis_cache_store
并已reconnect_attempts
设置,但我想在 Redis 仍然关闭的情况下将用户发送到自定义错误页面,而不是让他们卡在不知道发生了什么的无响应页面上。
我尝试的是通过重新引发一种新型错误来猴子修补failsafe
方法,然后我有我的捕获和静态 500 页面。RedisCacheStore
RedisUnavailableError
application_controller
redirect_to
这个问题的原因是我希望我的应用程序在重定向后停止。在下面的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)
解决方案
所以我的问题是:有没有办法让rescue_from块在到达某条线后停止而不继续触发其他任何东西?
是的,只需调用 rubybreak
关键字。
break
是为了完全打破一个块。next
用于跳出块并继续进行下一次迭代(例如在while循环中)。它们非常有用。
推荐阅读
- ansible - 以非 root 用户身份运行 Ansible 命令不起作用
- azure-active-directory - Azure AD Microsoft Identity Web OpenIdConnectEvents - 如何在注销期间访问来自用户令牌的可选声明
- html - 如何更改导航栏中项目边框的形状
- python - python多客户端聊天不起作用
- jenkins - Ansible 读取 Jenkins 布尔参数
- python - 第一个程序不会打印价格
- springdoc - 具有多个 api-docs 的 Springdoc
- github - 切换到使用子键后,如何在 GitHub 上验证提交?
- python - 以 '\x020' 形式表示整数 > 31 的十六进制形式
- javascript - Angular HttpClient在带有句点的路径上添加斜杠