【发布时间】:2016-08-30 14:28:34
【问题描述】:
我有几个需要连接的第三方 API,因此我为单例行为定义了一个抽象模块,以及特定的连接器单例实例。
我的问题:每次 Rails 服务器崩溃(500 错误,本地主机),似乎我丢失了连接器的 @client 实例变量
module ServiceConnector
extend ActiveSupport::Concern
included do
include Singleton
@activated = false
@activation_attempt = false
@client = nil
def client
@client
end
def service_name
self.class.name.gsub('Connector', '')
end
def activate
@activation_attempt = true
if credentials_present?
@client = service_client
@activated = true
end
status_report
end
class MyConnector
include ServiceConnector
@app_id = nil
@api_key = nil
def credentials_present?
@app_id.present? and @api_key.present?
end
def service_client
::MyService::Client.new(
app_id: @app_id,
api_key: @api_key
)
end
def set_credentials(id, key)
@app_id = id
@api_key = key
end
我在 Rails 初始化程序中初始化我的单例
#config/initializers/my_connectors.rb
my_service = MyConnector.instance
if my_service_should_be_activated?
my_service.set_credentials(
Rails.application.secrets.app_id,
Rails.application.secrets.api_key
)
my_service.activate
end
def some_action_on_client
client.push_event(...)
end
事件集
rails s
...
# MyConnector client Online and working fine
...
# error 500 on some controller
# (next client request)
# MyConnector @client variable mysteriously set to nil
【问题讨论】:
-
您是否尝试过使用
Rails.logger来查看它是否被正确初始化?崩溃与进程重启没有什么不同。应该重新初始化单例。 -
每次重新加载应用后都会发生这种情况吗?当 Rails 重新加载应用程序代码时,它不会重新执行初始化程序。发生的情况是您的类已定义,它们包含关注点,然后将
@client设置为 nil。但是,初始化程序没有运行,所以@client永远不会再次分配。我怀疑每次代码更改后都会发生这种情况,而您只是在触发错误后才注意到它。 -
啊,感谢您为我指明了正确的方向,这很可能是发生的事情。那你会怎么处理呢?我将使用不同的单例模式变体发布解决方案,但我会很好奇/接受解释我应该如何编写在这些情况下正确重新加载的服务的答案。
标签: ruby-on-rails ruby singleton ruby-on-rails-5 activesupport