簡體   English   中英

我可以在沒有開始......結束的情況下將重試放在救援塊中嗎?

[英]Can I put retry in rescue block without begin ... end?

我遇到了一個問題,當 PG 不同步時(眾所周知的問題)( 示例)。

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

但它很可能不起作用,因為我不確定 Rails/Ruby 是否會理解它究竟要求重試什么。

有什么解決辦法嗎?

PS 對於整個序列問題的非相關解決方案,在沒有手動命令行命令的情況下也可以工作並且沒有服務的用戶也很受歡迎。

要回答你問的問題,不。 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM