2016-08-30 39 views
1

我有幾個第三方API需要連接,所以我爲Singleton行爲定義了一個抽象模塊,並且定義了特定的連接器單例。Rails單機客戶端在Rails崩潰後丟失

我的問題:每次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 
+1

你試過使用'Rails.logger'來查看它是否正確初始化?崩潰與進程重啓沒有區別。單身人士應該重新初始化。 – tadman

+1

每次重新加載應用程序後都會發生這種情況嗎?當Rails重新加載應用程序代碼時,它不會重新執行初始化程序。會發生什麼是您的類被定義,它們包括關注,然後他們將'@ client'設置爲零。但是,初始化程序沒有運行,所以'@ client'永遠不會再被分配。我懷疑在每次代碼更改後都會發生這種情況,並且在觸發錯誤後您只會注意到它。 –

+0

啊感謝您指點我正確的方向,這很可能是發生了什麼事情。那麼你將如何處理?我將發佈一個使用不同單例模式變體的解決方案,但我會很好奇/接受解釋我應該如何編寫一個在這些情況下正確重裝的服務的解答。 –

回答

0

的我結束了重寫代碼全光照G作爲描述there

基本上模塊Singleton模式,它由只使用一個模塊,模塊類變量

module ServiceConnector 
    extend ActiveSupport::Concern 

    class ConnectorError < Exception 
    end 

    class ActivationError < ConnectorError 
    end 

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

    # all other methods as class methods with self. 

class MyConnector 
    include ServiceConnector 

    @@some_credential = nil 

    def self.set_credentials(cred) 
    @@some_credential = cred 
    end 

    def self.credentials_present? 
    @@some_credential != nil 
    end 

    def self.service_client 
    ::MyService.new(
     @@some_credential, 
    ) 
    end 

    # also all other methods with self. 

和訪問便直接與MyConnector.some_method,而不是調用.instance第一