【问题标题】:Sinatra with a persistent variable具有持久变量的 Sinatra
【发布时间】:2014-01-30 06:31:45
【问题描述】:

我的 sinatra 应用程序必须解析一个 ~60MB 的 XML 文件。该文件几乎不会更改:在每晚的 cron 作业中,它会被另一个文件覆盖。

是否有技巧或方法将解析后的文件作为变量保存在内存中,以便我可以在传入请求时从中读取,但不必为每个传入请求一遍又一遍地解析它?

一些伪代码来说明我的问题。

get '/projects/:id'
  return @nokigiri_object.search("//projects/project[@id=#{params[:id]}]/name/text()")
end

post '/projects/update'
  if params[:token] == "s3cr3t"
    @nokogiri_object = reparse_the_xml_file
  end
end

我需要知道的是如何创建这样的@nokogiri_object,以便它在 Sinatra 运行时持续存在。这有可能吗?或者我需要一些存储空间吗?

【问题讨论】:

    标签: ruby sinatra scope


    【解决方案1】:

    你可以试试:

    configure do
      @@nokogiri_object = parse_xml
    end
    

    然后@@nokogiri_object 将在您的请求方法中可用。它是一个类变量而不是实例变量,但应该做你想做的。

    【讨论】:

    • @@var 是否可以跨会话和跨请求使用?假设用户 Anna 获取 /foo,@@var 被创建,那么当 Barry 访问 /foo 时,@@var 仍然被设置?
    • @berkes 是的,所有请求之间只有一个 @@var 共享
    • @berkes:拥有 60 mb 的变量不是很有效。应该更好地使用该公羊。我认为使用文件存储解析文件的解决方案要好得多。您甚至可以使用 Mini redis 数据库来存储文件最后一次解析的时间,甚至可以使用全局变量。但在内存中只存储日期,而不是实际文件。如果超过一天,则更新解析文件。如果它较低,则只需读取已解析的文件。这是我能想到的最有效的方法。
    • @@Nerian:你是对的。在第一次重构中,我将考虑 redis 或 mongodb。现在,我主要需要获得概念证明,看看我是否可以根据参数解析文件/文件(还有更多)。但是感谢您的警告和提示!
    • @Dominik 你的意思是每个request都会调用这个方法?您使用的是 shotgun 还是其他一些应用重新加载器?
    【解决方案2】:

    建议的解决方案给出警告

    警告:从顶层访问类变量

    可以使用类方法访问类变量,警告会消失

    require 'sinatra'
    
    class Cache
      @@count = 0
    
      def self.init()
        @@count = 0
      end
    
      def self.increment()
        @@count = @@count + 1
      end
    
      def self.count()
        return @@count
      end
    end
    
    configure do
      Cache::init()
    end
    
    get '/' do
      if Cache::count() == 0
        Cache::increment()
        "First time"
      else
        Cache::increment()
        "Another time #{Cache::count()}"
      end
    end
    

    【讨论】:

      【解决方案3】:

      两种选择:

      • 将解析后的文件保存到一个新文件并始终读取该文件。

      您可以在文件中保存 - 序列化 - 带有两个键的哈希:'last-modified' 和 'data'。

      'last-modified' 值是一个日期,如果当天是今天,您可以签入每个请求。如果不是今天,则下载、解析和存储一个新文件并使用今天的日期。

      “数据”值是解析后的文件。

      这样你只解析一次,有点像缓存。

      • 将解析后的文件保存到 NoSQL 数据库,例如 redis。

      【讨论】:

      • 我一直在考虑 redis、memcached 甚至 mongoDB。仍在比赛中,但我宁愿尽可能保持非常简单:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-30
      相关资源
      最近更新 更多