2016-04-17 20 views
2

我遇到了一個問題,當PG失敗不同步(衆所周知的問題)(example)。我可以在沒有開始...結束的情況下在救援塊中重試嗎?

PG失敗不同步,id序列停止遞增並引發ActiveRecord::RecordNotUnique錯誤。

但是這裏提出的所有解決方案(我發現的都是)提出了一些手動解決方案 - 要麼在控制檯中執行一些操作,要麼運行自定義rake任務。

但是,我發現這種產品不太令人滿意:每次發生這種情況,用戶都會得到500,而有人管理服務器應該有效地節省一天的時間。 (根據測試數據出於某種原因,我可能會經常發生這種情況)。

所以我想補丁ActiveRecord基類趕上這個具體的錯誤和救援它。

我在控制器有時會使用這樣的邏輯:

class ApplicationController < ActionController::Base 

    rescue_from ActionController::ParameterMissing, ActiveRecord::RecordNotFound do |e| 
    # some logic here 
    end 
    end 

不過,在這裏我不需要重試。另外,我希望不要深入猴子補丁,例如,不要重寫Base創建方法。

所以我在想是這樣的:

module ActiveRecord 
    class Base 


     rescue ActiveRecord::RecordNotUnique => e 
     if e.message.include? '_pkey' 
      table =e.message.match(//) #regex to define table 
      ActiveRecord::Base.connection.reset_pk_sequence!(table) 
      retry 
     else 
      raise 
     end 
     end 
    end 

但它最有可能行不通,因爲我不知道,如果軌道/紅寶石就會明白到底是什麼要求重試。

有沒有解決方法?

P.S.對於沒有手動命令行命令並且沒有服務器用戶的序列整體問題沒有相關的解決方案也是值得讚賞的。

回答

0

要回答你問的問題,不。 rescue只能在begin..end塊或方法體內使用。

begin 
    bad_method 
rescue SomeException 
    retry 
end 

def some_method 
    bad_method 
rescue SomeException 
    retry 
end 

rescue_from只是因爲執行如何間接是在控制器中創建一個框架的輔助方法。

要回答你的問題真的問,當然。您可以用rescue/retry覆蓋create_or_update

module NonUniquePkeyRecovery 
    def create_or_update(*) 
    super 
    rescue ActiveRecord::RecordNotUnique => e 
    raise unless e.message.include? '_pkey' 
    self.class.connection.reset_pk_sequence!(self.class.table_name) 
    retry 
    end 
end 

ActiveSupport.on_load(:active_record) do 
    include NonUniquePkeyRecovery 
end 
相關問題