【问题标题】:Where is the correct place to initialize BigDecimal limit when using Puma使用 Puma 时初始化 BigDecimal 限制的正确位置在哪里
【发布时间】:2023-03-17 08:21:01
【问题描述】:

我有一个 Rails 初始化程序,用于设置 Big Decimal 的限制

BigDecimal.limit(20)

这被执行并且似乎正确地设置了限制。

但是当一个网络请求进来时(我使用的是 Puma),处理请求的线程上似乎没有设置限制。限制设置为默认值 0。

我应该在其他地方设置限制吗?

如果你想重现:

创建一个全新的 Rails 应用并添加一个设置限制的初始化程序

BigDecimal.limit(20)
puts "*** Set #{BigDecimal.limit}"

在你的应用控制器中添加

before_action :check_big_decimal

def check_big_decimal
  puts "***request #{BigDecimal.limit}"
end

启动您的服务器,刷新页面并发出请求

您应该看到它设置为 20,但是当请求进来时它又回到 0。

【问题讨论】:

  • 前几天我在看这个。我认为问题在于您在不同的线程(Rails 主线程)中设置了限制。该线程中不处理任何请求,因此您永远看不到限制。解决这个问题的方法可以是使用在每个请求上设置它的中间件或 ApplicationController 中的 before_action。老实说,我认为你不应该这样做,因为它有很大的缺点(例如,你的任务中没有设置限制)。
  • 一般来说,您可能需要重新考虑是否要首先执行此操作。有一种方法BigDecimal#save_limit[1] 可用于仅设置块内的限制。将关键业务逻辑包装在这样的块中可能是最佳实践。主要好处之一是读者 100% 清楚我们正在处理与默认精度不同的精度。 [1]:ruby-doc.org/stdlib-2.5.1/libdoc/bigdecimal/rdoc/…

标签: ruby-on-rails puma


【解决方案1】:

我得到了 Rails 的答复community

基本要点是:

这是因为 Ruby 将 BigDecimal 限制存储在线程本地存储中。 当例如Puma 启动新线程处理请求,新线程无法访问初始线程中设置的 BigDecimal 限制。

【讨论】:

    【解决方案2】:

    一个 hacky 且不推荐的方法是猴子修补课程。您可以在初始化程序中添加它

    class BigDecimal
      def self.limit(val = 25)
        25
      end
    end
    

    问题是,你真的想在所有地方都限制为 25 个吗?如果是,那么您可以将其作为最后的手段尝试,因为我不确定硬编码该值(并完全覆盖该方法)的副作用

    【讨论】:

    • 您的建议让我想到了覆盖该属性以查看是否可以知道它在哪里被重置...我可以看到它在设置时被调用,但它从未在其他任何地方被调用!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2014-04-27
    • 2015-06-27
    相关资源
    最近更新 更多