使用的解决方案代替$ global变量?

时间:2013-08-06 19:47:29

标签: ruby-on-rails ruby-on-rails-3 caching global-variables

我有一个缓存的对象需要相当长的时间来计算(~30秒)。我每24小时重新计算一次这个对象,如果发生这种情况,有时用户如果恰好在同一时间就会遇到超时。我正在缓存的对象目前是这样的:

  def matrix    
    Rails.cache.fetch(["matrix"], expires_in: 24.hours) do
      # Math
    end
  end

我想做的是附加一个版本。这样我就可以用不同的方法在后台计算一个新的“矩阵”...

  def rewrite_matrix
    new_version = DateTime.now.to_s

    Rails.cache.fetch(["matrix", new_version], expires_in: 24.hours) do
      # Math
    end

    $matrix_version = new_version # This feels like a faux pas.
  end

然后将我的矩阵方法更改为......

 def matrix
    $matrix_version ||= DateTime.now.to_s

    Rails.cache.fetch(["matrix", $matrix_version], expires_in: 24.hours) do
      # Math
    end
  end

我一直在阅读Ruby / Rails中的全局变量,并且一切都说他们不应该被触及?这个$ matrix_version变量是否可以在其他进程和其他用户中使用?无论如何,我希望有一个关于如何在后台解决或创建新缓存版本的想法,然后在它完成计算和存储时开始使用它。

2 个答案:

答案 0 :(得分:1)

想到的第一个想法是先进行计算:

def matrix    
  Rails.cache.fetch('matrix') do
    calculate_matrix
  end
end

def rewrite_matrix
  new_version = calculate_matrix

  Rails.cache.delete('matrix')
  Rails.cache.fetch('matrix') do
    new_version
  end

end

def calculate_matrix
  #Math
end

如果你每24小时(在一个单独的过程中)调用rewrite_matrix,它应首先执行工作,然后更新缓存,这将在用户工作时保持可用。

答案 1 :(得分:1)

如果需要24小时,我建议不要使缓存过期。相反,只需在准备好新版本时替换它。

class YourModel
  def matrix    
    Rails.cache.fetch(["matrix"]) do
      math
    end
  end

  def self.recalculate_matrix
    Rails.cache.set(["matrix"]) do
      math
    end
  end
end

然后,也许使用whenever gem

every 1.day, :at => '4:30 am' do
  runner "MyModel.recalculate_matrix"
end