gpt4 book ai didi

ruby-on-rails - Rails 控制台 - 重新加载!模块中的第三方服务

转载 作者:数据小太阳 更新时间:2023-10-29 08:11:18 26 4
gpt4 key购买 nike

我的应用已连接到某些第三方 API。

我有几个 APIconnector 模块单例,它们只在应用程序启动时初始化一次(初始化意味着客户端使用从 secret 中检索到的凭据实例化一次)

当我重新加载!我的控制台中的应用程序时,我失去了那些服务,我必须退出并从头开始重新启动控制台。

基本上我所有的连接器都包含一个像这样的 ServiceConnector 模块

module ServiceConnector
extend ActiveSupport::Concern

included do
@activated = false
@activation_attempt = false
@client = nil

attr_reader :client, :activated

def self.client
@client ||= service_client
end

def self.service_name
name.gsub('Connector', '')
end

def self.activate
@activation_attempt = true
if credentials_present?
@client = service_client
@activated = true
end
end

这是一个服务实现的例子

module My Connector
include ServiceConnector

@app_id = nil
@api_key = nil

def self.set_credentials(id, key)
@app_id = id
@api_key = key
end

def self.credentials_present?
@app_id.present? and @api_key.present?
end

def self.service_client
::SomeAPI::Client.new(
app_id: @app_id,
api_key: @api_key
)
end
end

我使用这种模式让我在 Rails 之外重用那些服务(例如 Capistrano、没有 Rails 的 worker 等)。在 Rails 中,我会以这种方式加载服务

# config/initializers/my_service.rb
if my_service_should_be_activated?
my_service.set_credentials(
Rails.application.secrets.my_service_app_id,
Rails.application.secrets.my_service_app_key
)
my_service.activate
end

我猜想执行 reload! 似乎清除了我所有的实例变量,包括 @client@app_id@api_key.

是否可以添加在 reload! 之后执行的代码?就我而言,我需要重新运行初始化程序。或者有没有办法确保我的服务的实例变量不会在重新加载时被清除! ?

最佳答案

所以我想出了一个涉及两个初始化器的解决方案

首先,一个 000_initializer 将报告哪些 secret 已成功加载

module SecretChecker
module_function

# Return true if all secrets are present
def secrets?(secret_list, under:)
secret_root = Rails.application.secrets
if under
if under.is_a?(Array)
secret_root = secret_root.public_send(under.shift)&.dig(*under.map(&:to_s))
else
secret_root = secret_root.public_send(under)
end
secret_list.map do |secret|
secret_root&.dig(secret.to_s).present?
end
else
secret_list.map do |secret|
secret_root&.public_send(secret.to_s).present?
end
end.reduce(:&)
end

def check_secrets(theme, secret_list, under: nil)
return if secrets?(secret_list, under: under)
message = "WARNING - Missing secrets for #{theme} - #{yield}"
puts message and Rails.logger.warn(message)
end
end

SecretChecker.check_secrets('Slack', %i[martine], under: [:slack, :webhooks]) do
'Slack Notifications will not work'
end

SecretChecker.check_secrets('MongoDB', %i[user password], under: :mongodb) do
'No Database Connection if auth is activated'
end

然后,使用 ActiveSupport::Reloader 重新加载服务的模块(以 Slack 为特色的示例)

# config/initializers/0_service_activation.rb
module ServiceActivation
def self.with_reload
ActiveSupport::Reloader.to_prepare do
yield
end
end

module Slack
def self.service
::SlackConnector
end

def self.should_be_activated?
Rails.env.production? ||
Rails.env.staging? ||
(Rails.env.development? && ENV['ENABLE_SLACK'] == 'true')
end

def self.activate
slack = service
slack.webhook = Rails.application.secrets.slack&.dig('webhooks', 'my_webhook')
ENV['SLACK_INTERCEPT_CHANNEL'].try do |channel|
slack.intercept_channel = channel if channel.present?
end
slack.activate
slack
end
end
end

[
...,
ServiceActivation::Slack
] .each do |activator|
ServiceActivation.with_reload do
activator.activate if activator.should_be_activated?
activator.service.status_report
end
end

关于ruby-on-rails - Rails 控制台 - 重新加载!模块中的第三方服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40424383/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com