简体   繁体   English

每个请求在生产中使用TimeCop

[英]TimeCop in production on a per-request basis

I've got a rails app using MRI ruby and Unicorn as the app server. 我有一个使用MRI ruby​​和Unicorn作为应用程序服务器的Rails应用程序。 The app provides a 10-week fitness program, and I've built a feature for people logged in as admins to be able to "time travel" to different weeks in the program. 该应用程序提供了一个为期10周的健身计划,并且我为以管理员身份登录的用户构建了一项功能,使其能够“定时旅行”到计划中的不同星期。 Basically, it just sets a session variable with the date they're "time travelled" to, and, each request, it time-travels to that point at the beginning, then returns at the end. 基本上,它只是将会话变量设置为带有其“时间行进”日期的日期,并且每个请求都在开始时移动到该点,然后在结束时返回。 The code is below. 代码如下。

I'd limited the feature non-production environments, out of fear that one person's time-travelling may affect other users (since TimeCop monkey patches core classes). 由于担心一个人的时间旅行可能会影响其他用户(因为TimeCop猴子修补了核心类),因此我限制了功能非生产环境。 But, given MRI isn't really multi-threaded I'm now thinking that's an irrational fear, and that there should be no danger of using the "time travel" feature in production. 但是,由于MRI并不是真正的多线程,所以我现在认为这是一种非理性的恐惧,并且在生产中不应该使用“时间旅行”功能。

For the duration within which a single request is processed (and therefore the time for which the core classes are monkey patched by TimeCop if the user is using "time travel"), there should be no possibility that any other request gets run on the same ruby process. 在处理单个请求的持续时间内(因此,如果用户使用“时间旅行”,则TimeCop对核心类进行猴子修补的时间),任何其他请求都不应在同一时间运行红宝石工艺。

Is this correct? 这个对吗? Or can other user's requests be affected by TimeCop's changes to the core classes in a way I'm not aware of? 还是其他用户的请求会以我不知道的方式受到TimeCop对核心类的更改的影响?

The code I'm using is as follows: 我使用的代码如下:

module TimeTravelFilters
  extend ActiveSupport::Concern

  included do
    if Rails.env.development? || Rails.env.staging?
      around_action :time_travel_for_request
    end
  end

  def time_travel_for_request
    time_travel
    yield
    time_travel_return
  end

  def time_travel
    if session[:timetravel_to_date]
      Timecop.travel(session[:timetravel_to_date])
    end
  end

  def time_travel_return
    Timecop.return
  end
end

MRI's global interpreter lock does mean that 2 threads won't execute concurrently, but the granularity of that is much much smaller than the processing of one request. MRI的全局解释器锁定确实意味着不会同时执行2个线程,但是它的粒度比处理一个请求小得多。

As it happens unicorn doesn't use threads for concurrency so you'd be ok, but the day you switched to another server (eg puma) then you'd be in for a nasty surprise. 碰巧的是,独角兽不使用线程进行并发,所以您会没事的,但是当您切换到另一台服务器(例如puma)的那一天,您会感到非常讨厌。

This would also affect things like data in logs, created_at/updated_at timestamps for anything updated and so on. 这也会影响诸如日志中的数据,created_at / updated_at时间戳等更新内容之类的内容。 It might also affect monitoring data gathered by services like newrelic, airbrake etc if you use those. 如果使用这些服务,它也可能会影响由诸如newrelic,airbrake等服务收集的监视数据。 Another example of something that might seem completely unrelated is api requests to AWS: the signature that verifies these requests includes a timestamp, and they will fail if you're out of sync by more than a few minutes. 另一个似乎完全不相关的示例是对AWS的api请求:验证这些请求的签名包括时间戳,如果您在几分钟以上不同步,它们将失败。 There is just too much code (much of which you don't control) that assumes that Time.now is accurate. 太多的代码(其中很多是您无法控制的)都认为Time.now是准确的。

You'd be much better off identifying those bits of code that implicitly use the current Time and changing them to allow the desired time to be passed as an argument. 最好识别那些隐式使用当前时间的代码位,并对其进行更改以允许将所需的时间作为参数传递。

As an aside I think your code would leave the altered time in place if the controller raised an exception 顺便说一句,我认为如果控制器引发异常,您的代码将保留更改的时间

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM