Sinatra with a persistent variable

2019-02-06 06:03发布

My sinatra app has to parse a ~60MB XML-file. This file hardly ever changes: on a nightly cron job, It is overwritten with another one.

Are there tricks or ways to keep the parsed file in memory, as a variable, so that I can read from it on incoming requests, but not have to parse it over and over for each incoming request?

Some Pseudocode to illustrate my problem.

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

What I need to know, is how to create such a @nokogiri_object so that it persists when Sinatra runs. Is that possible at all? Or do I need some storage for that?

3条回答
该账号已被封号
2楼-- · 2019-02-06 06:52

You could try:

configure do
  @@nokogiri_object = parse_xml
end

Then @@nokogiri_object will be available in your request methods. It's a class variable rather than an instance variable, but should do what you want.

查看更多
我只想做你的唯一
3楼-- · 2019-02-06 06:58

Two options:

  • Save the parsed file to a new file and always read that one.

You can save in a file – serialize - a hash with two keys: 'last-modified' and 'data'.

The 'last-modified' value is a date and you check in every request if that day is today. If it is not today then a new file is downloaded, parsed and stored with today's date.

The 'data' value is the parsed file.

That way you parse just once time, sort of a cache.

  • Save the parsed file to a NoSQL database, for example redis.
查看更多
冷血范
4楼-- · 2019-02-06 07:03

The proposed solution gives a warning

warning: class variable access from toplevel

You can use a class method to access the class variable and the warning will disappear

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
查看更多
登录 后发表回答